11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 30a8ac0c1SNamjae Jeon * NTFS kernel directory operations. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2001-2007 Anton Altaparmakov 61e9ea7e0SNamjae Jeon * Copyright (c) 2002 Richard Russon 70a8ac0c1SNamjae Jeon * Copyright (c) 2025 LG Electronics Co., Ltd. 81e9ea7e0SNamjae Jeon */ 91e9ea7e0SNamjae Jeon 101e9ea7e0SNamjae Jeon #include <linux/blkdev.h> 111e9ea7e0SNamjae Jeon 121e9ea7e0SNamjae Jeon #include "dir.h" 131e9ea7e0SNamjae Jeon #include "mft.h" 141e9ea7e0SNamjae Jeon #include "ntfs.h" 150a8ac0c1SNamjae Jeon #include "index.h" 160a8ac0c1SNamjae Jeon #include "reparse.h" 170a8ac0c1SNamjae Jeon 180a8ac0c1SNamjae Jeon #include <linux/filelock.h> 191e9ea7e0SNamjae Jeon 201e9ea7e0SNamjae Jeon /* 211e9ea7e0SNamjae Jeon * The little endian Unicode string $I30 as a global constant. 221e9ea7e0SNamjae Jeon */ 230a8ac0c1SNamjae Jeon __le16 I30[5] = { cpu_to_le16('$'), cpu_to_le16('I'), 241e9ea7e0SNamjae Jeon cpu_to_le16('3'), cpu_to_le16('0'), 0 }; 251e9ea7e0SNamjae Jeon 260a8ac0c1SNamjae Jeon /* 271e9ea7e0SNamjae Jeon * ntfs_lookup_inode_by_name - find an inode in a directory given its name 281e9ea7e0SNamjae Jeon * @dir_ni: ntfs inode of the directory in which to search for the name 291e9ea7e0SNamjae Jeon * @uname: Unicode name for which to search in the directory 301e9ea7e0SNamjae Jeon * @uname_len: length of the name @uname in Unicode characters 311e9ea7e0SNamjae Jeon * @res: return the found file name if necessary (see below) 321e9ea7e0SNamjae Jeon * 331e9ea7e0SNamjae Jeon * Look for an inode with name @uname in the directory with inode @dir_ni. 341e9ea7e0SNamjae Jeon * ntfs_lookup_inode_by_name() walks the contents of the directory looking for 351e9ea7e0SNamjae Jeon * the Unicode name. If the name is found in the directory, the corresponding 361e9ea7e0SNamjae Jeon * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it 371e9ea7e0SNamjae Jeon * is a 64-bit number containing the sequence number. 381e9ea7e0SNamjae Jeon * 391e9ea7e0SNamjae Jeon * On error, a negative value is returned corresponding to the error code. In 401e9ea7e0SNamjae Jeon * particular if the inode is not found -ENOENT is returned. Note that you 411e9ea7e0SNamjae Jeon * can't just check the return value for being negative, you have to check the 421e9ea7e0SNamjae Jeon * inode number for being negative which you can extract using MREC(return 431e9ea7e0SNamjae Jeon * value). 441e9ea7e0SNamjae Jeon * 451e9ea7e0SNamjae Jeon * Note, @uname_len does not include the (optional) terminating NULL character. 461e9ea7e0SNamjae Jeon * 471e9ea7e0SNamjae Jeon * Note, we look for a case sensitive match first but we also look for a case 481e9ea7e0SNamjae Jeon * insensitive match at the same time. If we find a case insensitive match, we 491e9ea7e0SNamjae Jeon * save that for the case that we don't find an exact match, where we return 501e9ea7e0SNamjae Jeon * the case insensitive match and setup @res (which we allocate!) with the mft 511e9ea7e0SNamjae Jeon * reference, the file name type, length and with a copy of the little endian 521e9ea7e0SNamjae Jeon * Unicode file name itself. If we match a file name which is in the DOS name 531e9ea7e0SNamjae Jeon * space, we only return the mft reference and file name type in @res. 541e9ea7e0SNamjae Jeon * ntfs_lookup() then uses this to find the long file name in the inode itself. 551e9ea7e0SNamjae Jeon * This is to avoid polluting the dcache with short file names. We want them to 561e9ea7e0SNamjae Jeon * work but we don't care for how quickly one can access them. This also fixes 571e9ea7e0SNamjae Jeon * the dcache aliasing issues. 581e9ea7e0SNamjae Jeon * 591e9ea7e0SNamjae Jeon * Locking: - Caller must hold i_mutex on the directory. 601e9ea7e0SNamjae Jeon * - Each page cache page in the index allocation mapping must be 611e9ea7e0SNamjae Jeon * locked whilst being accessed otherwise we may find a corrupt 621e9ea7e0SNamjae Jeon * page due to it being under ->writepage at the moment which 631e9ea7e0SNamjae Jeon * applies the mst protection fixups before writing out and then 641e9ea7e0SNamjae Jeon * removes them again after the write is complete after which it 651e9ea7e0SNamjae Jeon * unlocks the page. 661e9ea7e0SNamjae Jeon */ 670a8ac0c1SNamjae Jeon u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname, 680a8ac0c1SNamjae Jeon const int uname_len, struct ntfs_name **res) 691e9ea7e0SNamjae Jeon { 700a8ac0c1SNamjae Jeon struct ntfs_volume *vol = dir_ni->vol; 711e9ea7e0SNamjae Jeon struct super_block *sb = vol->sb; 720a8ac0c1SNamjae Jeon struct inode *ia_vi = NULL; 730a8ac0c1SNamjae Jeon struct mft_record *m; 740a8ac0c1SNamjae Jeon struct index_root *ir; 750a8ac0c1SNamjae Jeon struct index_entry *ie; 760a8ac0c1SNamjae Jeon struct index_block *ia; 771e9ea7e0SNamjae Jeon u8 *index_end; 781e9ea7e0SNamjae Jeon u64 mref; 790a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx; 801e9ea7e0SNamjae Jeon int err, rc; 810a8ac0c1SNamjae Jeon s64 vcn, old_vcn; 821e9ea7e0SNamjae Jeon struct address_space *ia_mapping; 830a8ac0c1SNamjae Jeon struct folio *folio; 840a8ac0c1SNamjae Jeon u8 *kaddr = NULL; 850a8ac0c1SNamjae Jeon struct ntfs_name *name = NULL; 861e9ea7e0SNamjae Jeon 871e9ea7e0SNamjae Jeon /* Get hold of the mft record for the directory. */ 881e9ea7e0SNamjae Jeon m = map_mft_record(dir_ni); 891e9ea7e0SNamjae Jeon if (IS_ERR(m)) { 901e9ea7e0SNamjae Jeon ntfs_error(sb, "map_mft_record() failed with error code %ld.", 911e9ea7e0SNamjae Jeon -PTR_ERR(m)); 921e9ea7e0SNamjae Jeon return ERR_MREF(PTR_ERR(m)); 931e9ea7e0SNamjae Jeon } 941e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(dir_ni, m); 951e9ea7e0SNamjae Jeon if (unlikely(!ctx)) { 961e9ea7e0SNamjae Jeon err = -ENOMEM; 971e9ea7e0SNamjae Jeon goto err_out; 981e9ea7e0SNamjae Jeon } 991e9ea7e0SNamjae Jeon /* Find the index root attribute in the mft record. */ 1001e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 1011e9ea7e0SNamjae Jeon 0, ctx); 1021e9ea7e0SNamjae Jeon if (unlikely(err)) { 1031e9ea7e0SNamjae Jeon if (err == -ENOENT) { 1040a8ac0c1SNamjae Jeon ntfs_error(sb, 105d9038d99SNamjae Jeon "Index root attribute missing in directory inode 0x%llx.", 1061e9ea7e0SNamjae Jeon dir_ni->mft_no); 1071e9ea7e0SNamjae Jeon err = -EIO; 1081e9ea7e0SNamjae Jeon } 1091e9ea7e0SNamjae Jeon goto err_out; 1101e9ea7e0SNamjae Jeon } 1111e9ea7e0SNamjae Jeon /* Get to the index root value (it's been verified in read_inode). */ 1120a8ac0c1SNamjae Jeon ir = (struct index_root *)((u8 *)ctx->attr + 1131e9ea7e0SNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 1141e9ea7e0SNamjae Jeon index_end = (u8 *)&ir->index + le32_to_cpu(ir->index.index_length); 1151e9ea7e0SNamjae Jeon /* The first index entry. */ 1160a8ac0c1SNamjae Jeon ie = (struct index_entry *)((u8 *)&ir->index + 1171e9ea7e0SNamjae Jeon le32_to_cpu(ir->index.entries_offset)); 1181e9ea7e0SNamjae Jeon /* 1191e9ea7e0SNamjae Jeon * Loop until we exceed valid memory (corruption case) or until we 1201e9ea7e0SNamjae Jeon * reach the last entry. 1211e9ea7e0SNamjae Jeon */ 1220a8ac0c1SNamjae Jeon for (;; ie = (struct index_entry *)((u8 *)ie + le16_to_cpu(ie->length))) { 1231e9ea7e0SNamjae Jeon /* Bounds checks. */ 1240a8ac0c1SNamjae Jeon if ((u8 *)ie < (u8 *)ctx->mrec || 1250a8ac0c1SNamjae Jeon (u8 *)ie + sizeof(struct index_entry_header) > index_end || 1260a8ac0c1SNamjae Jeon (u8 *)ie + sizeof(struct index_entry_header) + le16_to_cpu(ie->key_length) > 1270a8ac0c1SNamjae Jeon index_end || (u8 *)ie + le16_to_cpu(ie->length) > index_end) 1281e9ea7e0SNamjae Jeon goto dir_err_out; 1291e9ea7e0SNamjae Jeon /* 1301e9ea7e0SNamjae Jeon * The last entry cannot contain a name. It can however contain 1311e9ea7e0SNamjae Jeon * a pointer to a child node in the B+tree so we just break out. 1321e9ea7e0SNamjae Jeon */ 1331e9ea7e0SNamjae Jeon if (ie->flags & INDEX_ENTRY_END) 1341e9ea7e0SNamjae Jeon break; 1350a8ac0c1SNamjae Jeon /* Key length should not be zero if it is not last entry. */ 1360a8ac0c1SNamjae Jeon if (!ie->key_length) 1370a8ac0c1SNamjae Jeon goto dir_err_out; 1380a8ac0c1SNamjae Jeon /* Check the consistency of an index entry */ 1390a8ac0c1SNamjae Jeon if (ntfs_index_entry_inconsistent(NULL, vol, ie, COLLATION_FILE_NAME, 1400a8ac0c1SNamjae Jeon dir_ni->mft_no)) 1410a8ac0c1SNamjae Jeon goto dir_err_out; 1421e9ea7e0SNamjae Jeon /* 1431e9ea7e0SNamjae Jeon * We perform a case sensitive comparison and if that matches 1441e9ea7e0SNamjae Jeon * we are done and return the mft reference of the inode (i.e. 1451e9ea7e0SNamjae Jeon * the inode number together with the sequence number for 1461e9ea7e0SNamjae Jeon * consistency checking). We convert it to cpu format before 1471e9ea7e0SNamjae Jeon * returning. 1481e9ea7e0SNamjae Jeon */ 1491e9ea7e0SNamjae Jeon if (ntfs_are_names_equal(uname, uname_len, 1500a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 1511e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 1521e9ea7e0SNamjae Jeon CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { 1531e9ea7e0SNamjae Jeon found_it: 1541e9ea7e0SNamjae Jeon /* 1551e9ea7e0SNamjae Jeon * We have a perfect match, so we don't need to care 1561e9ea7e0SNamjae Jeon * about having matched imperfectly before, so we can 1571e9ea7e0SNamjae Jeon * free name and set *res to NULL. 1581e9ea7e0SNamjae Jeon * However, if the perfect match is a short file name, 1591e9ea7e0SNamjae Jeon * we need to signal this through *res, so that 1601e9ea7e0SNamjae Jeon * ntfs_lookup() can fix dcache aliasing issues. 1611e9ea7e0SNamjae Jeon * As an optimization we just reuse an existing 1621e9ea7e0SNamjae Jeon * allocation of *res. 1631e9ea7e0SNamjae Jeon */ 1641e9ea7e0SNamjae Jeon if (ie->key.file_name.file_name_type == FILE_NAME_DOS) { 1651e9ea7e0SNamjae Jeon if (!name) { 1660a8ac0c1SNamjae Jeon name = kmalloc(sizeof(struct ntfs_name), 1671e9ea7e0SNamjae Jeon GFP_NOFS); 1681e9ea7e0SNamjae Jeon if (!name) { 1691e9ea7e0SNamjae Jeon err = -ENOMEM; 1701e9ea7e0SNamjae Jeon goto err_out; 1711e9ea7e0SNamjae Jeon } 1721e9ea7e0SNamjae Jeon } 1731e9ea7e0SNamjae Jeon name->mref = le64_to_cpu( 1741e9ea7e0SNamjae Jeon ie->data.dir.indexed_file); 1751e9ea7e0SNamjae Jeon name->type = FILE_NAME_DOS; 1761e9ea7e0SNamjae Jeon name->len = 0; 1771e9ea7e0SNamjae Jeon *res = name; 1781e9ea7e0SNamjae Jeon } else { 1791e9ea7e0SNamjae Jeon kfree(name); 1801e9ea7e0SNamjae Jeon *res = NULL; 1811e9ea7e0SNamjae Jeon } 1821e9ea7e0SNamjae Jeon mref = le64_to_cpu(ie->data.dir.indexed_file); 1831e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 1841e9ea7e0SNamjae Jeon unmap_mft_record(dir_ni); 1851e9ea7e0SNamjae Jeon return mref; 1861e9ea7e0SNamjae Jeon } 1871e9ea7e0SNamjae Jeon /* 1881e9ea7e0SNamjae Jeon * For a case insensitive mount, we also perform a case 1891e9ea7e0SNamjae Jeon * insensitive comparison (provided the file name is not in the 1901e9ea7e0SNamjae Jeon * POSIX namespace). If the comparison matches, and the name is 1911e9ea7e0SNamjae Jeon * in the WIN32 namespace, we cache the filename in *res so 1921e9ea7e0SNamjae Jeon * that the caller, ntfs_lookup(), can work on it. If the 1931e9ea7e0SNamjae Jeon * comparison matches, and the name is in the DOS namespace, we 1941e9ea7e0SNamjae Jeon * only cache the mft reference and the file name type (we set 1951e9ea7e0SNamjae Jeon * the name length to zero for simplicity). 1961e9ea7e0SNamjae Jeon */ 1970a8ac0c1SNamjae Jeon if ((!NVolCaseSensitive(vol) || 1980a8ac0c1SNamjae Jeon ie->key.file_name.file_name_type == FILE_NAME_DOS) && 1991e9ea7e0SNamjae Jeon ntfs_are_names_equal(uname, uname_len, 2000a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 2011e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 2020a8ac0c1SNamjae Jeon IGNORE_CASE, vol->upcase, 2030a8ac0c1SNamjae Jeon vol->upcase_len)) { 2040a8ac0c1SNamjae Jeon int name_size = sizeof(struct ntfs_name); 2051e9ea7e0SNamjae Jeon u8 type = ie->key.file_name.file_name_type; 2061e9ea7e0SNamjae Jeon u8 len = ie->key.file_name.file_name_length; 2071e9ea7e0SNamjae Jeon 2081e9ea7e0SNamjae Jeon /* Only one case insensitive matching name allowed. */ 2091e9ea7e0SNamjae Jeon if (name) { 2100a8ac0c1SNamjae Jeon ntfs_error(sb, 2110a8ac0c1SNamjae Jeon "Found already allocated name in phase 1. Please run chkdsk"); 2121e9ea7e0SNamjae Jeon goto dir_err_out; 2131e9ea7e0SNamjae Jeon } 2141e9ea7e0SNamjae Jeon 2151e9ea7e0SNamjae Jeon if (type != FILE_NAME_DOS) 2160a8ac0c1SNamjae Jeon name_size += len * sizeof(__le16); 2171e9ea7e0SNamjae Jeon name = kmalloc(name_size, GFP_NOFS); 2181e9ea7e0SNamjae Jeon if (!name) { 2191e9ea7e0SNamjae Jeon err = -ENOMEM; 2201e9ea7e0SNamjae Jeon goto err_out; 2211e9ea7e0SNamjae Jeon } 2221e9ea7e0SNamjae Jeon name->mref = le64_to_cpu(ie->data.dir.indexed_file); 2231e9ea7e0SNamjae Jeon name->type = type; 2241e9ea7e0SNamjae Jeon if (type != FILE_NAME_DOS) { 2251e9ea7e0SNamjae Jeon name->len = len; 2261e9ea7e0SNamjae Jeon memcpy(name->name, ie->key.file_name.file_name, 2270a8ac0c1SNamjae Jeon len * sizeof(__le16)); 2281e9ea7e0SNamjae Jeon } else 2291e9ea7e0SNamjae Jeon name->len = 0; 2301e9ea7e0SNamjae Jeon *res = name; 2311e9ea7e0SNamjae Jeon } 2321e9ea7e0SNamjae Jeon /* 2331e9ea7e0SNamjae Jeon * Not a perfect match, need to do full blown collation so we 2341e9ea7e0SNamjae Jeon * know which way in the B+tree we have to go. 2351e9ea7e0SNamjae Jeon */ 2361e9ea7e0SNamjae Jeon rc = ntfs_collate_names(uname, uname_len, 2370a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 2381e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 1, 2391e9ea7e0SNamjae Jeon IGNORE_CASE, vol->upcase, vol->upcase_len); 2401e9ea7e0SNamjae Jeon /* 2411e9ea7e0SNamjae Jeon * If uname collates before the name of the current entry, there 2421e9ea7e0SNamjae Jeon * is definitely no such name in this index but we might need to 2431e9ea7e0SNamjae Jeon * descend into the B+tree so we just break out of the loop. 2441e9ea7e0SNamjae Jeon */ 2451e9ea7e0SNamjae Jeon if (rc == -1) 2461e9ea7e0SNamjae Jeon break; 2471e9ea7e0SNamjae Jeon /* The names are not equal, continue the search. */ 2481e9ea7e0SNamjae Jeon if (rc) 2491e9ea7e0SNamjae Jeon continue; 2501e9ea7e0SNamjae Jeon /* 2511e9ea7e0SNamjae Jeon * Names match with case insensitive comparison, now try the 2521e9ea7e0SNamjae Jeon * case sensitive comparison, which is required for proper 2531e9ea7e0SNamjae Jeon * collation. 2541e9ea7e0SNamjae Jeon */ 2551e9ea7e0SNamjae Jeon rc = ntfs_collate_names(uname, uname_len, 2560a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 2571e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 1, 2581e9ea7e0SNamjae Jeon CASE_SENSITIVE, vol->upcase, vol->upcase_len); 2591e9ea7e0SNamjae Jeon if (rc == -1) 2601e9ea7e0SNamjae Jeon break; 2611e9ea7e0SNamjae Jeon if (rc) 2621e9ea7e0SNamjae Jeon continue; 2631e9ea7e0SNamjae Jeon /* 2641e9ea7e0SNamjae Jeon * Perfect match, this will never happen as the 2651e9ea7e0SNamjae Jeon * ntfs_are_names_equal() call will have gotten a match but we 2661e9ea7e0SNamjae Jeon * still treat it correctly. 2671e9ea7e0SNamjae Jeon */ 2681e9ea7e0SNamjae Jeon goto found_it; 2691e9ea7e0SNamjae Jeon } 2701e9ea7e0SNamjae Jeon /* 2711e9ea7e0SNamjae Jeon * We have finished with this index without success. Check for the 2721e9ea7e0SNamjae Jeon * presence of a child node and if not present return -ENOENT, unless 2731e9ea7e0SNamjae Jeon * we have got a matching name cached in name in which case return the 2741e9ea7e0SNamjae Jeon * mft reference associated with it. 2751e9ea7e0SNamjae Jeon */ 2761e9ea7e0SNamjae Jeon if (!(ie->flags & INDEX_ENTRY_NODE)) { 2771e9ea7e0SNamjae Jeon if (name) { 2781e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 2791e9ea7e0SNamjae Jeon unmap_mft_record(dir_ni); 2801e9ea7e0SNamjae Jeon return name->mref; 2811e9ea7e0SNamjae Jeon } 2821e9ea7e0SNamjae Jeon ntfs_debug("Entry not found."); 2831e9ea7e0SNamjae Jeon err = -ENOENT; 2841e9ea7e0SNamjae Jeon goto err_out; 2851e9ea7e0SNamjae Jeon } /* Child node present, descend into it. */ 2860a8ac0c1SNamjae Jeon 2871e9ea7e0SNamjae Jeon /* Get the starting vcn of the index_block holding the child node. */ 2880a8ac0c1SNamjae Jeon vcn = le64_to_cpup((__le64 *)((u8 *)ie + le16_to_cpu(ie->length) - 8)); 2890a8ac0c1SNamjae Jeon 2901e9ea7e0SNamjae Jeon /* 2911e9ea7e0SNamjae Jeon * We are done with the index root and the mft record. Release them, 2920a8ac0c1SNamjae Jeon * otherwise we deadlock with read_mapping_folio(). 2931e9ea7e0SNamjae Jeon */ 2941e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 2951e9ea7e0SNamjae Jeon unmap_mft_record(dir_ni); 2961e9ea7e0SNamjae Jeon m = NULL; 2971e9ea7e0SNamjae Jeon ctx = NULL; 2980a8ac0c1SNamjae Jeon 2990a8ac0c1SNamjae Jeon ia_vi = ntfs_index_iget(VFS_I(dir_ni), I30, 4); 3000a8ac0c1SNamjae Jeon if (IS_ERR(ia_vi)) { 3010a8ac0c1SNamjae Jeon err = PTR_ERR(ia_vi); 3020a8ac0c1SNamjae Jeon goto err_out; 3030a8ac0c1SNamjae Jeon } 3040a8ac0c1SNamjae Jeon 3050a8ac0c1SNamjae Jeon ia_mapping = ia_vi->i_mapping; 3061e9ea7e0SNamjae Jeon descend_into_child_node: 3071e9ea7e0SNamjae Jeon /* 3081e9ea7e0SNamjae Jeon * Convert vcn to index into the index allocation attribute in units 3091e9ea7e0SNamjae Jeon * of PAGE_SIZE and map the page cache page, reading it from 3101e9ea7e0SNamjae Jeon * disk if necessary. 3111e9ea7e0SNamjae Jeon */ 3120a8ac0c1SNamjae Jeon folio = read_mapping_folio(ia_mapping, vcn << 3130a8ac0c1SNamjae Jeon dir_ni->itype.index.vcn_size_bits >> PAGE_SHIFT, NULL); 3140a8ac0c1SNamjae Jeon if (IS_ERR(folio)) { 3151e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to map directory index page, error %ld.", 3160a8ac0c1SNamjae Jeon -PTR_ERR(folio)); 3170a8ac0c1SNamjae Jeon err = PTR_ERR(folio); 3181e9ea7e0SNamjae Jeon goto err_out; 3191e9ea7e0SNamjae Jeon } 3200a8ac0c1SNamjae Jeon 3210a8ac0c1SNamjae Jeon folio_lock(folio); 3220a8ac0c1SNamjae Jeon kaddr = kmalloc(PAGE_SIZE, GFP_NOFS); 3230a8ac0c1SNamjae Jeon if (!kaddr) { 3240a8ac0c1SNamjae Jeon err = -ENOMEM; 3250a8ac0c1SNamjae Jeon folio_unlock(folio); 3260a8ac0c1SNamjae Jeon folio_put(folio); 3270a8ac0c1SNamjae Jeon goto unm_err_out; 3280a8ac0c1SNamjae Jeon } 3290a8ac0c1SNamjae Jeon 3300a8ac0c1SNamjae Jeon memcpy_from_folio(kaddr, folio, 0, PAGE_SIZE); 3310a8ac0c1SNamjae Jeon post_read_mst_fixup((struct ntfs_record *)kaddr, PAGE_SIZE); 3320a8ac0c1SNamjae Jeon folio_unlock(folio); 3330a8ac0c1SNamjae Jeon folio_put(folio); 3341e9ea7e0SNamjae Jeon fast_descend_into_child_node: 3351e9ea7e0SNamjae Jeon /* Get to the index allocation block. */ 3360a8ac0c1SNamjae Jeon ia = (struct index_block *)(kaddr + ((vcn << 3371e9ea7e0SNamjae Jeon dir_ni->itype.index.vcn_size_bits) & ~PAGE_MASK)); 3381e9ea7e0SNamjae Jeon /* Bounds checks. */ 3391e9ea7e0SNamjae Jeon if ((u8 *)ia < kaddr || (u8 *)ia > kaddr + PAGE_SIZE) { 3400a8ac0c1SNamjae Jeon ntfs_error(sb, 341d9038d99SNamjae Jeon "Out of bounds check failed. Corrupt directory inode 0x%llx or driver bug.", 3420a8ac0c1SNamjae Jeon dir_ni->mft_no); 3431e9ea7e0SNamjae Jeon goto unm_err_out; 3441e9ea7e0SNamjae Jeon } 3451e9ea7e0SNamjae Jeon /* Catch multi sector transfer fixup errors. */ 3461e9ea7e0SNamjae Jeon if (unlikely(!ntfs_is_indx_record(ia->magic))) { 3470a8ac0c1SNamjae Jeon ntfs_error(sb, 348d9038d99SNamjae Jeon "Directory index record with vcn 0x%llx is corrupt. Corrupt inode 0x%llx. Run chkdsk.", 349d9038d99SNamjae Jeon vcn, dir_ni->mft_no); 3501e9ea7e0SNamjae Jeon goto unm_err_out; 3511e9ea7e0SNamjae Jeon } 3520a8ac0c1SNamjae Jeon if (le64_to_cpu(ia->index_block_vcn) != vcn) { 3530a8ac0c1SNamjae Jeon ntfs_error(sb, 354d9038d99SNamjae Jeon "Actual VCN (0x%llx) of index buffer is different from expected VCN (0x%llx). Directory inode 0x%llx is corrupt or driver bug.", 355d9038d99SNamjae Jeon le64_to_cpu(ia->index_block_vcn), 356d9038d99SNamjae Jeon vcn, dir_ni->mft_no); 3571e9ea7e0SNamjae Jeon goto unm_err_out; 3581e9ea7e0SNamjae Jeon } 3591e9ea7e0SNamjae Jeon if (le32_to_cpu(ia->index.allocated_size) + 0x18 != 3601e9ea7e0SNamjae Jeon dir_ni->itype.index.block_size) { 3610a8ac0c1SNamjae Jeon ntfs_error(sb, 362d9038d99SNamjae Jeon "Index buffer (VCN 0x%llx) of directory inode 0x%llx has a size (%u) differing from the directory specified size (%u). Directory inode is corrupt or driver bug.", 363d9038d99SNamjae Jeon vcn, dir_ni->mft_no, 3641e9ea7e0SNamjae Jeon le32_to_cpu(ia->index.allocated_size) + 0x18, 3651e9ea7e0SNamjae Jeon dir_ni->itype.index.block_size); 3661e9ea7e0SNamjae Jeon goto unm_err_out; 3671e9ea7e0SNamjae Jeon } 3681e9ea7e0SNamjae Jeon index_end = (u8 *)ia + dir_ni->itype.index.block_size; 3691e9ea7e0SNamjae Jeon if (index_end > kaddr + PAGE_SIZE) { 3700a8ac0c1SNamjae Jeon ntfs_error(sb, 371d9038d99SNamjae Jeon "Index buffer (VCN 0x%llx) of directory inode 0x%llx crosses page boundary. Impossible! Cannot access! This is probably a bug in the driver.", 372d9038d99SNamjae Jeon vcn, dir_ni->mft_no); 3731e9ea7e0SNamjae Jeon goto unm_err_out; 3741e9ea7e0SNamjae Jeon } 3751e9ea7e0SNamjae Jeon index_end = (u8 *)&ia->index + le32_to_cpu(ia->index.index_length); 3761e9ea7e0SNamjae Jeon if (index_end > (u8 *)ia + dir_ni->itype.index.block_size) { 3770a8ac0c1SNamjae Jeon ntfs_error(sb, 378d9038d99SNamjae Jeon "Size of index buffer (VCN 0x%llx) of directory inode 0x%llx exceeds maximum size.", 379d9038d99SNamjae Jeon vcn, dir_ni->mft_no); 3801e9ea7e0SNamjae Jeon goto unm_err_out; 3811e9ea7e0SNamjae Jeon } 3821e9ea7e0SNamjae Jeon /* The first index entry. */ 3830a8ac0c1SNamjae Jeon ie = (struct index_entry *)((u8 *)&ia->index + 3841e9ea7e0SNamjae Jeon le32_to_cpu(ia->index.entries_offset)); 3851e9ea7e0SNamjae Jeon /* 3861e9ea7e0SNamjae Jeon * Iterate similar to above big loop but applied to index buffer, thus 3871e9ea7e0SNamjae Jeon * loop until we exceed valid memory (corruption case) or until we 3881e9ea7e0SNamjae Jeon * reach the last entry. 3891e9ea7e0SNamjae Jeon */ 3900a8ac0c1SNamjae Jeon for (;; ie = (struct index_entry *)((u8 *)ie + le16_to_cpu(ie->length))) { 3910a8ac0c1SNamjae Jeon /* Bounds checks. */ 3920a8ac0c1SNamjae Jeon if ((u8 *)ie < (u8 *)ia || 3930a8ac0c1SNamjae Jeon (u8 *)ie + sizeof(struct index_entry_header) > index_end || 3940a8ac0c1SNamjae Jeon (u8 *)ie + sizeof(struct index_entry_header) + le16_to_cpu(ie->key_length) > 3950a8ac0c1SNamjae Jeon index_end || (u8 *)ie + le16_to_cpu(ie->length) > index_end) { 396d9038d99SNamjae Jeon ntfs_error(sb, "Index entry out of bounds in directory inode 0x%llx.", 3971e9ea7e0SNamjae Jeon dir_ni->mft_no); 3981e9ea7e0SNamjae Jeon goto unm_err_out; 3991e9ea7e0SNamjae Jeon } 4001e9ea7e0SNamjae Jeon /* 4011e9ea7e0SNamjae Jeon * The last entry cannot contain a name. It can however contain 4021e9ea7e0SNamjae Jeon * a pointer to a child node in the B+tree so we just break out. 4031e9ea7e0SNamjae Jeon */ 4041e9ea7e0SNamjae Jeon if (ie->flags & INDEX_ENTRY_END) 4051e9ea7e0SNamjae Jeon break; 4060a8ac0c1SNamjae Jeon /* Key length should not be zero if it is not last entry. */ 4070a8ac0c1SNamjae Jeon if (!ie->key_length) 4080a8ac0c1SNamjae Jeon goto unm_err_out; 4090a8ac0c1SNamjae Jeon /* Check the consistency of an index entry */ 4100a8ac0c1SNamjae Jeon if (ntfs_index_entry_inconsistent(NULL, vol, ie, COLLATION_FILE_NAME, 4110a8ac0c1SNamjae Jeon dir_ni->mft_no)) 4120a8ac0c1SNamjae Jeon goto unm_err_out; 4131e9ea7e0SNamjae Jeon /* 4141e9ea7e0SNamjae Jeon * We perform a case sensitive comparison and if that matches 4151e9ea7e0SNamjae Jeon * we are done and return the mft reference of the inode (i.e. 4161e9ea7e0SNamjae Jeon * the inode number together with the sequence number for 4171e9ea7e0SNamjae Jeon * consistency checking). We convert it to cpu format before 4181e9ea7e0SNamjae Jeon * returning. 4191e9ea7e0SNamjae Jeon */ 4201e9ea7e0SNamjae Jeon if (ntfs_are_names_equal(uname, uname_len, 4210a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 4221e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 4231e9ea7e0SNamjae Jeon CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { 4241e9ea7e0SNamjae Jeon found_it2: 4251e9ea7e0SNamjae Jeon /* 4261e9ea7e0SNamjae Jeon * We have a perfect match, so we don't need to care 4271e9ea7e0SNamjae Jeon * about having matched imperfectly before, so we can 4281e9ea7e0SNamjae Jeon * free name and set *res to NULL. 4291e9ea7e0SNamjae Jeon * However, if the perfect match is a short file name, 4301e9ea7e0SNamjae Jeon * we need to signal this through *res, so that 4311e9ea7e0SNamjae Jeon * ntfs_lookup() can fix dcache aliasing issues. 4321e9ea7e0SNamjae Jeon * As an optimization we just reuse an existing 4331e9ea7e0SNamjae Jeon * allocation of *res. 4341e9ea7e0SNamjae Jeon */ 4351e9ea7e0SNamjae Jeon if (ie->key.file_name.file_name_type == FILE_NAME_DOS) { 4361e9ea7e0SNamjae Jeon if (!name) { 4370a8ac0c1SNamjae Jeon name = kmalloc(sizeof(struct ntfs_name), 4381e9ea7e0SNamjae Jeon GFP_NOFS); 4391e9ea7e0SNamjae Jeon if (!name) { 4401e9ea7e0SNamjae Jeon err = -ENOMEM; 4411e9ea7e0SNamjae Jeon goto unm_err_out; 4421e9ea7e0SNamjae Jeon } 4431e9ea7e0SNamjae Jeon } 4441e9ea7e0SNamjae Jeon name->mref = le64_to_cpu( 4451e9ea7e0SNamjae Jeon ie->data.dir.indexed_file); 4461e9ea7e0SNamjae Jeon name->type = FILE_NAME_DOS; 4471e9ea7e0SNamjae Jeon name->len = 0; 4481e9ea7e0SNamjae Jeon *res = name; 4491e9ea7e0SNamjae Jeon } else { 4501e9ea7e0SNamjae Jeon kfree(name); 4511e9ea7e0SNamjae Jeon *res = NULL; 4521e9ea7e0SNamjae Jeon } 4531e9ea7e0SNamjae Jeon mref = le64_to_cpu(ie->data.dir.indexed_file); 4540a8ac0c1SNamjae Jeon kfree(kaddr); 4550a8ac0c1SNamjae Jeon iput(ia_vi); 4561e9ea7e0SNamjae Jeon return mref; 4571e9ea7e0SNamjae Jeon } 4581e9ea7e0SNamjae Jeon /* 4591e9ea7e0SNamjae Jeon * For a case insensitive mount, we also perform a case 4601e9ea7e0SNamjae Jeon * insensitive comparison (provided the file name is not in the 4611e9ea7e0SNamjae Jeon * POSIX namespace). If the comparison matches, and the name is 4621e9ea7e0SNamjae Jeon * in the WIN32 namespace, we cache the filename in *res so 4631e9ea7e0SNamjae Jeon * that the caller, ntfs_lookup(), can work on it. If the 4641e9ea7e0SNamjae Jeon * comparison matches, and the name is in the DOS namespace, we 4651e9ea7e0SNamjae Jeon * only cache the mft reference and the file name type (we set 4661e9ea7e0SNamjae Jeon * the name length to zero for simplicity). 4671e9ea7e0SNamjae Jeon */ 4680a8ac0c1SNamjae Jeon if ((!NVolCaseSensitive(vol) || 4690a8ac0c1SNamjae Jeon ie->key.file_name.file_name_type == FILE_NAME_DOS) && 4701e9ea7e0SNamjae Jeon ntfs_are_names_equal(uname, uname_len, 4710a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 4721e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 4730a8ac0c1SNamjae Jeon IGNORE_CASE, vol->upcase, 4740a8ac0c1SNamjae Jeon vol->upcase_len)) { 4750a8ac0c1SNamjae Jeon int name_size = sizeof(struct ntfs_name); 4761e9ea7e0SNamjae Jeon u8 type = ie->key.file_name.file_name_type; 4771e9ea7e0SNamjae Jeon u8 len = ie->key.file_name.file_name_length; 4781e9ea7e0SNamjae Jeon 4791e9ea7e0SNamjae Jeon /* Only one case insensitive matching name allowed. */ 4801e9ea7e0SNamjae Jeon if (name) { 4810a8ac0c1SNamjae Jeon ntfs_error(sb, 4820a8ac0c1SNamjae Jeon "Found already allocated name in phase 2. Please run chkdsk"); 4830a8ac0c1SNamjae Jeon kfree(kaddr); 4841e9ea7e0SNamjae Jeon goto dir_err_out; 4851e9ea7e0SNamjae Jeon } 4861e9ea7e0SNamjae Jeon 4871e9ea7e0SNamjae Jeon if (type != FILE_NAME_DOS) 4880a8ac0c1SNamjae Jeon name_size += len * sizeof(__le16); 4891e9ea7e0SNamjae Jeon name = kmalloc(name_size, GFP_NOFS); 4901e9ea7e0SNamjae Jeon if (!name) { 4911e9ea7e0SNamjae Jeon err = -ENOMEM; 4921e9ea7e0SNamjae Jeon goto unm_err_out; 4931e9ea7e0SNamjae Jeon } 4941e9ea7e0SNamjae Jeon name->mref = le64_to_cpu(ie->data.dir.indexed_file); 4951e9ea7e0SNamjae Jeon name->type = type; 4961e9ea7e0SNamjae Jeon if (type != FILE_NAME_DOS) { 4971e9ea7e0SNamjae Jeon name->len = len; 4981e9ea7e0SNamjae Jeon memcpy(name->name, ie->key.file_name.file_name, 4990a8ac0c1SNamjae Jeon len * sizeof(__le16)); 5001e9ea7e0SNamjae Jeon } else 5011e9ea7e0SNamjae Jeon name->len = 0; 5021e9ea7e0SNamjae Jeon *res = name; 5031e9ea7e0SNamjae Jeon } 5041e9ea7e0SNamjae Jeon /* 5051e9ea7e0SNamjae Jeon * Not a perfect match, need to do full blown collation so we 5061e9ea7e0SNamjae Jeon * know which way in the B+tree we have to go. 5071e9ea7e0SNamjae Jeon */ 5081e9ea7e0SNamjae Jeon rc = ntfs_collate_names(uname, uname_len, 5090a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 5101e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 1, 5111e9ea7e0SNamjae Jeon IGNORE_CASE, vol->upcase, vol->upcase_len); 5121e9ea7e0SNamjae Jeon /* 5131e9ea7e0SNamjae Jeon * If uname collates before the name of the current entry, there 5141e9ea7e0SNamjae Jeon * is definitely no such name in this index but we might need to 5151e9ea7e0SNamjae Jeon * descend into the B+tree so we just break out of the loop. 5161e9ea7e0SNamjae Jeon */ 5171e9ea7e0SNamjae Jeon if (rc == -1) 5181e9ea7e0SNamjae Jeon break; 5191e9ea7e0SNamjae Jeon /* The names are not equal, continue the search. */ 5201e9ea7e0SNamjae Jeon if (rc) 5211e9ea7e0SNamjae Jeon continue; 5221e9ea7e0SNamjae Jeon /* 5231e9ea7e0SNamjae Jeon * Names match with case insensitive comparison, now try the 5241e9ea7e0SNamjae Jeon * case sensitive comparison, which is required for proper 5251e9ea7e0SNamjae Jeon * collation. 5261e9ea7e0SNamjae Jeon */ 5271e9ea7e0SNamjae Jeon rc = ntfs_collate_names(uname, uname_len, 5280a8ac0c1SNamjae Jeon (__le16 *)&ie->key.file_name.file_name, 5291e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, 1, 5301e9ea7e0SNamjae Jeon CASE_SENSITIVE, vol->upcase, vol->upcase_len); 5311e9ea7e0SNamjae Jeon if (rc == -1) 5321e9ea7e0SNamjae Jeon break; 5331e9ea7e0SNamjae Jeon if (rc) 5341e9ea7e0SNamjae Jeon continue; 5351e9ea7e0SNamjae Jeon /* 5361e9ea7e0SNamjae Jeon * Perfect match, this will never happen as the 5371e9ea7e0SNamjae Jeon * ntfs_are_names_equal() call will have gotten a match but we 5381e9ea7e0SNamjae Jeon * still treat it correctly. 5391e9ea7e0SNamjae Jeon */ 5401e9ea7e0SNamjae Jeon goto found_it2; 5411e9ea7e0SNamjae Jeon } 5421e9ea7e0SNamjae Jeon /* 5431e9ea7e0SNamjae Jeon * We have finished with this index buffer without success. Check for 5441e9ea7e0SNamjae Jeon * the presence of a child node. 5451e9ea7e0SNamjae Jeon */ 5461e9ea7e0SNamjae Jeon if (ie->flags & INDEX_ENTRY_NODE) { 5471e9ea7e0SNamjae Jeon if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { 5480a8ac0c1SNamjae Jeon ntfs_error(sb, 549d9038d99SNamjae Jeon "Index entry with child node found in a leaf node in directory inode 0x%llx.", 5501e9ea7e0SNamjae Jeon dir_ni->mft_no); 5511e9ea7e0SNamjae Jeon goto unm_err_out; 5521e9ea7e0SNamjae Jeon } 5531e9ea7e0SNamjae Jeon /* Child node present, descend into it. */ 5541e9ea7e0SNamjae Jeon old_vcn = vcn; 5550a8ac0c1SNamjae Jeon vcn = le64_to_cpup((__le64 *)((u8 *)ie + 5561e9ea7e0SNamjae Jeon le16_to_cpu(ie->length) - 8)); 5571e9ea7e0SNamjae Jeon if (vcn >= 0) { 5580a8ac0c1SNamjae Jeon /* 5590a8ac0c1SNamjae Jeon * If vcn is in the same page cache page as old_vcn we 5600a8ac0c1SNamjae Jeon * recycle the mapped page. 5610a8ac0c1SNamjae Jeon */ 5620a8ac0c1SNamjae Jeon if (ntfs_cluster_to_pidx(vol, old_vcn) == 5630a8ac0c1SNamjae Jeon ntfs_cluster_to_pidx(vol, vcn)) 5641e9ea7e0SNamjae Jeon goto fast_descend_into_child_node; 5650a8ac0c1SNamjae Jeon kfree(kaddr); 5660a8ac0c1SNamjae Jeon kaddr = NULL; 5671e9ea7e0SNamjae Jeon goto descend_into_child_node; 5681e9ea7e0SNamjae Jeon } 569d9038d99SNamjae Jeon ntfs_error(sb, "Negative child node vcn in directory inode 0x%llx.", 5700a8ac0c1SNamjae Jeon dir_ni->mft_no); 5711e9ea7e0SNamjae Jeon goto unm_err_out; 5721e9ea7e0SNamjae Jeon } 5731e9ea7e0SNamjae Jeon /* 5741e9ea7e0SNamjae Jeon * No child node present, return -ENOENT, unless we have got a matching 5751e9ea7e0SNamjae Jeon * name cached in name in which case return the mft reference 5761e9ea7e0SNamjae Jeon * associated with it. 5771e9ea7e0SNamjae Jeon */ 5781e9ea7e0SNamjae Jeon if (name) { 5790a8ac0c1SNamjae Jeon kfree(kaddr); 5800a8ac0c1SNamjae Jeon iput(ia_vi); 5811e9ea7e0SNamjae Jeon return name->mref; 5821e9ea7e0SNamjae Jeon } 5831e9ea7e0SNamjae Jeon ntfs_debug("Entry not found."); 5841e9ea7e0SNamjae Jeon err = -ENOENT; 5851e9ea7e0SNamjae Jeon unm_err_out: 5860a8ac0c1SNamjae Jeon kfree(kaddr); 5871e9ea7e0SNamjae Jeon err_out: 5881e9ea7e0SNamjae Jeon if (!err) 5891e9ea7e0SNamjae Jeon err = -EIO; 5901e9ea7e0SNamjae Jeon if (ctx) 5911e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 5921e9ea7e0SNamjae Jeon if (m) 5931e9ea7e0SNamjae Jeon unmap_mft_record(dir_ni); 5941e9ea7e0SNamjae Jeon kfree(name); 5951e9ea7e0SNamjae Jeon *res = NULL; 5967cf4b3c7SHyunchul Lee if (!IS_ERR_OR_NULL(ia_vi)) 5970a8ac0c1SNamjae Jeon iput(ia_vi); 5981e9ea7e0SNamjae Jeon return ERR_MREF(err); 5991e9ea7e0SNamjae Jeon dir_err_out: 6001e9ea7e0SNamjae Jeon ntfs_error(sb, "Corrupt directory. Aborting lookup."); 6011e9ea7e0SNamjae Jeon goto err_out; 6021e9ea7e0SNamjae Jeon } 6031e9ea7e0SNamjae Jeon 6041e9ea7e0SNamjae Jeon /* 6051e9ea7e0SNamjae Jeon * ntfs_filldir - ntfs specific filldir method 6061e9ea7e0SNamjae Jeon * @vol: current ntfs volume 6071e9ea7e0SNamjae Jeon * @ndir: ntfs inode of current directory 6081e9ea7e0SNamjae Jeon * @ia_page: page in which the index allocation buffer @ie is in resides 6091e9ea7e0SNamjae Jeon * @ie: current index entry 6101e9ea7e0SNamjae Jeon * @name: buffer to use for the converted name 6111e9ea7e0SNamjae Jeon * @actor: what to feed the entries to 6121e9ea7e0SNamjae Jeon * 6131e9ea7e0SNamjae Jeon * Convert the Unicode @name to the loaded NLS and pass it to the @filldir 6141e9ea7e0SNamjae Jeon * callback. 6151e9ea7e0SNamjae Jeon * 6161e9ea7e0SNamjae Jeon * If @ia_page is not NULL it is the locked page containing the index 6171e9ea7e0SNamjae Jeon * allocation block containing the index entry @ie. 6181e9ea7e0SNamjae Jeon * 6191e9ea7e0SNamjae Jeon * Note, we drop (and then reacquire) the page lock on @ia_page across the 6201e9ea7e0SNamjae Jeon * @filldir() call otherwise we would deadlock with NFSd when it calls ->lookup 6211e9ea7e0SNamjae Jeon * since ntfs_lookup() will lock the same page. As an optimization, we do not 6221e9ea7e0SNamjae Jeon * retake the lock if we are returning a non-zero value as ntfs_readdir() 6231e9ea7e0SNamjae Jeon * would need to drop the lock immediately anyway. 6241e9ea7e0SNamjae Jeon */ 6250a8ac0c1SNamjae Jeon static inline int ntfs_filldir(struct ntfs_volume *vol, 6260a8ac0c1SNamjae Jeon struct ntfs_inode *ndir, struct page *ia_page, struct index_entry *ie, 6271e9ea7e0SNamjae Jeon u8 *name, struct dir_context *actor) 6281e9ea7e0SNamjae Jeon { 6291e9ea7e0SNamjae Jeon unsigned long mref; 6301e9ea7e0SNamjae Jeon int name_len; 6310a8ac0c1SNamjae Jeon unsigned int dt_type; 6320a8ac0c1SNamjae Jeon u8 name_type; 6331e9ea7e0SNamjae Jeon 6341e9ea7e0SNamjae Jeon name_type = ie->key.file_name.file_name_type; 6351e9ea7e0SNamjae Jeon if (name_type == FILE_NAME_DOS) { 6361e9ea7e0SNamjae Jeon ntfs_debug("Skipping DOS name space entry."); 6371e9ea7e0SNamjae Jeon return 0; 6381e9ea7e0SNamjae Jeon } 6391e9ea7e0SNamjae Jeon if (MREF_LE(ie->data.dir.indexed_file) == FILE_root) { 6401e9ea7e0SNamjae Jeon ntfs_debug("Skipping root directory self reference entry."); 6411e9ea7e0SNamjae Jeon return 0; 6421e9ea7e0SNamjae Jeon } 6431e9ea7e0SNamjae Jeon if (MREF_LE(ie->data.dir.indexed_file) < FILE_first_user && 6441e9ea7e0SNamjae Jeon !NVolShowSystemFiles(vol)) { 6451e9ea7e0SNamjae Jeon ntfs_debug("Skipping system file."); 6461e9ea7e0SNamjae Jeon return 0; 6471e9ea7e0SNamjae Jeon } 6480a8ac0c1SNamjae Jeon if (!NVolShowHiddenFiles(vol) && 6490a8ac0c1SNamjae Jeon (ie->key.file_name.file_attributes & FILE_ATTR_HIDDEN)) { 6500a8ac0c1SNamjae Jeon ntfs_debug("Skipping hidden file."); 6510a8ac0c1SNamjae Jeon return 0; 6520a8ac0c1SNamjae Jeon } 6530a8ac0c1SNamjae Jeon 6540a8ac0c1SNamjae Jeon name_len = ntfs_ucstonls(vol, (__le16 *)&ie->key.file_name.file_name, 6551e9ea7e0SNamjae Jeon ie->key.file_name.file_name_length, &name, 6561e9ea7e0SNamjae Jeon NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1); 6571e9ea7e0SNamjae Jeon if (name_len <= 0) { 6581e9ea7e0SNamjae Jeon ntfs_warning(vol->sb, "Skipping unrepresentable inode 0x%llx.", 6591e9ea7e0SNamjae Jeon (long long)MREF_LE(ie->data.dir.indexed_file)); 6601e9ea7e0SNamjae Jeon return 0; 6611e9ea7e0SNamjae Jeon } 6620a8ac0c1SNamjae Jeon 6630a8ac0c1SNamjae Jeon mref = MREF_LE(ie->data.dir.indexed_file); 6641e9ea7e0SNamjae Jeon if (ie->key.file_name.file_attributes & 6651e9ea7e0SNamjae Jeon FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT) 6661e9ea7e0SNamjae Jeon dt_type = DT_DIR; 6670a8ac0c1SNamjae Jeon else if (ie->key.file_name.file_attributes & FILE_ATTR_REPARSE_POINT) 6680a8ac0c1SNamjae Jeon dt_type = ntfs_reparse_tag_dt_types(vol, mref); 6691e9ea7e0SNamjae Jeon else 6701e9ea7e0SNamjae Jeon dt_type = DT_REG; 6710a8ac0c1SNamjae Jeon 6721e9ea7e0SNamjae Jeon /* 6731e9ea7e0SNamjae Jeon * Drop the page lock otherwise we deadlock with NFS when it calls 6741e9ea7e0SNamjae Jeon * ->lookup since ntfs_lookup() will lock the same page. 6751e9ea7e0SNamjae Jeon */ 6761e9ea7e0SNamjae Jeon if (ia_page) 6771e9ea7e0SNamjae Jeon unlock_page(ia_page); 6780a8ac0c1SNamjae Jeon ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode 0x%lx, DT_%s.", 6790a8ac0c1SNamjae Jeon name, name_len, actor->pos, mref, dt_type == DT_DIR ? "DIR" : "REG"); 6801e9ea7e0SNamjae Jeon if (!dir_emit(actor, name, name_len, mref, dt_type)) 6811e9ea7e0SNamjae Jeon return 1; 6821e9ea7e0SNamjae Jeon /* Relock the page but not if we are aborting ->readdir. */ 6831e9ea7e0SNamjae Jeon if (ia_page) 6841e9ea7e0SNamjae Jeon lock_page(ia_page); 6851e9ea7e0SNamjae Jeon return 0; 6861e9ea7e0SNamjae Jeon } 6871e9ea7e0SNamjae Jeon 6880a8ac0c1SNamjae Jeon struct ntfs_file_private { 6890a8ac0c1SNamjae Jeon void *key; 6900a8ac0c1SNamjae Jeon __le16 key_length; 6910a8ac0c1SNamjae Jeon bool end_in_iterate; 6920a8ac0c1SNamjae Jeon loff_t curr_pos; 6930a8ac0c1SNamjae Jeon }; 6940a8ac0c1SNamjae Jeon 6950a8ac0c1SNamjae Jeon struct ntfs_index_ra { 6960a8ac0c1SNamjae Jeon unsigned long start_index; 6970a8ac0c1SNamjae Jeon unsigned int count; 6980a8ac0c1SNamjae Jeon struct rb_node rb_node; 6990a8ac0c1SNamjae Jeon }; 7000a8ac0c1SNamjae Jeon 7010a8ac0c1SNamjae Jeon static void ntfs_insert_rb(struct ntfs_index_ra *nir, struct rb_root *root) 7020a8ac0c1SNamjae Jeon { 7030a8ac0c1SNamjae Jeon struct rb_node **new = &root->rb_node, *parent = NULL; 7040a8ac0c1SNamjae Jeon struct ntfs_index_ra *cnir; 7050a8ac0c1SNamjae Jeon 7060a8ac0c1SNamjae Jeon while (*new) { 7070a8ac0c1SNamjae Jeon parent = *new; 7080a8ac0c1SNamjae Jeon cnir = rb_entry(parent, struct ntfs_index_ra, rb_node); 7090a8ac0c1SNamjae Jeon if (nir->start_index < cnir->start_index) 7100a8ac0c1SNamjae Jeon new = &parent->rb_left; 7110a8ac0c1SNamjae Jeon else if (nir->start_index >= cnir->start_index + cnir->count) 7120a8ac0c1SNamjae Jeon new = &parent->rb_right; 7130a8ac0c1SNamjae Jeon else { 7140a8ac0c1SNamjae Jeon pr_err("nir start index : %ld, count : %d, cnir start_index : %ld, count : %d\n", 7150a8ac0c1SNamjae Jeon nir->start_index, nir->count, cnir->start_index, cnir->count); 7160a8ac0c1SNamjae Jeon return; 7170a8ac0c1SNamjae Jeon } 7180a8ac0c1SNamjae Jeon } 7190a8ac0c1SNamjae Jeon 7200a8ac0c1SNamjae Jeon rb_link_node(&nir->rb_node, parent, new); 7210a8ac0c1SNamjae Jeon rb_insert_color(&nir->rb_node, root); 7220a8ac0c1SNamjae Jeon } 7230a8ac0c1SNamjae Jeon 7240a8ac0c1SNamjae Jeon static int ntfs_ia_blocks_readahead(struct ntfs_inode *ia_ni, loff_t pos) 7250a8ac0c1SNamjae Jeon { 7260a8ac0c1SNamjae Jeon unsigned long dir_start_index, dir_end_index; 7270a8ac0c1SNamjae Jeon struct inode *ia_vi = VFS_I(ia_ni); 7280a8ac0c1SNamjae Jeon struct file_ra_state *dir_ra; 7290a8ac0c1SNamjae Jeon 7300a8ac0c1SNamjae Jeon dir_end_index = (i_size_read(ia_vi) + PAGE_SIZE - 1) >> PAGE_SHIFT; 7310a8ac0c1SNamjae Jeon dir_start_index = (pos + PAGE_SIZE - 1) >> PAGE_SHIFT; 7320a8ac0c1SNamjae Jeon 7330a8ac0c1SNamjae Jeon if (dir_start_index >= dir_end_index) 7340a8ac0c1SNamjae Jeon return 0; 7350a8ac0c1SNamjae Jeon 7360a8ac0c1SNamjae Jeon dir_ra = kzalloc(sizeof(*dir_ra), GFP_NOFS); 7370a8ac0c1SNamjae Jeon if (!dir_ra) 7380a8ac0c1SNamjae Jeon return -ENOMEM; 7390a8ac0c1SNamjae Jeon 7400a8ac0c1SNamjae Jeon file_ra_state_init(dir_ra, ia_vi->i_mapping); 7410a8ac0c1SNamjae Jeon dir_end_index = (i_size_read(ia_vi) + PAGE_SIZE - 1) >> PAGE_SHIFT; 7420a8ac0c1SNamjae Jeon dir_start_index = (pos + PAGE_SIZE - 1) >> PAGE_SHIFT; 7430a8ac0c1SNamjae Jeon dir_ra->ra_pages = dir_end_index - dir_start_index; 7440a8ac0c1SNamjae Jeon page_cache_sync_readahead(ia_vi->i_mapping, dir_ra, NULL, 7450a8ac0c1SNamjae Jeon dir_start_index, dir_end_index - dir_start_index); 7460a8ac0c1SNamjae Jeon kfree(dir_ra); 7470a8ac0c1SNamjae Jeon 7480a8ac0c1SNamjae Jeon return 0; 7490a8ac0c1SNamjae Jeon } 7500a8ac0c1SNamjae Jeon 7511e9ea7e0SNamjae Jeon static int ntfs_readdir(struct file *file, struct dir_context *actor) 7521e9ea7e0SNamjae Jeon { 7530a8ac0c1SNamjae Jeon struct inode *vdir = file_inode(file); 7541e9ea7e0SNamjae Jeon struct super_block *sb = vdir->i_sb; 7550a8ac0c1SNamjae Jeon struct ntfs_inode *ndir = NTFS_I(vdir); 7560a8ac0c1SNamjae Jeon struct ntfs_volume *vol = NTFS_SB(sb); 7570a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx = NULL; 7580a8ac0c1SNamjae Jeon struct ntfs_index_context *ictx = NULL; 7590a8ac0c1SNamjae Jeon u8 *name; 7600a8ac0c1SNamjae Jeon struct index_root *ir; 7610a8ac0c1SNamjae Jeon struct index_entry *next = NULL; 7620a8ac0c1SNamjae Jeon struct ntfs_file_private *private = NULL; 7630a8ac0c1SNamjae Jeon int err = 0; 7640a8ac0c1SNamjae Jeon loff_t ie_pos = 2; /* initialize it with dot and dotdot size */ 7650a8ac0c1SNamjae Jeon struct ntfs_index_ra *nir = NULL; 7660a8ac0c1SNamjae Jeon unsigned long index; 7670a8ac0c1SNamjae Jeon struct rb_root ra_root = RB_ROOT; 7680a8ac0c1SNamjae Jeon struct file_ra_state *ra; 7691e9ea7e0SNamjae Jeon 770e7d82353SNamjae Jeon ntfs_debug("Entering for inode 0x%llx, fpos 0x%llx.", 771e7d82353SNamjae Jeon ndir->mft_no, actor->pos); 7720a8ac0c1SNamjae Jeon 7730a8ac0c1SNamjae Jeon if (file->private_data) { 7740a8ac0c1SNamjae Jeon private = file->private_data; 7750a8ac0c1SNamjae Jeon 7760a8ac0c1SNamjae Jeon if (actor->pos != private->curr_pos) { 7770a8ac0c1SNamjae Jeon /* 7780a8ac0c1SNamjae Jeon * If actor->pos is different from the previous passed 7790a8ac0c1SNamjae Jeon * one, Discard the private->key and fill dirent buffer 7800a8ac0c1SNamjae Jeon * with linear lookup. 7810a8ac0c1SNamjae Jeon */ 7820a8ac0c1SNamjae Jeon kfree(private->key); 7830a8ac0c1SNamjae Jeon private->key = NULL; 7840a8ac0c1SNamjae Jeon private->end_in_iterate = false; 7850a8ac0c1SNamjae Jeon } else if (private->end_in_iterate) { 7860a8ac0c1SNamjae Jeon kfree(private->key); 7870a8ac0c1SNamjae Jeon kfree(file->private_data); 7880a8ac0c1SNamjae Jeon file->private_data = NULL; 7891e9ea7e0SNamjae Jeon return 0; 7900a8ac0c1SNamjae Jeon } 7910a8ac0c1SNamjae Jeon } 7920a8ac0c1SNamjae Jeon 7931e9ea7e0SNamjae Jeon /* Emulate . and .. for all directories. */ 7941e9ea7e0SNamjae Jeon if (!dir_emit_dots(file, actor)) 7951e9ea7e0SNamjae Jeon return 0; 7960a8ac0c1SNamjae Jeon 7971e9ea7e0SNamjae Jeon /* 7981e9ea7e0SNamjae Jeon * Allocate a buffer to store the current name being processed 7991e9ea7e0SNamjae Jeon * converted to format determined by current NLS. 8001e9ea7e0SNamjae Jeon */ 8011e9ea7e0SNamjae Jeon name = kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1, GFP_NOFS); 8020a8ac0c1SNamjae Jeon if (unlikely(!name)) 8030a8ac0c1SNamjae Jeon return -ENOMEM; 8040a8ac0c1SNamjae Jeon 8050a8ac0c1SNamjae Jeon mutex_lock_nested(&ndir->mrec_lock, NTFS_INODE_MUTEX_PARENT); 8060a8ac0c1SNamjae Jeon ictx = ntfs_index_ctx_get(ndir, I30, 4); 8070a8ac0c1SNamjae Jeon if (!ictx) { 8080a8ac0c1SNamjae Jeon kfree(name); 8090a8ac0c1SNamjae Jeon mutex_unlock(&ndir->mrec_lock); 8100a8ac0c1SNamjae Jeon return -ENOMEM; 8110a8ac0c1SNamjae Jeon } 8120a8ac0c1SNamjae Jeon 8130a8ac0c1SNamjae Jeon ra = kzalloc(sizeof(struct file_ra_state), GFP_NOFS); 8140a8ac0c1SNamjae Jeon if (!ra) { 8150a8ac0c1SNamjae Jeon kfree(name); 8160a8ac0c1SNamjae Jeon ntfs_index_ctx_put(ictx); 8170a8ac0c1SNamjae Jeon mutex_unlock(&ndir->mrec_lock); 8180a8ac0c1SNamjae Jeon return -ENOMEM; 8190a8ac0c1SNamjae Jeon } 8200a8ac0c1SNamjae Jeon file_ra_state_init(ra, vol->mft_ino->i_mapping); 8210a8ac0c1SNamjae Jeon 8220a8ac0c1SNamjae Jeon if (private && private->key) { 8230a8ac0c1SNamjae Jeon /* 8240a8ac0c1SNamjae Jeon * Find index witk private->key using ntfs_index_lookup() 8250a8ac0c1SNamjae Jeon * instead of linear index lookup. 8260a8ac0c1SNamjae Jeon */ 8270a8ac0c1SNamjae Jeon err = ntfs_index_lookup(private->key, 8280a8ac0c1SNamjae Jeon le16_to_cpu(private->key_length), 8290a8ac0c1SNamjae Jeon ictx); 8300a8ac0c1SNamjae Jeon if (!err) { 8310a8ac0c1SNamjae Jeon next = ictx->entry; 8320a8ac0c1SNamjae Jeon /* 8330a8ac0c1SNamjae Jeon * Update ie_pos with private->curr_pos 8340a8ac0c1SNamjae Jeon * to make next d_off of dirent correct. 8350a8ac0c1SNamjae Jeon */ 8360a8ac0c1SNamjae Jeon ie_pos = private->curr_pos; 8370a8ac0c1SNamjae Jeon 8380a8ac0c1SNamjae Jeon if (actor->pos > vol->mft_record_size && ictx->ia_ni) { 8390a8ac0c1SNamjae Jeon err = ntfs_ia_blocks_readahead(ictx->ia_ni, actor->pos); 8400a8ac0c1SNamjae Jeon if (err) 8410a8ac0c1SNamjae Jeon goto out; 8420a8ac0c1SNamjae Jeon } 8430a8ac0c1SNamjae Jeon 8440a8ac0c1SNamjae Jeon goto nextdir; 8450a8ac0c1SNamjae Jeon } else { 8460a8ac0c1SNamjae Jeon goto out; 8470a8ac0c1SNamjae Jeon } 8480a8ac0c1SNamjae Jeon } else if (!private) { 8490a8ac0c1SNamjae Jeon private = kzalloc(sizeof(struct ntfs_file_private), GFP_KERNEL); 8500a8ac0c1SNamjae Jeon if (!private) { 8511e9ea7e0SNamjae Jeon err = -ENOMEM; 8520a8ac0c1SNamjae Jeon goto out; 8531e9ea7e0SNamjae Jeon } 8540a8ac0c1SNamjae Jeon file->private_data = private; 8551e9ea7e0SNamjae Jeon } 8560a8ac0c1SNamjae Jeon 8570a8ac0c1SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ndir, NULL); 8580a8ac0c1SNamjae Jeon if (!ctx) { 8591e9ea7e0SNamjae Jeon err = -ENOMEM; 8600a8ac0c1SNamjae Jeon goto out; 8611e9ea7e0SNamjae Jeon } 8620a8ac0c1SNamjae Jeon 8631e9ea7e0SNamjae Jeon /* Find the index root attribute in the mft record. */ 8640a8ac0c1SNamjae Jeon if (ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0, 8650a8ac0c1SNamjae Jeon ctx)) { 866d9038d99SNamjae Jeon ntfs_error(sb, "Index root attribute missing in directory inode %llu", 8670a8ac0c1SNamjae Jeon ndir->mft_no); 8680a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 8691e9ea7e0SNamjae Jeon err = -ENOMEM; 8700a8ac0c1SNamjae Jeon goto out; 8711e9ea7e0SNamjae Jeon } 8720a8ac0c1SNamjae Jeon 8730a8ac0c1SNamjae Jeon /* Get to the index root value. */ 8740a8ac0c1SNamjae Jeon ir = (struct index_root *)((u8 *)ctx->attr + 8750a8ac0c1SNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 8760a8ac0c1SNamjae Jeon 8770a8ac0c1SNamjae Jeon ictx->ir = ir; 8780a8ac0c1SNamjae Jeon ictx->actx = ctx; 8790a8ac0c1SNamjae Jeon ictx->parent_vcn[ictx->pindex] = VCN_INDEX_ROOT_PARENT; 8800a8ac0c1SNamjae Jeon ictx->is_in_root = true; 8810a8ac0c1SNamjae Jeon ictx->parent_pos[ictx->pindex] = 0; 8820a8ac0c1SNamjae Jeon 8830a8ac0c1SNamjae Jeon ictx->block_size = le32_to_cpu(ir->index_block_size); 8840a8ac0c1SNamjae Jeon if (ictx->block_size < NTFS_BLOCK_SIZE) { 8850a8ac0c1SNamjae Jeon ntfs_error(sb, "Index block size (%d) is smaller than the sector size (%d)", 8860a8ac0c1SNamjae Jeon ictx->block_size, NTFS_BLOCK_SIZE); 8871e9ea7e0SNamjae Jeon err = -EIO; 8880a8ac0c1SNamjae Jeon goto out; 8890a8ac0c1SNamjae Jeon } 8900a8ac0c1SNamjae Jeon 8910a8ac0c1SNamjae Jeon if (vol->cluster_size <= ictx->block_size) 8920a8ac0c1SNamjae Jeon ictx->vcn_size_bits = vol->cluster_size_bits; 8930a8ac0c1SNamjae Jeon else 8940a8ac0c1SNamjae Jeon ictx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS; 8950a8ac0c1SNamjae Jeon 8960a8ac0c1SNamjae Jeon /* The first index entry. */ 8970a8ac0c1SNamjae Jeon next = (struct index_entry *)((u8 *)&ir->index + 8980a8ac0c1SNamjae Jeon le32_to_cpu(ir->index.entries_offset)); 8990a8ac0c1SNamjae Jeon 9000a8ac0c1SNamjae Jeon if (next->flags & INDEX_ENTRY_NODE) { 9010a8ac0c1SNamjae Jeon ictx->ia_ni = ntfs_ia_open(ictx, ictx->idx_ni); 9020a8ac0c1SNamjae Jeon if (!ictx->ia_ni) { 9030a8ac0c1SNamjae Jeon err = -EINVAL; 9040a8ac0c1SNamjae Jeon goto out; 9050a8ac0c1SNamjae Jeon } 9060a8ac0c1SNamjae Jeon 9070a8ac0c1SNamjae Jeon err = ntfs_ia_blocks_readahead(ictx->ia_ni, actor->pos); 9080a8ac0c1SNamjae Jeon if (err) 9090a8ac0c1SNamjae Jeon goto out; 9100a8ac0c1SNamjae Jeon } 9110a8ac0c1SNamjae Jeon 9120a8ac0c1SNamjae Jeon if (next->flags & INDEX_ENTRY_NODE) { 9130a8ac0c1SNamjae Jeon next = ntfs_index_walk_down(next, ictx); 9140a8ac0c1SNamjae Jeon if (!next) { 9150a8ac0c1SNamjae Jeon err = -EIO; 9160a8ac0c1SNamjae Jeon goto out; 9170a8ac0c1SNamjae Jeon } 9180a8ac0c1SNamjae Jeon } 9190a8ac0c1SNamjae Jeon 9200a8ac0c1SNamjae Jeon if (next && !(next->flags & INDEX_ENTRY_END)) 9210a8ac0c1SNamjae Jeon goto nextdir; 9220a8ac0c1SNamjae Jeon 9230a8ac0c1SNamjae Jeon while ((next = ntfs_index_next(next, ictx)) != NULL) { 9240a8ac0c1SNamjae Jeon nextdir: 9250a8ac0c1SNamjae Jeon /* Check the consistency of an index entry */ 9260a8ac0c1SNamjae Jeon if (ntfs_index_entry_inconsistent(ictx, vol, next, COLLATION_FILE_NAME, 9270a8ac0c1SNamjae Jeon ndir->mft_no)) { 9280a8ac0c1SNamjae Jeon err = -EIO; 9290a8ac0c1SNamjae Jeon goto out; 9300a8ac0c1SNamjae Jeon } 9310a8ac0c1SNamjae Jeon 9320a8ac0c1SNamjae Jeon if (ie_pos < actor->pos) { 9330a8ac0c1SNamjae Jeon ie_pos += le16_to_cpu(next->length); 9340a8ac0c1SNamjae Jeon continue; 9350a8ac0c1SNamjae Jeon } 9360a8ac0c1SNamjae Jeon 9370a8ac0c1SNamjae Jeon actor->pos = ie_pos; 9380a8ac0c1SNamjae Jeon 9390a8ac0c1SNamjae Jeon index = ntfs_mft_no_to_pidx(vol, 9400a8ac0c1SNamjae Jeon MREF_LE(next->data.dir.indexed_file)); 9410a8ac0c1SNamjae Jeon if (nir) { 9420a8ac0c1SNamjae Jeon struct ntfs_index_ra *cnir; 9430a8ac0c1SNamjae Jeon struct rb_node *node = ra_root.rb_node; 9440a8ac0c1SNamjae Jeon 9450a8ac0c1SNamjae Jeon if (nir->start_index <= index && 9460a8ac0c1SNamjae Jeon index < nir->start_index + nir->count) { 9470a8ac0c1SNamjae Jeon /* No behavior */ 9480a8ac0c1SNamjae Jeon goto filldir; 9490a8ac0c1SNamjae Jeon } 9500a8ac0c1SNamjae Jeon 9510a8ac0c1SNamjae Jeon while (node) { 9520a8ac0c1SNamjae Jeon cnir = rb_entry(node, struct ntfs_index_ra, rb_node); 9530a8ac0c1SNamjae Jeon if (cnir->start_index <= index && 9540a8ac0c1SNamjae Jeon index < cnir->start_index + cnir->count) { 9550a8ac0c1SNamjae Jeon goto filldir; 9560a8ac0c1SNamjae Jeon } else if (cnir->start_index + cnir->count == index) { 9570a8ac0c1SNamjae Jeon cnir->count++; 9580a8ac0c1SNamjae Jeon goto filldir; 9590a8ac0c1SNamjae Jeon } else if (!cnir->start_index && cnir->start_index - 1 == index) { 9600a8ac0c1SNamjae Jeon cnir->start_index = index; 9610a8ac0c1SNamjae Jeon goto filldir; 9620a8ac0c1SNamjae Jeon } 9630a8ac0c1SNamjae Jeon 9640a8ac0c1SNamjae Jeon if (index < cnir->start_index) 9650a8ac0c1SNamjae Jeon node = node->rb_left; 9660a8ac0c1SNamjae Jeon else if (index >= cnir->start_index + cnir->count) 9670a8ac0c1SNamjae Jeon node = node->rb_right; 9680a8ac0c1SNamjae Jeon } 9690a8ac0c1SNamjae Jeon 9700a8ac0c1SNamjae Jeon if (nir->start_index + nir->count == index) { 9710a8ac0c1SNamjae Jeon nir->count++; 9720a8ac0c1SNamjae Jeon } else if (!nir->start_index && nir->start_index - 1 == index) { 9730a8ac0c1SNamjae Jeon nir->start_index = index; 9740a8ac0c1SNamjae Jeon } else if (nir->count > 2) { 9750a8ac0c1SNamjae Jeon ntfs_insert_rb(nir, &ra_root); 9760a8ac0c1SNamjae Jeon nir = NULL; 9770a8ac0c1SNamjae Jeon } else { 9780a8ac0c1SNamjae Jeon nir->start_index = index; 9790a8ac0c1SNamjae Jeon nir->count = 1; 9800a8ac0c1SNamjae Jeon } 9810a8ac0c1SNamjae Jeon } 9820a8ac0c1SNamjae Jeon 9830a8ac0c1SNamjae Jeon if (!nir) { 9840a8ac0c1SNamjae Jeon nir = kzalloc(sizeof(struct ntfs_index_ra), GFP_KERNEL); 9850a8ac0c1SNamjae Jeon if (nir) { 9860a8ac0c1SNamjae Jeon nir->start_index = index; 9870a8ac0c1SNamjae Jeon nir->count = 1; 9880a8ac0c1SNamjae Jeon } 9890a8ac0c1SNamjae Jeon } 9900a8ac0c1SNamjae Jeon 9910a8ac0c1SNamjae Jeon filldir: 9920a8ac0c1SNamjae Jeon /* Submit the name to the filldir callback. */ 9930a8ac0c1SNamjae Jeon err = ntfs_filldir(vol, ndir, NULL, next, name, actor); 9940a8ac0c1SNamjae Jeon if (err) { 9950a8ac0c1SNamjae Jeon /* 9960a8ac0c1SNamjae Jeon * Store index key value to file private_data to start 9970a8ac0c1SNamjae Jeon * from current index offset on next round. 9980a8ac0c1SNamjae Jeon */ 9990a8ac0c1SNamjae Jeon private = file->private_data; 10000a8ac0c1SNamjae Jeon kfree(private->key); 10010a8ac0c1SNamjae Jeon private->key = kmalloc(le16_to_cpu(next->key_length), GFP_KERNEL); 10020a8ac0c1SNamjae Jeon if (!private->key) { 10030a8ac0c1SNamjae Jeon err = -ENOMEM; 10040a8ac0c1SNamjae Jeon goto out; 10050a8ac0c1SNamjae Jeon } 10060a8ac0c1SNamjae Jeon 10070a8ac0c1SNamjae Jeon memcpy(private->key, &next->key.file_name, le16_to_cpu(next->key_length)); 10080a8ac0c1SNamjae Jeon private->key_length = next->key_length; 10090a8ac0c1SNamjae Jeon break; 10100a8ac0c1SNamjae Jeon } 10110a8ac0c1SNamjae Jeon ie_pos += le16_to_cpu(next->length); 10120a8ac0c1SNamjae Jeon } 10130a8ac0c1SNamjae Jeon 10140a8ac0c1SNamjae Jeon if (!err) 10150a8ac0c1SNamjae Jeon private->end_in_iterate = true; 10160a8ac0c1SNamjae Jeon else 10170a8ac0c1SNamjae Jeon err = 0; 10180a8ac0c1SNamjae Jeon 10190a8ac0c1SNamjae Jeon private->curr_pos = actor->pos = ie_pos; 10200a8ac0c1SNamjae Jeon out: 10210a8ac0c1SNamjae Jeon while (!RB_EMPTY_ROOT(&ra_root)) { 10220a8ac0c1SNamjae Jeon struct ntfs_index_ra *cnir; 10230a8ac0c1SNamjae Jeon struct rb_node *node; 10240a8ac0c1SNamjae Jeon 10250a8ac0c1SNamjae Jeon node = rb_first(&ra_root); 10260a8ac0c1SNamjae Jeon cnir = rb_entry(node, struct ntfs_index_ra, rb_node); 10270a8ac0c1SNamjae Jeon ra->ra_pages = cnir->count; 10280a8ac0c1SNamjae Jeon page_cache_sync_readahead(vol->mft_ino->i_mapping, ra, NULL, 10290a8ac0c1SNamjae Jeon cnir->start_index, cnir->count); 10300a8ac0c1SNamjae Jeon rb_erase(node, &ra_root); 10310a8ac0c1SNamjae Jeon kfree(cnir); 10320a8ac0c1SNamjae Jeon } 10330a8ac0c1SNamjae Jeon 10340a8ac0c1SNamjae Jeon if (err) { 1035*4e59f8a1SHyunchul Lee if (private) { 10360a8ac0c1SNamjae Jeon private->curr_pos = actor->pos; 10370a8ac0c1SNamjae Jeon private->end_in_iterate = true; 1038*4e59f8a1SHyunchul Lee } 10390a8ac0c1SNamjae Jeon err = 0; 10400a8ac0c1SNamjae Jeon } 10410a8ac0c1SNamjae Jeon ntfs_index_ctx_put(ictx); 10420a8ac0c1SNamjae Jeon kfree(name); 10430a8ac0c1SNamjae Jeon kfree(nir); 10440a8ac0c1SNamjae Jeon kfree(ra); 10450a8ac0c1SNamjae Jeon mutex_unlock(&ndir->mrec_lock); 10461e9ea7e0SNamjae Jeon return err; 10471e9ea7e0SNamjae Jeon } 10481e9ea7e0SNamjae Jeon 10490a8ac0c1SNamjae Jeon int ntfs_check_empty_dir(struct ntfs_inode *ni, struct mft_record *ni_mrec) 10500a8ac0c1SNamjae Jeon { 10510a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx; 10520a8ac0c1SNamjae Jeon int ret = 0; 10530a8ac0c1SNamjae Jeon 10540a8ac0c1SNamjae Jeon if (!(ni_mrec->flags & MFT_RECORD_IS_DIRECTORY)) 10550a8ac0c1SNamjae Jeon return 0; 10560a8ac0c1SNamjae Jeon 10570a8ac0c1SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, NULL); 10580a8ac0c1SNamjae Jeon if (!ctx) { 10590a8ac0c1SNamjae Jeon ntfs_error(ni->vol->sb, "Failed to get search context"); 10600a8ac0c1SNamjae Jeon return -ENOMEM; 10610a8ac0c1SNamjae Jeon } 10620a8ac0c1SNamjae Jeon 10630a8ac0c1SNamjae Jeon /* Find the index root attribute in the mft record. */ 10640a8ac0c1SNamjae Jeon ret = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 10650a8ac0c1SNamjae Jeon 0, ctx); 10660a8ac0c1SNamjae Jeon if (ret) { 1067d9038d99SNamjae Jeon ntfs_error(ni->vol->sb, "Index root attribute missing in directory inode %llu", 1068d9038d99SNamjae Jeon ni->mft_no); 10690a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 10700a8ac0c1SNamjae Jeon return ret; 10710a8ac0c1SNamjae Jeon } 10720a8ac0c1SNamjae Jeon 10730a8ac0c1SNamjae Jeon /* Non-empty directory? */ 10740a8ac0c1SNamjae Jeon if (le32_to_cpu(ctx->attr->data.resident.value_length) != 10750a8ac0c1SNamjae Jeon sizeof(struct index_root) + sizeof(struct index_entry_header)) { 10760a8ac0c1SNamjae Jeon /* Both ENOTEMPTY and EEXIST are ok. We use the more common. */ 10770a8ac0c1SNamjae Jeon ret = -ENOTEMPTY; 10780a8ac0c1SNamjae Jeon ntfs_debug("Directory is not empty\n"); 10790a8ac0c1SNamjae Jeon } 10800a8ac0c1SNamjae Jeon 10810a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 10820a8ac0c1SNamjae Jeon 10830a8ac0c1SNamjae Jeon return ret; 10840a8ac0c1SNamjae Jeon } 10850a8ac0c1SNamjae Jeon 10860a8ac0c1SNamjae Jeon /* 10871e9ea7e0SNamjae Jeon * ntfs_dir_open - called when an inode is about to be opened 10881e9ea7e0SNamjae Jeon * @vi: inode to be opened 10891e9ea7e0SNamjae Jeon * @filp: file structure describing the inode 10901e9ea7e0SNamjae Jeon * 10911e9ea7e0SNamjae Jeon * Limit directory size to the page cache limit on architectures where unsigned 10921e9ea7e0SNamjae Jeon * long is 32-bits. This is the most we can do for now without overflowing the 10931e9ea7e0SNamjae Jeon * page cache page index. Doing it this way means we don't run into problems 10941e9ea7e0SNamjae Jeon * because of existing too large directories. It would be better to allow the 10951e9ea7e0SNamjae Jeon * user to read the accessible part of the directory but I doubt very much 10961e9ea7e0SNamjae Jeon * anyone is going to hit this check on a 32-bit architecture, so there is no 10971e9ea7e0SNamjae Jeon * point in adding the extra complexity required to support this. 10981e9ea7e0SNamjae Jeon * 10991e9ea7e0SNamjae Jeon * On 64-bit architectures, the check is hopefully optimized away by the 11001e9ea7e0SNamjae Jeon * compiler. 11011e9ea7e0SNamjae Jeon */ 11021e9ea7e0SNamjae Jeon static int ntfs_dir_open(struct inode *vi, struct file *filp) 11031e9ea7e0SNamjae Jeon { 11041e9ea7e0SNamjae Jeon if (sizeof(unsigned long) < 8) { 11051e9ea7e0SNamjae Jeon if (i_size_read(vi) > MAX_LFS_FILESIZE) 11061e9ea7e0SNamjae Jeon return -EFBIG; 11071e9ea7e0SNamjae Jeon } 11081e9ea7e0SNamjae Jeon return 0; 11091e9ea7e0SNamjae Jeon } 11101e9ea7e0SNamjae Jeon 11110a8ac0c1SNamjae Jeon static int ntfs_dir_release(struct inode *vi, struct file *filp) 11120a8ac0c1SNamjae Jeon { 11130a8ac0c1SNamjae Jeon if (filp->private_data) { 11140a8ac0c1SNamjae Jeon kfree(((struct ntfs_file_private *)filp->private_data)->key); 11150a8ac0c1SNamjae Jeon kfree(filp->private_data); 11160a8ac0c1SNamjae Jeon filp->private_data = NULL; 11170a8ac0c1SNamjae Jeon } 11180a8ac0c1SNamjae Jeon return 0; 11190a8ac0c1SNamjae Jeon } 11201e9ea7e0SNamjae Jeon 11210a8ac0c1SNamjae Jeon /* 11221e9ea7e0SNamjae Jeon * ntfs_dir_fsync - sync a directory to disk 11230a8ac0c1SNamjae Jeon * @filp: file describing the directory to be synced 11240a8ac0c1SNamjae Jeon * @start: start offset to be synced 11250a8ac0c1SNamjae Jeon * @end: end offset to be synced 11261e9ea7e0SNamjae Jeon * @datasync: if non-zero only flush user data and not metadata 11271e9ea7e0SNamjae Jeon * 11281e9ea7e0SNamjae Jeon * Data integrity sync of a directory to disk. Used for fsync, fdatasync, and 11291e9ea7e0SNamjae Jeon * msync system calls. This function is based on file.c::ntfs_file_fsync(). 11301e9ea7e0SNamjae Jeon * 11311e9ea7e0SNamjae Jeon * Write the mft record and all associated extent mft records as well as the 11321e9ea7e0SNamjae Jeon * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device. 11331e9ea7e0SNamjae Jeon * 11341e9ea7e0SNamjae Jeon * If @datasync is true, we do not wait on the inode(s) to be written out 11351e9ea7e0SNamjae Jeon * but we always wait on the page cache pages to be written out. 11361e9ea7e0SNamjae Jeon * 11371e9ea7e0SNamjae Jeon * Note: In the past @filp could be NULL so we ignore it as we don't need it 11381e9ea7e0SNamjae Jeon * anyway. 11391e9ea7e0SNamjae Jeon * 11401e9ea7e0SNamjae Jeon * Locking: Caller must hold i_mutex on the inode. 11411e9ea7e0SNamjae Jeon */ 11421e9ea7e0SNamjae Jeon static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, 11431e9ea7e0SNamjae Jeon int datasync) 11441e9ea7e0SNamjae Jeon { 11451e9ea7e0SNamjae Jeon struct inode *bmp_vi, *vi = filp->f_mapping->host; 11460a8ac0c1SNamjae Jeon struct ntfs_volume *vol = NTFS_I(vi)->vol; 11470a8ac0c1SNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 11480a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx; 11490a8ac0c1SNamjae Jeon struct inode *parent_vi, *ia_vi; 11501e9ea7e0SNamjae Jeon int err, ret; 11510a8ac0c1SNamjae Jeon struct ntfs_attr na; 11521e9ea7e0SNamjae Jeon 1153e7d82353SNamjae Jeon ntfs_debug("Entering for inode 0x%llx.", ni->mft_no); 11541e9ea7e0SNamjae Jeon 11550a8ac0c1SNamjae Jeon if (NVolShutdown(vol)) 11560a8ac0c1SNamjae Jeon return -EIO; 11570a8ac0c1SNamjae Jeon 11580a8ac0c1SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, NULL); 11590a8ac0c1SNamjae Jeon if (!ctx) 11600a8ac0c1SNamjae Jeon return -ENOMEM; 11610a8ac0c1SNamjae Jeon 11620a8ac0c1SNamjae Jeon mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL_CHILD); 11630a8ac0c1SNamjae Jeon while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx))) { 11640a8ac0c1SNamjae Jeon struct file_name_attr *fn = (struct file_name_attr *)((u8 *)ctx->attr + 11650a8ac0c1SNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 11660a8ac0c1SNamjae Jeon 11670a8ac0c1SNamjae Jeon if (MREF_LE(fn->parent_directory) == ni->mft_no) 11680a8ac0c1SNamjae Jeon continue; 11690a8ac0c1SNamjae Jeon 11700a8ac0c1SNamjae Jeon parent_vi = ntfs_iget(vi->i_sb, MREF_LE(fn->parent_directory)); 11710a8ac0c1SNamjae Jeon if (IS_ERR(parent_vi)) 11720a8ac0c1SNamjae Jeon continue; 11730a8ac0c1SNamjae Jeon mutex_lock_nested(&NTFS_I(parent_vi)->mrec_lock, NTFS_INODE_MUTEX_NORMAL); 11740a8ac0c1SNamjae Jeon ia_vi = ntfs_index_iget(parent_vi, I30, 4); 11750a8ac0c1SNamjae Jeon mutex_unlock(&NTFS_I(parent_vi)->mrec_lock); 11760a8ac0c1SNamjae Jeon if (IS_ERR(ia_vi)) { 11770a8ac0c1SNamjae Jeon iput(parent_vi); 11780a8ac0c1SNamjae Jeon continue; 11790a8ac0c1SNamjae Jeon } 11800a8ac0c1SNamjae Jeon write_inode_now(ia_vi, 1); 11810a8ac0c1SNamjae Jeon iput(ia_vi); 11820a8ac0c1SNamjae Jeon write_inode_now(parent_vi, 1); 11830a8ac0c1SNamjae Jeon iput(parent_vi); 11840a8ac0c1SNamjae Jeon } 11850a8ac0c1SNamjae Jeon mutex_unlock(&ni->mrec_lock); 11860a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 11870a8ac0c1SNamjae Jeon 11881e9ea7e0SNamjae Jeon err = file_write_and_wait_range(filp, start, end); 11891e9ea7e0SNamjae Jeon if (err) 11901e9ea7e0SNamjae Jeon return err; 11911e9ea7e0SNamjae Jeon inode_lock(vi); 11921e9ea7e0SNamjae Jeon 11931e9ea7e0SNamjae Jeon /* If the bitmap attribute inode is in memory sync it, too. */ 11941e9ea7e0SNamjae Jeon na.mft_no = vi->i_ino; 11951e9ea7e0SNamjae Jeon na.type = AT_BITMAP; 11961e9ea7e0SNamjae Jeon na.name = I30; 11971e9ea7e0SNamjae Jeon na.name_len = 4; 11981e9ea7e0SNamjae Jeon bmp_vi = ilookup5(vi->i_sb, vi->i_ino, ntfs_test_inode, &na); 11991e9ea7e0SNamjae Jeon if (bmp_vi) { 12001e9ea7e0SNamjae Jeon write_inode_now(bmp_vi, !datasync); 12011e9ea7e0SNamjae Jeon iput(bmp_vi); 12021e9ea7e0SNamjae Jeon } 12031e9ea7e0SNamjae Jeon ret = __ntfs_write_inode(vi, 1); 12040a8ac0c1SNamjae Jeon 12051e9ea7e0SNamjae Jeon write_inode_now(vi, !datasync); 12060a8ac0c1SNamjae Jeon 12070a8ac0c1SNamjae Jeon write_inode_now(vol->mftbmp_ino, 1); 12080a8ac0c1SNamjae Jeon down_write(&vol->lcnbmp_lock); 12090a8ac0c1SNamjae Jeon write_inode_now(vol->lcnbmp_ino, 1); 12100a8ac0c1SNamjae Jeon up_write(&vol->lcnbmp_lock); 12110a8ac0c1SNamjae Jeon write_inode_now(vol->mft_ino, 1); 12120a8ac0c1SNamjae Jeon 12131e9ea7e0SNamjae Jeon err = sync_blockdev(vi->i_sb->s_bdev); 12141e9ea7e0SNamjae Jeon if (unlikely(err && !ret)) 12151e9ea7e0SNamjae Jeon ret = err; 12161e9ea7e0SNamjae Jeon if (likely(!ret)) 12171e9ea7e0SNamjae Jeon ntfs_debug("Done."); 12181e9ea7e0SNamjae Jeon else 12190a8ac0c1SNamjae Jeon ntfs_warning(vi->i_sb, 1220e7d82353SNamjae Jeon "Failed to f%ssync inode 0x%llx. Error %u.", 1221e7d82353SNamjae Jeon datasync ? "data" : "", ni->mft_no, -ret); 12221e9ea7e0SNamjae Jeon inode_unlock(vi); 12231e9ea7e0SNamjae Jeon return ret; 12241e9ea7e0SNamjae Jeon } 12251e9ea7e0SNamjae Jeon 12261e9ea7e0SNamjae Jeon const struct file_operations ntfs_dir_ops = { 12271e9ea7e0SNamjae Jeon .llseek = generic_file_llseek, /* Seek inside directory. */ 12281e9ea7e0SNamjae Jeon .read = generic_read_dir, /* Return -EISDIR. */ 12290a8ac0c1SNamjae Jeon .iterate_shared = ntfs_readdir, /* Read directory contents. */ 12301e9ea7e0SNamjae Jeon .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ 12311e9ea7e0SNamjae Jeon .open = ntfs_dir_open, /* Open directory. */ 12320a8ac0c1SNamjae Jeon .release = ntfs_dir_release, 12330a8ac0c1SNamjae Jeon .unlocked_ioctl = ntfs_ioctl, 12340a8ac0c1SNamjae Jeon #ifdef CONFIG_COMPAT 12350a8ac0c1SNamjae Jeon .compat_ioctl = ntfs_compat_ioctl, 12360a8ac0c1SNamjae Jeon #endif 12370a8ac0c1SNamjae Jeon .setlease = generic_setlease, 12381e9ea7e0SNamjae Jeon }; 1239