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