11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
48331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov * Copyright (c) 2001-2007 Anton Altaparmakov
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002 Richard Russon
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program/include file is free software; you can redistribute it and/or
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License as published
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the Free Software Foundation; either version 2 of the License, or
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program/include file is distributed in the hope that it will be
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program (in the main directory of the Linux-NTFS
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * distribution in the file COPYING); if not, write to the Free Software
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h>
245a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dir.h"
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aops.h"
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "attrib.h"
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mft.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "debug.h"
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ntfs.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The little endian Unicode string $I30 as a global constant.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3663cd885426872254e82dac2d9e13ea4f720c21dcHarvey Harrisonntfschar I30[5] = { cpu_to_le16('$'), cpu_to_le16('I'),
3763cd885426872254e82dac2d9e13ea4f720c21dcHarvey Harrison		cpu_to_le16('3'),	cpu_to_le16('0'), 0 };
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_lookup_inode_by_name - find an inode in a directory given its name
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dir_ni:	ntfs inode of the directory in which to search for the name
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @uname:	Unicode name for which to search in the directory
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @uname_len:	length of the name @uname in Unicode characters
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @res:	return the found file name if necessary (see below)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Look for an inode with name @uname in the directory with inode @dir_ni.
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_lookup_inode_by_name() walks the contents of the directory looking for
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Unicode name. If the name is found in the directory, the corresponding
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is a 64-bit number containing the sequence number.
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On error, a negative value is returned corresponding to the error code. In
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular if the inode is not found -ENOENT is returned. Note that you
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can't just check the return value for being negative, you have to check the
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inode number for being negative which you can extract using MREC(return
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * value).
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note, @uname_len does not include the (optional) terminating NULL character.
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note, we look for a case sensitive match first but we also look for a case
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * insensitive match at the same time. If we find a case insensitive match, we
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * save that for the case that we don't find an exact match, where we return
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the case insensitive match and setup @res (which we allocate!) with the mft
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference, the file name type, length and with a copy of the little endian
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Unicode file name itself. If we match a file name which is in the DOS name
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * space, we only return the mft reference and file name type in @res.
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_lookup() then uses this to find the long file name in the inode itself.
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is to avoid polluting the dcache with short file names. We want them to
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * work but we don't care for how quickly one can access them. This also fixes
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the dcache aliasing issues.
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
721b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * Locking:  - Caller must hold i_mutex on the directory.
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	     - Each page cache page in the index allocation mapping must be
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       locked whilst being accessed otherwise we may find a corrupt
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       page due to it being under ->writepage at the moment which
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       applies the mst protection fixups before writing out and then
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       removes them again after the write is complete after which it
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       unlocks the page.
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const int uname_len, ntfs_name **res)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol = dir_ni->vol;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block *sb = vol->sb;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MFT_RECORD *m;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ROOT *ir;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ENTRY *ie;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ALLOCATION *ia;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *index_end;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 mref;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_search_ctx *ctx;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, rc;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VCN vcn, old_vcn;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct address_space *ia_mapping;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *kaddr;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_name *name = NULL;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!S_ISDIR(VFS_I(dir_ni)->i_mode));
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(NInoAttr(dir_ni));
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get hold of the mft record for the directory. */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = map_mft_record(dir_ni);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(m)) {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-PTR_ERR(m));
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_MREF(PTR_ERR(m));
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ctx)) {
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the index root attribute in the mft record. */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0, ctx);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err)) {
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err == -ENOENT) {
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index root attribute missing in "
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"directory inode 0x%lx.",
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -EIO;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get to the index root value (it's been verified in read_inode). */
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ir = (INDEX_ROOT*)((u8*)ctx->attr +
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le16_to_cpu(ctx->attr->data.resident.value_offset));
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry. */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ir->index +
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ir->index.entries_offset));
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Loop until we exceed valid memory (corruption case) or until we
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry.
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds checks. */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end)
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto dir_err_out;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The last entry cannot contain a name. It can however contain
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * a pointer to a child node in the B+tree so we just break out.
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We perform a case sensitive comparison and if that matches
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we are done and return the mft reference of the inode (i.e.
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the inode number together with the sequence number for
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * consistency checking). We convert it to cpu format before
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * returning.
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ntfs_are_names_equal(uname, uname_len,
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length,
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len)) {
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound_it:
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * We have a perfect match, so we don't need to care
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * about having matched imperfectly before, so we can
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * free name and set *res to NULL.
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * However, if the perfect match is a short file name,
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * we need to signal this through *res, so that
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ntfs_lookup() can fix dcache aliasing issues.
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * As an optimization we just reuse an existing
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * allocation of *res.
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ie->key.file_name.file_name_type == FILE_NAME_DOS) {
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!name) {
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					name = kmalloc(sizeof(ntfs_name),
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							GFP_NOFS);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!name) {
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						err = -ENOMEM;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto err_out;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->mref = le64_to_cpu(
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						ie->data.dir.indexed_file);
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->type = FILE_NAME_DOS;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = 0;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*res = name;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
186251c8427c9c418674fc3c04a11de95dc3661b560Jesper Juhl				kfree(name);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*res = NULL;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mref = le64_to_cpu(ie->data.dir.indexed_file);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_attr_put_search_ctx(ctx);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unmap_mft_record(dir_ni);
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mref;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For a case insensitive mount, we also perform a case
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * insensitive comparison (provided the file name is not in the
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * POSIX namespace). If the comparison matches, and the name is
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * in the WIN32 namespace, we cache the filename in *res so
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * that the caller, ntfs_lookup(), can work on it. If the
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * comparison matches, and the name is in the DOS namespace, we
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * only cache the mft reference and the file name type (we set
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the name length to zero for simplicity).
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!NVolCaseSensitive(vol) &&
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_type &&
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_are_names_equal(uname, uname_len,
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length,
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len)) {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int name_size = sizeof(ntfs_name);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 type = ie->key.file_name.file_name_type;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 len = ie->key.file_name.file_name_length;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Only one case insensitive matching name allowed. */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (name) {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_error(sb, "Found already allocated name "
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"in phase 1. Please run chkdsk "
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"and if that doesn't find any "
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"errors please report you saw "
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"this message to "
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"linux-ntfs-dev@lists."
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"sourceforge.net.");
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto dir_err_out;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (type != FILE_NAME_DOS)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name_size += len * sizeof(ntfschar);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name = kmalloc(name_size, GFP_NOFS);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!name) {
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -ENOMEM;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_out;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name->mref = le64_to_cpu(ie->data.dir.indexed_file);
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name->type = type;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (type != FILE_NAME_DOS) {
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = len;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(name->name, ie->key.file_name.file_name,
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						len * sizeof(ntfschar));
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = 0;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*res = name;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Not a perfect match, need to do full blown collation so we
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * know which way in the B+tree we have to go.
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If uname collates before the name of the current entry, there
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is definitely no such name in this index but we might need to
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * descend into the B+tree so we just break out of the loop.
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The names are not equal, continue the search. */
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Names match with case insensitive comparison, now try the
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive comparison, which is required for proper
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * collation.
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Perfect match, this will never happen as the
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_are_names_equal() call will have gotten a match but we
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * still treat it correctly.
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto found_it;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We have finished with this index without success. Check for the
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * presence of a child node and if not present return -ENOENT, unless
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we have got a matching name cached in name in which case return the
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mft reference associated with it.
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(ie->flags & INDEX_ENTRY_NODE)) {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (name) {
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_attr_put_search_ctx(ctx);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unmap_mft_record(dir_ni);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return name->mref;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Entry not found.");
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOENT;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} /* Child node present, descend into it. */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Consistency check: Verify that an index allocation exists. */
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoIndexAllocPresent(dir_ni)) {
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "No index allocation attribute but index entry "
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"requires one. Directory inode 0x%lx is "
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"corrupt or driver bug.", dir_ni->mft_no);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the starting vcn of the index_block holding the child node. */
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia_mapping = VFS_I(dir_ni)->i_mapping;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We are done with the index root and the mft record. Release them,
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * otherwise we deadlock with ntfs_map_page().
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_put_search_ctx(ctx);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unmap_mft_record(dir_ni);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = NULL;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = NULL;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdescend_into_child_node:
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Convert vcn to index into the index allocation attribute in units
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * of PAGE_CACHE_SIZE and map the page cache page, reading it from
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * disk if necessary.
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page = ntfs_map_page(ia_mapping, vcn <<
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(page)) {
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Failed to map directory index page, error %ld.",
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-PTR_ERR(page));
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(page);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lock_page(page);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kaddr = (u8*)page_address(page);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfast_descend_into_child_node:
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get to the index allocation block. */
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia = (INDEX_ALLOCATION*)(kaddr + ((vcn <<
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK));
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Bounds checks. */
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx or driver bug.", dir_ni->mft_no);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Catch multi sector transfer fixup errors. */
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ntfs_is_indx_record(ia->magic))) {
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Directory index record with vcn 0x%llx is "
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"corrupt.  Corrupt inode 0x%lx.  Run chkdsk.",
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is "
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"different from expected VCN (0x%llx). "
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Directory inode 0x%lx is corrupt or driver "
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"bug.", (unsigned long long)
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sle64_to_cpu(ia->index_block_vcn),
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.block_size) {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx has a size (%u) differing from the "
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"directory specified size (%u). Directory "
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode is corrupt or driver bug.",
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le32_to_cpu(ia->index.allocated_size) + 0x18,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dir_ni->itype.index.block_size);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)ia + dir_ni->itype.index.block_size;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (index_end > kaddr + PAGE_CACHE_SIZE) {
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx crosses page boundary. Impossible! "
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Cannot access! This is probably a bug in the "
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"driver.", (unsigned long long)vcn,
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dir_ni->mft_no);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (index_end > (u8*)ia + dir_ni->itype.index.block_size) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx exceeds maximum size.",
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry. */
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ia->index +
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ia->index.entries_offset));
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Iterate similar to above big loop but applied to index buffer, thus
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * loop until we exceed valid memory (corruption case) or until we
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry.
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds check. */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((u8*)ie < (u8*)ia || (u8*)ie +
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end) {
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index entry out of bounds in "
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"directory inode 0x%lx.",
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto unm_err_out;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The last entry cannot contain a name. It can however contain
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * a pointer to a child node in the B+tree so we just break out.
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We perform a case sensitive comparison and if that matches
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we are done and return the mft reference of the inode (i.e.
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the inode number together with the sequence number for
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * consistency checking). We convert it to cpu format before
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * returning.
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ntfs_are_names_equal(uname, uname_len,
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length,
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len)) {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound_it2:
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * We have a perfect match, so we don't need to care
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * about having matched imperfectly before, so we can
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * free name and set *res to NULL.
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * However, if the perfect match is a short file name,
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * we need to signal this through *res, so that
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ntfs_lookup() can fix dcache aliasing issues.
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * As an optimization we just reuse an existing
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * allocation of *res.
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ie->key.file_name.file_name_type == FILE_NAME_DOS) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!name) {
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					name = kmalloc(sizeof(ntfs_name),
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							GFP_NOFS);
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!name) {
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						err = -ENOMEM;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto unm_err_out;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->mref = le64_to_cpu(
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						ie->data.dir.indexed_file);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->type = FILE_NAME_DOS;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = 0;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*res = name;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
446251c8427c9c418674fc3c04a11de95dc3661b560Jesper Juhl				kfree(name);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*res = NULL;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mref = le64_to_cpu(ie->data.dir.indexed_file);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unlock_page(page);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(page);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mref;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For a case insensitive mount, we also perform a case
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * insensitive comparison (provided the file name is not in the
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * POSIX namespace). If the comparison matches, and the name is
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * in the WIN32 namespace, we cache the filename in *res so
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * that the caller, ntfs_lookup(), can work on it. If the
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * comparison matches, and the name is in the DOS namespace, we
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * only cache the mft reference and the file name type (we set
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the name length to zero for simplicity).
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!NVolCaseSensitive(vol) &&
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_type &&
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_are_names_equal(uname, uname_len,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length,
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len)) {
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int name_size = sizeof(ntfs_name);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 type = ie->key.file_name.file_name_type;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 len = ie->key.file_name.file_name_length;
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Only one case insensitive matching name allowed. */
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (name) {
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_error(sb, "Found already allocated name "
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"in phase 2. Please run chkdsk "
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"and if that doesn't find any "
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"errors please report you saw "
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"this message to "
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"linux-ntfs-dev@lists."
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"sourceforge.net.");
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				unlock_page(page);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_unmap_page(page);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto dir_err_out;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (type != FILE_NAME_DOS)
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name_size += len * sizeof(ntfschar);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name = kmalloc(name_size, GFP_NOFS);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!name) {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -ENOMEM;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto unm_err_out;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name->mref = le64_to_cpu(ie->data.dir.indexed_file);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			name->type = type;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (type != FILE_NAME_DOS) {
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = len;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(name->name, ie->key.file_name.file_name,
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						len * sizeof(ntfschar));
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				name->len = 0;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*res = name;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Not a perfect match, need to do full blown collation so we
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * know which way in the B+tree we have to go.
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If uname collates before the name of the current entry, there
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is definitely no such name in this index but we might need to
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * descend into the B+tree so we just break out of the loop.
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The names are not equal, continue the search. */
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Names match with case insensitive comparison, now try the
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive comparison, which is required for proper
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * collation.
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Perfect match, this will never happen as the
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_are_names_equal() call will have gotten a match but we
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * still treat it correctly.
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto found_it2;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We have finished with this index buffer without success. Check for
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the presence of a child node.
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ie->flags & INDEX_ENTRY_NODE) {
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index entry with child node found in "
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"a leaf node in directory inode 0x%lx.",
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto unm_err_out;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Child node present, descend into it. */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_vcn = vcn;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vcn = sle64_to_cpup((sle64*)((u8*)ie +
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le16_to_cpu(ie->length) - 8));
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vcn >= 0) {
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* If vcn is in the same page cache page as old_vcn we
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * recycle the mapped page. */
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (old_vcn << vol->cluster_size_bits >>
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PAGE_CACHE_SHIFT == vcn <<
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vol->cluster_size_bits >>
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PAGE_CACHE_SHIFT)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fast_descend_into_child_node;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unlock_page(page);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(page);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto descend_into_child_node;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Negative child node vcn in directory inode "
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx.", dir_ni->mft_no);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * No child node present, return -ENOENT, unless we have got a matching
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * name cached in name in which case return the mft reference
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * associated with it.
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (name) {
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_unmap_page(page);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return name->mref;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entry not found.");
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = -ENOENT;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunm_err_out:
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_unmap_page(page);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out:
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!err)
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ctx)
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_attr_put_search_ctx(ctx);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (m)
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unmap_mft_record(dir_ni);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (name) {
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(name);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*res = NULL;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_MREF(err);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdir_err_out:
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_error(sb, "Corrupt directory.  Aborting lookup.");
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto err_out;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// TODO: (AIA)
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// The algorithm embedded in this code will be required for the time when we
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// want to support adding of entries to directories, where we require correct
611c002f42543e155dd2b5b5039ea2637ab26c82513Anton Altaparmakov// collation of file names in order not to cause corruption of the filesystem.
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_lookup_inode_by_name - find an inode in a directory given its name
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dir_ni:	ntfs inode of the directory in which to search for the name
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @uname:	Unicode name for which to search in the directory
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @uname_len:	length of the name @uname in Unicode characters
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Look for an inode with name @uname in the directory with inode @dir_ni.
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_lookup_inode_by_name() walks the contents of the directory looking for
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Unicode name. If the name is found in the directory, the corresponding
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is a 64-bit number containing the sequence number.
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On error, a negative value is returned corresponding to the error code. In
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular if the inode is not found -ENOENT is returned. Note that you
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can't just check the return value for being negative, you have to check the
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inode number for being negative which you can extract using MREC(return
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * value).
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note, @uname_len does not include the (optional) terminating NULL character.
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const int uname_len)
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol = dir_ni->vol;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block *sb = vol->sb;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MFT_RECORD *m;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ROOT *ir;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ENTRY *ie;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ALLOCATION *ia;
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *index_end;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 mref;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_search_ctx *ctx;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, rc;
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IGNORE_CASE_BOOL ic;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VCN vcn, old_vcn;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct address_space *ia_mapping;
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *kaddr;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get hold of the mft record for the directory. */
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = map_mft_record(dir_ni);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(m)) {
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-PTR_ERR(m));
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_MREF(PTR_ERR(m));
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!ctx) {
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the index root attribute in the mft record. */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0, ctx);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err)) {
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err == -ENOENT) {
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index root attribute missing in "
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"directory inode 0x%lx.",
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -EIO;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get to the index root value (it's been verified in read_inode). */
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ir = (INDEX_ROOT*)((u8*)ctx->attr +
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le16_to_cpu(ctx->attr->data.resident.value_offset));
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry. */
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ir->index +
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ir->index.entries_offset));
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Loop until we exceed valid memory (corruption case) or until we
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry.
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds checks. */
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto dir_err_out;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The last entry cannot contain a name. It can however contain
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * a pointer to a child node in the B+tree so we just break out.
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the current entry has a name type of POSIX, the name is
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive and not otherwise. This has the effect of us
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * not being able to access any POSIX file names which collate
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * after the non-POSIX one when they only differ in case, but
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * anyone doing screwy stuff like that deserves to burn in
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * hell... Doing that kind of stuff on NT4 actually causes
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * corruption on the partition even when using SP6a and Linux
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is not involved at all.
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ic = ie->key.file_name.file_name_type ? IGNORE_CASE :
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the names match perfectly, we are done and return the
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * mft reference of the inode (i.e. the inode number together
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * with the sequence number for consistency checking. We
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * convert it to cpu format before returning.
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ntfs_are_names_equal(uname, uname_len,
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, ic,
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vol->upcase, vol->upcase_len)) {
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound_it:
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mref = le64_to_cpu(ie->data.dir.indexed_file);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_attr_put_search_ctx(ctx);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unmap_mft_record(dir_ni);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mref;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Not a perfect match, need to do full blown collation so we
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * know which way in the B+tree we have to go.
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If uname collates before the name of the current entry, there
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is definitely no such name in this index but we might need to
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * descend into the B+tree so we just break out of the loop.
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The names are not equal, continue the search. */
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Names match with case insensitive comparison, now try the
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive comparison, which is required for proper
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * collation.
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Perfect match, this will never happen as the
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_are_names_equal() call will have gotten a match but we
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * still treat it correctly.
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto found_it;
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We have finished with this index without success. Check for the
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * presence of a child node.
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(ie->flags & INDEX_ENTRY_NODE)) {
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No child node, return -ENOENT. */
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOENT;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} /* Child node present, descend into it. */
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Consistency check: Verify that an index allocation exists. */
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoIndexAllocPresent(dir_ni)) {
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "No index allocation attribute but index entry "
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"requires one. Directory inode 0x%lx is "
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"corrupt or driver bug.", dir_ni->mft_no);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the starting vcn of the index_block holding the child node. */
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia_mapping = VFS_I(dir_ni)->i_mapping;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We are done with the index root and the mft record. Release them,
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * otherwise we deadlock with ntfs_map_page().
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_put_search_ctx(ctx);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unmap_mft_record(dir_ni);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = NULL;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = NULL;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdescend_into_child_node:
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Convert vcn to index into the index allocation attribute in units
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * of PAGE_CACHE_SIZE and map the page cache page, reading it from
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * disk if necessary.
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page = ntfs_map_page(ia_mapping, vcn <<
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(page)) {
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Failed to map directory index page, error %ld.",
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-PTR_ERR(page));
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(page);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lock_page(page);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kaddr = (u8*)page_address(page);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfast_descend_into_child_node:
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get to the index allocation block. */
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia = (INDEX_ALLOCATION*)(kaddr + ((vcn <<
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK));
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Bounds checks. */
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx or driver bug.", dir_ni->mft_no);
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Catch multi sector transfer fixup errors. */
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ntfs_is_indx_record(ia->magic))) {
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Directory index record with vcn 0x%llx is "
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"corrupt.  Corrupt inode 0x%lx.  Run chkdsk.",
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is "
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"different from expected VCN (0x%llx). "
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Directory inode 0x%lx is corrupt or driver "
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"bug.", (unsigned long long)
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sle64_to_cpu(ia->index_block_vcn),
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dir_ni->itype.index.block_size) {
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx has a size (%u) differing from the "
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"directory specified size (%u). Directory "
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode is corrupt or driver bug.",
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no,
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le32_to_cpu(ia->index.allocated_size) + 0x18,
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dir_ni->itype.index.block_size);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)ia + dir_ni->itype.index.block_size;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (index_end > kaddr + PAGE_CACHE_SIZE) {
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx crosses page boundary. Impossible! "
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Cannot access! This is probably a bug in the "
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"driver.", (unsigned long long)vcn,
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dir_ni->mft_no);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (index_end > (u8*)ia + dir_ni->itype.index.block_size) {
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx exceeds maximum size.",
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)vcn, dir_ni->mft_no);
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry. */
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ia->index +
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ia->index.entries_offset));
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Iterate similar to above big loop but applied to index buffer, thus
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * loop until we exceed valid memory (corruption case) or until we
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry.
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds check. */
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((u8*)ie < (u8*)ia || (u8*)ie +
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end) {
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index entry out of bounds in "
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"directory inode 0x%lx.",
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto unm_err_out;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The last entry cannot contain a name. It can however contain
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * a pointer to a child node in the B+tree so we just break out.
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the current entry has a name type of POSIX, the name is
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive and not otherwise. This has the effect of us
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * not being able to access any POSIX file names which collate
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * after the non-POSIX one when they only differ in case, but
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * anyone doing screwy stuff like that deserves to burn in
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * hell... Doing that kind of stuff on NT4 actually causes
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * corruption on the partition even when using SP6a and Linux
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is not involved at all.
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ic = ie->key.file_name.file_name_type ? IGNORE_CASE :
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the names match perfectly, we are done and return the
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * mft reference of the inode (i.e. the inode number together
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * with the sequence number for consistency checking. We
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * convert it to cpu format before returning.
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ntfs_are_names_equal(uname, uname_len,
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, ic,
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vol->upcase, vol->upcase_len)) {
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound_it2:
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mref = le64_to_cpu(ie->data.dir.indexed_file);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unlock_page(page);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(page);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mref;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Not a perfect match, need to do full blown collation so we
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * know which way in the B+tree we have to go.
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IGNORE_CASE, vol->upcase, vol->upcase_len);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If uname collates before the name of the current entry, there
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is definitely no such name in this index but we might need to
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * descend into the B+tree so we just break out of the loop.
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The names are not equal, continue the search. */
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Names match with case insensitive comparison, now try the
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * case sensitive comparison, which is required for proper
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * collation.
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_collate_names(uname, uname_len,
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(ntfschar*)&ie->key.file_name.file_name,
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ie->key.file_name.file_name_length, 1,
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CASE_SENSITIVE, vol->upcase, vol->upcase_len);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -1)
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Perfect match, this will never happen as the
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_are_names_equal() call will have gotten a match but we
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * still treat it correctly.
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto found_it2;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We have finished with this index buffer without success. Check for
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the presence of a child node.
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ie->flags & INDEX_ENTRY_NODE) {
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Index entry with child node found in "
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"a leaf node in directory inode 0x%lx.",
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_ni->mft_no);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto unm_err_out;
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Child node present, descend into it. */
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_vcn = vcn;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vcn >= 0) {
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* If vcn is in the same page cache page as old_vcn we
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * recycle the mapped page. */
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (old_vcn << vol->cluster_size_bits >>
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PAGE_CACHE_SHIFT == vcn <<
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vol->cluster_size_bits >>
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PAGE_CACHE_SHIFT)
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fast_descend_into_child_node;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unlock_page(page);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(page);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto descend_into_child_node;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Negative child node vcn in directory inode "
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx.", dir_ni->mft_no);
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No child node, return -ENOENT. */
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entry not found.");
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = -ENOENT;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunm_err_out:
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_unmap_page(page);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out:
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!err)
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ctx)
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_attr_put_search_ctx(ctx);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (m)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unmap_mft_record(dir_ni);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_MREF(err);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdir_err_out:
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_error(sb, "Corrupt directory. Aborting lookup.");
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto err_out;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_filldir - ntfs specific filldir method
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @vol:	current ntfs volume
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fpos:	position in the directory
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ndir:	ntfs inode of current directory
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ia_page:	page in which the index allocation buffer @ie is in resides
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ie:		current index entry
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @name:	buffer to use for the converted name
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dirent:	vfs filldir callback context
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @filldir:	vfs filldir callback
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert the Unicode @name to the loaded NLS and pass it to the @filldir
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * callback.
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If @ia_page is not NULL it is the locked page containing the index
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocation block containing the index entry @ie.
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note, we drop (and then reacquire) the page lock on @ia_page across the
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @filldir() call otherwise we would deadlock with NFSd when it calls ->lookup
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since ntfs_lookup() will lock the same page.  As an optimization, we do not
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * retake the lock if we are returning a non-zero value as ntfs_readdir()
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * would need to drop the lock immediately anyway.
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie,
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 *name, void *dirent, filldir_t filldir)
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mref;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int name_len, rc;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned dt_type;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FILE_NAME_TYPE_FLAGS name_type;
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	name_type = ie->key.file_name.file_name_type;
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (name_type == FILE_NAME_DOS) {
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Skipping DOS name space entry.");
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (MREF_LE(ie->data.dir.indexed_file) == FILE_root) {
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Skipping root directory self reference entry.");
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (MREF_LE(ie->data.dir.indexed_file) < FILE_first_user &&
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			!NVolShowSystemFiles(vol)) {
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Skipping system file.");
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	name_len = ntfs_ucstonls(vol, (ntfschar*)&ie->key.file_name.file_name,
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ie->key.file_name.file_name_length, &name,
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1);
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (name_len <= 0) {
1054f94ad38e68e1623660fdbb063d0c580ba6661c29Anton Altaparmakov		ntfs_warning(vol->sb, "Skipping unrepresentable inode 0x%llx.",
1055f94ad38e68e1623660fdbb063d0c580ba6661c29Anton Altaparmakov				(long long)MREF_LE(ie->data.dir.indexed_file));
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ie->key.file_name.file_attributes &
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT)
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dt_type = DT_DIR;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dt_type = DT_REG;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mref = MREF_LE(ie->data.dir.indexed_file);
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Drop the page lock otherwise we deadlock with NFS when it calls
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ->lookup since ntfs_lookup() will lock the same page.
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ia_page)
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(ia_page);
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode "
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"0x%lx, DT_%s.", name, name_len, fpos, mref,
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dt_type == DT_DIR ? "DIR" : "REG");
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = filldir(dirent, name, name_len, fpos, mref, dt_type);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Relock the page but not if we are aborting ->readdir. */
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!rc && ia_page)
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lock_page(ia_page);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We use the same basic approach as the old NTFS driver, i.e. we parse the
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * index root entries and then the index allocation entries that are marked
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as in use in the index bitmap.
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * While this will return the names in random order this doesn't matter for
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ->readdir but OTOH results in a faster ->readdir.
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10881b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * VFS calls ->readdir without BKL but with i_mutex held. This protects the VFS
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parts (e.g. ->f_pos and ->i_size, and it also protects against directory
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modifications).
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10921b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * Locking:  - Caller must hold i_mutex on the directory.
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	     - Each page cache page in the index allocation mapping must be
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       locked whilst being accessed otherwise we may find a corrupt
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       page due to it being under ->writepage at the moment which
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       applies the mst protection fixups before writing out and then
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       removes them again after the write is complete after which it
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	       unlocks the page.
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;
1103206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov	loff_t fpos, i_size;
110420d29372d3facfd078b4c7703637b951914d6759Josef "Jeff" Sipek	struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode;
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block *sb = vdir->i_sb;
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ndir = NTFS_I(vdir);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol = NTFS_SB(sb);
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MFT_RECORD *m;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ROOT *ir = NULL;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ENTRY *ie;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INDEX_ALLOCATION *ia;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *name = NULL;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc, err, ir_pos, cur_bmp_pos;
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct address_space *ia_mapping, *bmp_mapping;
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *bmp_page = NULL, *ia_page = NULL;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *kaddr, *bmp, *index_end;
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_search_ctx *ctx;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fpos = filp->f_pos;
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.",
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vdir->i_ino, fpos);
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = err = 0;
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Are we at end of dir yet? */
1124206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov	i_size = i_size_read(vdir);
1125206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov	if (fpos >= i_size + vol->mft_record_size)
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto done;
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Emulate . and .. for all directories. */
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!fpos) {
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Calling filldir for . with len 1, fpos 0x0, "
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx, DT_DIR.", vdir->i_ino);
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR);
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto done;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fpos++;
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fpos == 1) {
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx, DT_DIR.",
113920d29372d3facfd078b4c7703637b951914d6759Josef "Jeff" Sipek				(unsigned long)parent_ino(filp->f_path.dentry));
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = filldir(dirent, "..", 2, fpos,
114120d29372d3facfd078b4c7703637b951914d6759Josef "Jeff" Sipek				parent_ino(filp->f_path.dentry), DT_DIR);
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc)
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto done;
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fpos++;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = NULL;
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = NULL;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate a buffer to store the current name being processed
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * converted to format determined by current NLS.
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1152f52720ca5f48574e347dff35ffe6b389ace61537Panagiotis Issaris	name = kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1, GFP_NOFS);
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!name)) {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Are we jumping straight into the index allocation attribute? */
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fpos >= vol->mft_record_size)
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_index_root;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get hold of the mft record for the directory. */
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = map_mft_record(ndir);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(m)) {
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(m);
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		m = NULL;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = ntfs_attr_get_search_ctx(ndir, m);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ctx)) {
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the offset into the index root attribute. */
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ir_pos = (s64)fpos;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the index root attribute in the mft record. */
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0, ctx);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err)) {
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index root attribute missing in directory "
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx.", vdir->i_ino);
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Copy the index root attribute value to a buffer so that we can put
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the search context and unmap the mft record before calling the
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * filldir() callback.  We need to do this because of NFSd which calls
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ->lookup() from its filldir callback() and this causes NTFS to
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * deadlock as ntfs_lookup() maps the mft record of the directory and
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we have got it mapped here already.  The only solution is for us to
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unmap the mft record here so that a call to ntfs_lookup() is able to
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * map the mft record without deadlocking.
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = le32_to_cpu(ctx->attr->data.resident.value_length);
1193f52720ca5f48574e347dff35ffe6b389ace61537Panagiotis Issaris	ir = kmalloc(rc, GFP_NOFS);
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ir)) {
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Copy the index root value (it has been verified in read_inode). */
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(ir, (u8*)ctx->attr +
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le16_to_cpu(ctx->attr->data.resident.value_offset), rc);
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_put_search_ctx(ctx);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unmap_mft_record(ndir);
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = NULL;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = NULL;
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry. */
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ir->index +
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ir->index.entries_offset));
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Loop until we exceed valid memory (corruption case) or until we
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry or until filldir tells us it has had enough
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * or signals an error (both covered by the rc test).
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("In index root, offset 0x%zx.", (u8*)ie - (u8*)ir);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds checks. */
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely((u8*)ie < (u8*)ir || (u8*)ie +
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end))
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto err_out;
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The last entry cannot contain a name. */
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Skip index root entry if continuing previous readdir. */
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ir_pos > (u8*)ie - (u8*)ir)
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Advance the position even if going to skip the entry. */
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fpos = (u8*)ie - (u8*)ir;
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Submit the name to the filldir callback. */
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent,
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				filldir);
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc) {
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree(ir);
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto abort;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We are done with the index root and can free the buffer. */
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ir);
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ir = NULL;
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If there is no index allocation attribute we are finished. */
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoIndexAllocPresent(ndir))
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto EOD;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Advance fpos to the beginning of the index allocation. */
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fpos = vol->mft_record_size;
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_index_root:
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kaddr = NULL;
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prev_ia_pos = -1LL;
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the offset into the index allocation attribute. */
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia_pos = (s64)fpos - vol->mft_record_size;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia_mapping = vdir->i_mapping;
12528331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino);
12538331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
12548331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	if (IS_ERR(bmp_vi)) {
12558331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		ntfs_error(sb, "Failed to get bitmap attribute.");
12568331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		err = PTR_ERR(bmp_vi);
12578331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		goto err_out;
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bmp_mapping = bmp_vi->i_mapping;
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the starting bitmap bit position and sanity check it. */
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bmp_pos = ia_pos >> ndir->itype.index.block_size_bits;
1262206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov	if (unlikely(bmp_pos >> 3 >= i_size_read(bmp_vi))) {
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Current index allocation position exceeds "
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"index bitmap size.");
12658331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		goto iput_err_out;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the starting bit position in the current bitmap page. */
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1);
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bmp_pos &= ~(u64)((PAGE_CACHE_SIZE * 8) - 1);
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_next_bmp_page:
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Reading bitmap with page index 0x%llx, bit ofs 0x%llx",
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT),
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long long)bmp_pos &
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long long)((PAGE_CACHE_SIZE * 8) - 1));
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bmp_page = ntfs_map_page(bmp_mapping,
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bmp_pos >> (3 + PAGE_CACHE_SHIFT));
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(bmp_page)) {
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Reading index bitmap failed.");
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(bmp_page);
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bmp_page = NULL;
12818331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		goto iput_err_out;
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bmp = (u8*)page_address(bmp_page);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find next index block in use. */
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!(bmp[cur_bmp_pos >> 3] & (1 << (cur_bmp_pos & 7)))) {
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfind_next_index_buffer:
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cur_bmp_pos++;
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If we have reached the end of the bitmap page, get the next
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * page, and put away the old one.
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely((cur_bmp_pos >> 3) >= PAGE_CACHE_SIZE)) {
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(bmp_page);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bmp_pos += PAGE_CACHE_SIZE * 8;
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cur_bmp_pos = 0;
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto get_next_bmp_page;
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If we have reached the end of the bitmap, we are done. */
1299206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov		if (unlikely(((bmp_pos + cur_bmp_pos) >> 3) >= i_size))
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto unm_EOD;
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ia_pos = (bmp_pos + cur_bmp_pos) <<
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.block_size_bits;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Handling index buffer 0x%llx.",
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long long)bmp_pos + cur_bmp_pos);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the current index buffer is in the same page we reuse the page. */
13073bd1f4a173a3445f9919c21e775de2d8b9deacf8Anton Altaparmakov	if ((prev_ia_pos & (s64)PAGE_CACHE_MASK) !=
13083bd1f4a173a3445f9919c21e775de2d8b9deacf8Anton Altaparmakov			(ia_pos & (s64)PAGE_CACHE_MASK)) {
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prev_ia_pos = ia_pos;
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (likely(ia_page != NULL)) {
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unlock_page(ia_page);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(ia_page);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Map the page cache page containing the current ia_pos,
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * reading it from disk if necessary.
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ia_page = ntfs_map_page(ia_mapping, ia_pos >> PAGE_CACHE_SHIFT);
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(ia_page)) {
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(sb, "Reading index allocation data failed.");
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = PTR_ERR(ia_page);
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ia_page = NULL;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto err_out;
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lock_page(ia_page);
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kaddr = (u8*)page_address(ia_page);
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the current index buffer. */
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia = (INDEX_ALLOCATION*)(kaddr + (ia_pos & ~PAGE_CACHE_MASK &
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			~(s64)(ndir->itype.index.block_size - 1)));
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Bounds checks. */
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) {
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx or driver bug.", vdir->i_ino);
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Catch multi sector transfer fixup errors. */
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ntfs_is_indx_record(ia->magic))) {
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Directory index record with vcn 0x%llx is "
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"corrupt.  Corrupt inode 0x%lx.  Run chkdsk.",
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)ia_pos >>
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits, vdir->i_ino);
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos &
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			~(s64)(ndir->itype.index.block_size - 1)) >>
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ndir->itype.index.vcn_size_bits)) {
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is "
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"different from expected VCN (0x%llx). "
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Directory inode 0x%lx is corrupt or driver "
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"bug. ", (unsigned long long)
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sle64_to_cpu(ia->index_block_vcn),
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)ia_pos >>
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits, vdir->i_ino);
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(le32_to_cpu(ia->index.allocated_size) + 0x18 !=
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ndir->itype.index.block_size)) {
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx has a size (%u) differing from the "
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"directory specified size (%u). Directory "
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode is corrupt or driver bug.",
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)ia_pos >>
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits, vdir->i_ino,
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le32_to_cpu(ia->index.allocated_size) + 0x18,
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.block_size);
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)ia + ndir->itype.index.block_size;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(index_end > kaddr + PAGE_CACHE_SIZE)) {
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%lx crosses page boundary. Impossible! "
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Cannot access! This is probably a bug in the "
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"driver.", (unsigned long long)ia_pos >>
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits, vdir->i_ino);
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ia_start = ia_pos & ~(s64)(ndir->itype.index.block_size - 1);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(index_end > (u8*)ia + ndir->itype.index.block_size)) {
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"inode 0x%lx exceeds maximum size.",
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)ia_pos >>
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits, vdir->i_ino);
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first index entry in this index buffer. */
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ie = (INDEX_ENTRY*)((u8*)&ia->index +
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(ia->index.entries_offset));
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Loop until we exceed valid memory (corruption case) or until we
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reach the last entry or until filldir tells us it has had enough
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * or signals an error (both covered by the rc test).
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("In index allocation, offset 0x%llx.",
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)ia_start +
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned long long)((u8*)ie - (u8*)ia));
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bounds checks. */
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely((u8*)ie < (u8*)ia || (u8*)ie +
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(INDEX_ENTRY_HEADER) > index_end ||
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(u8*)ie + le16_to_cpu(ie->key_length) >
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				index_end))
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto err_out;
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The last entry cannot contain a name. */
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ie->flags & INDEX_ENTRY_END)
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Skip index block entry if continuing previous readdir. */
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Advance the position even if going to skip the entry. */
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fpos = (u8*)ie - (u8*)ia +
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(sle64_to_cpu(ia->index_block_vcn) <<
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ndir->itype.index.vcn_size_bits) +
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vol->mft_record_size;
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Submit the name to the @filldir callback.  Note,
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_filldir() drops the lock on @ia_page but it retakes it
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * before returning, unless a non-zero value is returned in
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * which case the page is left unlocked.
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent,
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				filldir);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc) {
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* @ia_page is already unlocked in this case. */
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(ia_page);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_unmap_page(bmp_page);
14288331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov			iput(bmp_vi);
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto abort;
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto find_next_index_buffer;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunm_EOD:
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ia_page) {
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(ia_page);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_unmap_page(ia_page);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_unmap_page(bmp_page);
14398331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	iput(bmp_vi);
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEOD:
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We are finished, set fpos to EOD. */
1442206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov	fpos = i_size + vol->mft_record_size;
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsabort:
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(name);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone:
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!rc)
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos);
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.",
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc, fpos);
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	filp->f_pos = fpos;
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out:
14568331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	if (bmp_page) {
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_unmap_page(bmp_page);
14588331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakoviput_err_out:
14598331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		iput(bmp_vi);
14608331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	}
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ia_page) {
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(ia_page);
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_unmap_page(ia_page);
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1465251c8427c9c418674fc3c04a11de95dc3661b560Jesper Juhl	kfree(ir);
1466251c8427c9c418674fc3c04a11de95dc3661b560Jesper Juhl	kfree(name);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ctx)
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_attr_put_search_ctx(ctx);
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (m)
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unmap_mft_record(ndir);
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!err)
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Failed. Returning error code %i.", -err);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	filp->f_pos = fpos;
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_dir_open - called when an inode is about to be opened
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @vi:		inode to be opened
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @filp:	file structure describing the inode
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Limit directory size to the page cache limit on architectures where unsigned
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long is 32-bits. This is the most we can do for now without overflowing the
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page cache page index. Doing it this way means we don't run into problems
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * because of existing too large directories. It would be better to allow the
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user to read the accessible part of the directory but I doubt very much
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anyone is going to hit this check on a 32-bit architecture, so there is no
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * point in adding the extra complexity required to support this.
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On 64-bit architectures, the check is hopefully optimized away by the
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * compiler.
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_dir_open(struct inode *vi, struct file *filp)
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sizeof(unsigned long) < 8) {
1497206f9f35b2348b7b966ff18a5564b8a3ca325ed5Anton Altaparmakov		if (i_size_read(vi) > MAX_LFS_FILESIZE)
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFBIG;
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_dir_fsync - sync a directory to disk
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @filp:	directory to be synced
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dentry:	dentry describing the directory to sync
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @datasync:	if non-zero only flush user data and not metadata
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Data integrity sync of a directory to disk.  Used for fsync, fdatasync, and
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * msync system calls.  This function is based on file.c::ntfs_file_fsync().
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write the mft record and all associated extent mft records as well as the
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device.
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If @datasync is true, we do not wait on the inode(s) to be written out
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but we always wait on the page cache pages to be written out.
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: In the past @filp could be NULL so we ignore it as we don't need it
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anyway.
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15231b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * Locking: Caller must hold i_mutex on the inode.
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO: We should probably also write all attribute/index inodes associated
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this inode but since we have no simple way of getting to them we ignore
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this problem for now.  We do write the $BITMAP attribute if it is present
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * which is the important one for a directory so things are not too bad.
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
153002c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacikstatic int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
153102c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik			  int datasync)
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15337ea8085910ef3dd4f3cad6845aaa2b580d39b115Christoph Hellwig	struct inode *bmp_vi, *vi = filp->f_mapping->host;
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, ret;
15358331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	ntfs_attr na;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
153802c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik
153902c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik	err = filemap_write_and_wait_range(vi->i_mapping, start, end);
154002c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik	if (err)
154102c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik		return err;
154202c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik	mutex_lock(&vi->i_mutex);
154302c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!S_ISDIR(vi->i_mode));
15458331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	/* If the bitmap attribute inode is in memory sync it, too. */
15468331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	na.mft_no = vi->i_ino;
15478331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	na.type = AT_BITMAP;
15488331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	na.name = I30;
15498331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	na.name_len = 4;
15508331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	bmp_vi = ilookup5(vi->i_sb, vi->i_ino, (test_t)ntfs_test_inode, &na);
15518331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	if (bmp_vi) {
15528331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov 		write_inode_now(bmp_vi, !datasync);
15538331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov		iput(bmp_vi);
15548331191e56802f0155772a3d56bc2a750acc38e1Anton Altaparmakov	}
1555a9185b41a4f84971b930c519f0c63bd450c4810dChristoph Hellwig	ret = __ntfs_write_inode(vi, 1);
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	write_inode_now(vi, !datasync);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = sync_blockdev(vi->i_sb->s_bdev);
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err && !ret))
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = err;
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (likely(!ret))
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Done.");
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
156502c24a82187d5a628c68edfe71ae60dc135cd178Josef Bacik	mutex_unlock(&vi->i_mutex);
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NTFS_RW */
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15714b6f5d20b04dcbc3d888555522b90ba6d36c4106Arjan van de Venconst struct file_operations ntfs_dir_ops = {
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.llseek		= generic_file_llseek,	/* Seek inside directory. */
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read		= generic_read_dir,	/* Return -EISDIR. */
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.readdir	= ntfs_readdir,		/* Read directory contents. */
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fsync		= ntfs_dir_fsync,	/* Sync a directory to disk. */
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*.aio_fsync	= ,*/			/* Sync all outstanding async
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   i/o operations on a kiocb. */
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NTFS_RW */
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*.ioctl	= ,*/			/* Perform function on the
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   mounted filesystem. */
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.open		= ntfs_dir_open,	/* Open directory. */
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1584