11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 30a8ac0c1SNamjae Jeon * NTFS kernel index handling. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2004-2005 Anton Altaparmakov 60a8ac0c1SNamjae Jeon * Copyright (c) 2025 LG Electronics Co., Ltd. 70a8ac0c1SNamjae Jeon * 80a8ac0c1SNamjae Jeon * Part of this file is based on code from the NTFS-3G. 90a8ac0c1SNamjae Jeon * and is copyrighted by the respective authors below: 100a8ac0c1SNamjae Jeon * Copyright (c) 2004-2005 Anton Altaparmakov 110a8ac0c1SNamjae Jeon * Copyright (c) 2004-2005 Richard Russon 120a8ac0c1SNamjae Jeon * Copyright (c) 2005-2006 Yura Pakhuchiy 130a8ac0c1SNamjae Jeon * Copyright (c) 2005-2008 Szabolcs Szakacsits 140a8ac0c1SNamjae Jeon * Copyright (c) 2007-2021 Jean-Pierre Andre 151e9ea7e0SNamjae Jeon */ 161e9ea7e0SNamjae Jeon 171e9ea7e0SNamjae Jeon #include "collate.h" 181e9ea7e0SNamjae Jeon #include "index.h" 191e9ea7e0SNamjae Jeon #include "ntfs.h" 200a8ac0c1SNamjae Jeon #include "attrlist.h" 211e9ea7e0SNamjae Jeon 220a8ac0c1SNamjae Jeon /* 230a8ac0c1SNamjae Jeon * ntfs_index_entry_inconsistent - Check the consistency of an index entry 241e9ea7e0SNamjae Jeon * 250a8ac0c1SNamjae Jeon * Make sure data and key do not overflow from entry. 260a8ac0c1SNamjae Jeon * As a side effect, an entry with zero length is rejected. 270a8ac0c1SNamjae Jeon * This entry must be a full one (no INDEX_ENTRY_END flag), and its 280a8ac0c1SNamjae Jeon * length must have been checked beforehand to not overflow from the 290a8ac0c1SNamjae Jeon * index record. 301e9ea7e0SNamjae Jeon */ 310a8ac0c1SNamjae Jeon int ntfs_index_entry_inconsistent(struct ntfs_index_context *icx, 320a8ac0c1SNamjae Jeon struct ntfs_volume *vol, const struct index_entry *ie, 330a8ac0c1SNamjae Jeon __le32 collation_rule, u64 inum) 341e9ea7e0SNamjae Jeon { 350a8ac0c1SNamjae Jeon if (icx) { 360a8ac0c1SNamjae Jeon struct index_header *ih; 370a8ac0c1SNamjae Jeon u8 *ie_start, *ie_end; 381e9ea7e0SNamjae Jeon 390a8ac0c1SNamjae Jeon if (icx->is_in_root) 400a8ac0c1SNamjae Jeon ih = &icx->ir->index; 410a8ac0c1SNamjae Jeon else 420a8ac0c1SNamjae Jeon ih = &icx->ib->index; 430a8ac0c1SNamjae Jeon 440a8ac0c1SNamjae Jeon if ((le32_to_cpu(ih->index_length) > le32_to_cpu(ih->allocated_size)) || 450a8ac0c1SNamjae Jeon (le32_to_cpu(ih->index_length) > icx->block_size)) { 460a8ac0c1SNamjae Jeon ntfs_error(vol->sb, "%s Index entry(0x%p)'s length is too big.", 470a8ac0c1SNamjae Jeon icx->is_in_root ? "Index root" : "Index block", 480a8ac0c1SNamjae Jeon (u8 *)icx->entry); 490a8ac0c1SNamjae Jeon return -EINVAL; 501e9ea7e0SNamjae Jeon } 511e9ea7e0SNamjae Jeon 520a8ac0c1SNamjae Jeon ie_start = (u8 *)ih + le32_to_cpu(ih->entries_offset); 530a8ac0c1SNamjae Jeon ie_end = (u8 *)ih + le32_to_cpu(ih->index_length); 540a8ac0c1SNamjae Jeon 550a8ac0c1SNamjae Jeon if (ie_start > (u8 *)ie || 560a8ac0c1SNamjae Jeon ie_end <= (u8 *)ie + le16_to_cpu(ie->length) || 570a8ac0c1SNamjae Jeon le16_to_cpu(ie->length) > le32_to_cpu(ih->allocated_size) || 580a8ac0c1SNamjae Jeon le16_to_cpu(ie->length) > icx->block_size) { 590a8ac0c1SNamjae Jeon ntfs_error(vol->sb, "Index entry(0x%p) is out of range from %s", 600a8ac0c1SNamjae Jeon (u8 *)icx->entry, 610a8ac0c1SNamjae Jeon icx->is_in_root ? "index root" : "index block"); 620a8ac0c1SNamjae Jeon return -EIO; 630a8ac0c1SNamjae Jeon } 640a8ac0c1SNamjae Jeon } 650a8ac0c1SNamjae Jeon 660a8ac0c1SNamjae Jeon if (ie->key_length && 670a8ac0c1SNamjae Jeon ((le16_to_cpu(ie->key_length) + offsetof(struct index_entry, key)) > 680a8ac0c1SNamjae Jeon le16_to_cpu(ie->length))) { 690a8ac0c1SNamjae Jeon ntfs_error(vol->sb, "Overflow from index entry in inode %lld\n", 700a8ac0c1SNamjae Jeon (long long)inum); 710a8ac0c1SNamjae Jeon return -EIO; 720a8ac0c1SNamjae Jeon 731e9ea7e0SNamjae Jeon } else { 740a8ac0c1SNamjae Jeon if (collation_rule == COLLATION_FILE_NAME) { 750a8ac0c1SNamjae Jeon if ((offsetof(struct index_entry, key.file_name.file_name) + 760a8ac0c1SNamjae Jeon ie->key.file_name.file_name_length * sizeof(__le16)) > 770a8ac0c1SNamjae Jeon le16_to_cpu(ie->length)) { 780a8ac0c1SNamjae Jeon ntfs_error(vol->sb, 790a8ac0c1SNamjae Jeon "File name overflow from index entry in inode %lld\n", 800a8ac0c1SNamjae Jeon (long long)inum); 810a8ac0c1SNamjae Jeon return -EIO; 820a8ac0c1SNamjae Jeon } 830a8ac0c1SNamjae Jeon } else { 840a8ac0c1SNamjae Jeon if (ie->data.vi.data_length && 850a8ac0c1SNamjae Jeon ((le16_to_cpu(ie->data.vi.data_offset) + 860a8ac0c1SNamjae Jeon le16_to_cpu(ie->data.vi.data_length)) > 870a8ac0c1SNamjae Jeon le16_to_cpu(ie->length))) { 880a8ac0c1SNamjae Jeon ntfs_error(vol->sb, 890a8ac0c1SNamjae Jeon "Data overflow from index entry in inode %lld\n", 900a8ac0c1SNamjae Jeon (long long)inum); 910a8ac0c1SNamjae Jeon return -EIO; 921e9ea7e0SNamjae Jeon } 931e9ea7e0SNamjae Jeon } 941e9ea7e0SNamjae Jeon } 951e9ea7e0SNamjae Jeon 960a8ac0c1SNamjae Jeon return 0; 970a8ac0c1SNamjae Jeon } 980a8ac0c1SNamjae Jeon 990a8ac0c1SNamjae Jeon /* 1000a8ac0c1SNamjae Jeon * ntfs_index_entry_mark_dirty - mark an index entry dirty 1010a8ac0c1SNamjae Jeon * @ictx: ntfs index context describing the index entry 1021e9ea7e0SNamjae Jeon * 1030a8ac0c1SNamjae Jeon * Mark the index entry described by the index entry context @ictx dirty. 1041e9ea7e0SNamjae Jeon * 1050a8ac0c1SNamjae Jeon * If the index entry is in the index root attribute, simply mark the inode 1060a8ac0c1SNamjae Jeon * containing the index root attribute dirty. This ensures the mftrecord, and 1070a8ac0c1SNamjae Jeon * hence the index root attribute, will be written out to disk later. 1081e9ea7e0SNamjae Jeon * 1090a8ac0c1SNamjae Jeon * If the index entry is in an index block belonging to the index allocation 1100a8ac0c1SNamjae Jeon * attribute, set ib_dirty to true, thus index block will be updated during 1110a8ac0c1SNamjae Jeon * ntfs_index_ctx_put. 1121e9ea7e0SNamjae Jeon */ 1130a8ac0c1SNamjae Jeon void ntfs_index_entry_mark_dirty(struct ntfs_index_context *ictx) 1141e9ea7e0SNamjae Jeon { 1150a8ac0c1SNamjae Jeon if (ictx->is_in_root) 1160a8ac0c1SNamjae Jeon mark_mft_record_dirty(ictx->actx->ntfs_ino); 1170a8ac0c1SNamjae Jeon else if (ictx->ib) 1180a8ac0c1SNamjae Jeon ictx->ib_dirty = true; 1190a8ac0c1SNamjae Jeon } 1201e9ea7e0SNamjae Jeon 1210a8ac0c1SNamjae Jeon static s64 ntfs_ib_vcn_to_pos(struct ntfs_index_context *icx, s64 vcn) 1220a8ac0c1SNamjae Jeon { 1230a8ac0c1SNamjae Jeon return vcn << icx->vcn_size_bits; 1241e9ea7e0SNamjae Jeon } 1250a8ac0c1SNamjae Jeon 1260a8ac0c1SNamjae Jeon static s64 ntfs_ib_pos_to_vcn(struct ntfs_index_context *icx, s64 pos) 1270a8ac0c1SNamjae Jeon { 1280a8ac0c1SNamjae Jeon return pos >> icx->vcn_size_bits; 1291e9ea7e0SNamjae Jeon } 1300a8ac0c1SNamjae Jeon 1310a8ac0c1SNamjae Jeon static int ntfs_ib_write(struct ntfs_index_context *icx, struct index_block *ib) 1320a8ac0c1SNamjae Jeon { 1330a8ac0c1SNamjae Jeon s64 ret, vcn = le64_to_cpu(ib->index_block_vcn); 1340a8ac0c1SNamjae Jeon 1350a8ac0c1SNamjae Jeon ntfs_debug("vcn: %lld\n", vcn); 1360a8ac0c1SNamjae Jeon 1370a8ac0c1SNamjae Jeon ret = pre_write_mst_fixup((struct ntfs_record *)ib, icx->block_size); 1380a8ac0c1SNamjae Jeon if (ret) 1390a8ac0c1SNamjae Jeon return -EIO; 1400a8ac0c1SNamjae Jeon 1410a8ac0c1SNamjae Jeon ret = ntfs_inode_attr_pwrite(VFS_I(icx->ia_ni), 1420a8ac0c1SNamjae Jeon ntfs_ib_vcn_to_pos(icx, vcn), icx->block_size, 1430a8ac0c1SNamjae Jeon (u8 *)ib, icx->sync_write); 1440a8ac0c1SNamjae Jeon if (ret != icx->block_size) { 1450a8ac0c1SNamjae Jeon ntfs_debug("Failed to write index block %lld, inode %llu", 1460a8ac0c1SNamjae Jeon vcn, (unsigned long long)icx->idx_ni->mft_no); 1470a8ac0c1SNamjae Jeon return ret; 1480a8ac0c1SNamjae Jeon } 1490a8ac0c1SNamjae Jeon 1500a8ac0c1SNamjae Jeon return 0; 1510a8ac0c1SNamjae Jeon } 1520a8ac0c1SNamjae Jeon 1530a8ac0c1SNamjae Jeon static int ntfs_icx_ib_write(struct ntfs_index_context *icx) 1540a8ac0c1SNamjae Jeon { 1550a8ac0c1SNamjae Jeon int err; 1560a8ac0c1SNamjae Jeon 1570a8ac0c1SNamjae Jeon err = ntfs_ib_write(icx, icx->ib); 1580a8ac0c1SNamjae Jeon if (err) 1590a8ac0c1SNamjae Jeon return err; 1600a8ac0c1SNamjae Jeon 1610a8ac0c1SNamjae Jeon icx->ib_dirty = false; 1620a8ac0c1SNamjae Jeon 1630a8ac0c1SNamjae Jeon return 0; 1640a8ac0c1SNamjae Jeon } 1650a8ac0c1SNamjae Jeon 1660a8ac0c1SNamjae Jeon int ntfs_icx_ib_sync_write(struct ntfs_index_context *icx) 1670a8ac0c1SNamjae Jeon { 1680a8ac0c1SNamjae Jeon int ret; 1690a8ac0c1SNamjae Jeon 1700a8ac0c1SNamjae Jeon if (icx->ib_dirty == false) 1710a8ac0c1SNamjae Jeon return 0; 1720a8ac0c1SNamjae Jeon 1730a8ac0c1SNamjae Jeon icx->sync_write = true; 1740a8ac0c1SNamjae Jeon 1750a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, icx->ib); 1760a8ac0c1SNamjae Jeon if (!ret) { 1770a8ac0c1SNamjae Jeon kvfree(icx->ib); 1780a8ac0c1SNamjae Jeon icx->ib = NULL; 1790a8ac0c1SNamjae Jeon icx->ib_dirty = false; 1800a8ac0c1SNamjae Jeon } else { 1810a8ac0c1SNamjae Jeon post_write_mst_fixup((struct ntfs_record *)icx->ib); 1820a8ac0c1SNamjae Jeon icx->sync_write = false; 1830a8ac0c1SNamjae Jeon } 1840a8ac0c1SNamjae Jeon 1850a8ac0c1SNamjae Jeon return ret; 1860a8ac0c1SNamjae Jeon } 1870a8ac0c1SNamjae Jeon 1880a8ac0c1SNamjae Jeon /* 1890a8ac0c1SNamjae Jeon * ntfs_index_ctx_get - allocate and initialize a new index context 1900a8ac0c1SNamjae Jeon * @ni: ntfs inode with which to initialize the context 1910a8ac0c1SNamjae Jeon * @name: name of the which context describes 1920a8ac0c1SNamjae Jeon * @name_len: length of the index name 1930a8ac0c1SNamjae Jeon * 1940a8ac0c1SNamjae Jeon * Allocate a new index context, initialize it with @ni and return it. 1950a8ac0c1SNamjae Jeon * Return NULL if allocation failed. 1960a8ac0c1SNamjae Jeon */ 1970a8ac0c1SNamjae Jeon struct ntfs_index_context *ntfs_index_ctx_get(struct ntfs_inode *ni, 1980a8ac0c1SNamjae Jeon __le16 *name, u32 name_len) 1990a8ac0c1SNamjae Jeon { 2000a8ac0c1SNamjae Jeon struct ntfs_index_context *icx; 2010a8ac0c1SNamjae Jeon 2020a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 2030a8ac0c1SNamjae Jeon 2040a8ac0c1SNamjae Jeon if (!ni) 2050a8ac0c1SNamjae Jeon return NULL; 2060a8ac0c1SNamjae Jeon 2070a8ac0c1SNamjae Jeon if (ni->nr_extents == -1) 2080a8ac0c1SNamjae Jeon ni = ni->ext.base_ntfs_ino; 2090a8ac0c1SNamjae Jeon 2100a8ac0c1SNamjae Jeon icx = kmem_cache_alloc(ntfs_index_ctx_cache, GFP_NOFS); 2110a8ac0c1SNamjae Jeon if (icx) 2120a8ac0c1SNamjae Jeon *icx = (struct ntfs_index_context) { 2130a8ac0c1SNamjae Jeon .idx_ni = ni, 2140a8ac0c1SNamjae Jeon .name = name, 2150a8ac0c1SNamjae Jeon .name_len = name_len, 2160a8ac0c1SNamjae Jeon }; 2170a8ac0c1SNamjae Jeon return icx; 2180a8ac0c1SNamjae Jeon } 2190a8ac0c1SNamjae Jeon 2200a8ac0c1SNamjae Jeon static void ntfs_index_ctx_free(struct ntfs_index_context *icx) 2210a8ac0c1SNamjae Jeon { 2220a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 2230a8ac0c1SNamjae Jeon 2240a8ac0c1SNamjae Jeon if (icx->actx) { 2250a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(icx->actx); 2260a8ac0c1SNamjae Jeon icx->actx = NULL; 2270a8ac0c1SNamjae Jeon } 2280a8ac0c1SNamjae Jeon 2290a8ac0c1SNamjae Jeon if (!icx->is_in_root) { 2300a8ac0c1SNamjae Jeon if (icx->ib_dirty) 2310a8ac0c1SNamjae Jeon ntfs_ib_write(icx, icx->ib); 2320a8ac0c1SNamjae Jeon kvfree(icx->ib); 2330a8ac0c1SNamjae Jeon icx->ib = NULL; 2340a8ac0c1SNamjae Jeon } 2350a8ac0c1SNamjae Jeon 2360a8ac0c1SNamjae Jeon if (icx->ia_ni) { 2370a8ac0c1SNamjae Jeon iput(VFS_I(icx->ia_ni)); 2380a8ac0c1SNamjae Jeon icx->ia_ni = NULL; 2390a8ac0c1SNamjae Jeon } 2400a8ac0c1SNamjae Jeon } 2410a8ac0c1SNamjae Jeon 2420a8ac0c1SNamjae Jeon /* 2430a8ac0c1SNamjae Jeon * ntfs_index_ctx_put - release an index context 2440a8ac0c1SNamjae Jeon * @icx: index context to free 2450a8ac0c1SNamjae Jeon * 2460a8ac0c1SNamjae Jeon * Release the index context @icx, releasing all associated resources. 2470a8ac0c1SNamjae Jeon */ 2480a8ac0c1SNamjae Jeon void ntfs_index_ctx_put(struct ntfs_index_context *icx) 2490a8ac0c1SNamjae Jeon { 2500a8ac0c1SNamjae Jeon ntfs_index_ctx_free(icx); 2510a8ac0c1SNamjae Jeon kmem_cache_free(ntfs_index_ctx_cache, icx); 2520a8ac0c1SNamjae Jeon } 2530a8ac0c1SNamjae Jeon 2540a8ac0c1SNamjae Jeon /* 2550a8ac0c1SNamjae Jeon * ntfs_index_ctx_reinit - reinitialize an index context 2560a8ac0c1SNamjae Jeon * @icx: index context to reinitialize 2570a8ac0c1SNamjae Jeon * 2580a8ac0c1SNamjae Jeon * Reinitialize the index context @icx so it can be used for ntfs_index_lookup. 2590a8ac0c1SNamjae Jeon */ 2600a8ac0c1SNamjae Jeon void ntfs_index_ctx_reinit(struct ntfs_index_context *icx) 2610a8ac0c1SNamjae Jeon { 2620a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 2630a8ac0c1SNamjae Jeon 2640a8ac0c1SNamjae Jeon ntfs_index_ctx_free(icx); 2650a8ac0c1SNamjae Jeon 2660a8ac0c1SNamjae Jeon *icx = (struct ntfs_index_context) { 2670a8ac0c1SNamjae Jeon .idx_ni = icx->idx_ni, 2680a8ac0c1SNamjae Jeon .name = icx->name, 2690a8ac0c1SNamjae Jeon .name_len = icx->name_len, 2700a8ac0c1SNamjae Jeon }; 2710a8ac0c1SNamjae Jeon } 2720a8ac0c1SNamjae Jeon 2730a8ac0c1SNamjae Jeon static __le64 *ntfs_ie_get_vcn_addr(struct index_entry *ie) 2740a8ac0c1SNamjae Jeon { 2750a8ac0c1SNamjae Jeon return (__le64 *)((u8 *)ie + le16_to_cpu(ie->length) - sizeof(s64)); 2760a8ac0c1SNamjae Jeon } 2770a8ac0c1SNamjae Jeon 2780a8ac0c1SNamjae Jeon /* 2790a8ac0c1SNamjae Jeon * Get the subnode vcn to which the index entry refers. 2800a8ac0c1SNamjae Jeon */ 2810a8ac0c1SNamjae Jeon static s64 ntfs_ie_get_vcn(struct index_entry *ie) 2820a8ac0c1SNamjae Jeon { 2830a8ac0c1SNamjae Jeon return le64_to_cpup(ntfs_ie_get_vcn_addr(ie)); 2840a8ac0c1SNamjae Jeon } 2850a8ac0c1SNamjae Jeon 2860a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_get_first(struct index_header *ih) 2870a8ac0c1SNamjae Jeon { 2880a8ac0c1SNamjae Jeon return (struct index_entry *)((u8 *)ih + le32_to_cpu(ih->entries_offset)); 2890a8ac0c1SNamjae Jeon } 2900a8ac0c1SNamjae Jeon 2910a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_get_next(struct index_entry *ie) 2920a8ac0c1SNamjae Jeon { 2930a8ac0c1SNamjae Jeon return (struct index_entry *)((char *)ie + le16_to_cpu(ie->length)); 2940a8ac0c1SNamjae Jeon } 2950a8ac0c1SNamjae Jeon 2960a8ac0c1SNamjae Jeon static u8 *ntfs_ie_get_end(struct index_header *ih) 2970a8ac0c1SNamjae Jeon { 2980a8ac0c1SNamjae Jeon return (u8 *)ih + le32_to_cpu(ih->index_length); 2990a8ac0c1SNamjae Jeon } 3000a8ac0c1SNamjae Jeon 3010a8ac0c1SNamjae Jeon static int ntfs_ie_end(struct index_entry *ie) 3020a8ac0c1SNamjae Jeon { 3030a8ac0c1SNamjae Jeon return ie->flags & INDEX_ENTRY_END || !ie->length; 3040a8ac0c1SNamjae Jeon } 3050a8ac0c1SNamjae Jeon 3060a8ac0c1SNamjae Jeon /* 3070a8ac0c1SNamjae Jeon * Find the last entry in the index block 3080a8ac0c1SNamjae Jeon */ 3090a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_get_last(struct index_entry *ie, char *ies_end) 3100a8ac0c1SNamjae Jeon { 3110a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 3120a8ac0c1SNamjae Jeon 3130a8ac0c1SNamjae Jeon while ((char *)ie < ies_end && !ntfs_ie_end(ie)) 3140a8ac0c1SNamjae Jeon ie = ntfs_ie_get_next(ie); 3150a8ac0c1SNamjae Jeon 3160a8ac0c1SNamjae Jeon return ie; 3170a8ac0c1SNamjae Jeon } 3180a8ac0c1SNamjae Jeon 3190a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_get_by_pos(struct index_header *ih, int pos) 3200a8ac0c1SNamjae Jeon { 3210a8ac0c1SNamjae Jeon struct index_entry *ie; 3220a8ac0c1SNamjae Jeon 3230a8ac0c1SNamjae Jeon ntfs_debug("pos: %d\n", pos); 3240a8ac0c1SNamjae Jeon 3250a8ac0c1SNamjae Jeon ie = ntfs_ie_get_first(ih); 3260a8ac0c1SNamjae Jeon 3270a8ac0c1SNamjae Jeon while (pos-- > 0) 3280a8ac0c1SNamjae Jeon ie = ntfs_ie_get_next(ie); 3290a8ac0c1SNamjae Jeon 3300a8ac0c1SNamjae Jeon return ie; 3310a8ac0c1SNamjae Jeon } 3320a8ac0c1SNamjae Jeon 3330a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_prev(struct index_header *ih, struct index_entry *ie) 3340a8ac0c1SNamjae Jeon { 3350a8ac0c1SNamjae Jeon struct index_entry *ie_prev = NULL; 3360a8ac0c1SNamjae Jeon struct index_entry *tmp; 3370a8ac0c1SNamjae Jeon 3380a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 3390a8ac0c1SNamjae Jeon 3400a8ac0c1SNamjae Jeon tmp = ntfs_ie_get_first(ih); 3410a8ac0c1SNamjae Jeon 3420a8ac0c1SNamjae Jeon while (tmp != ie) { 3430a8ac0c1SNamjae Jeon ie_prev = tmp; 3440a8ac0c1SNamjae Jeon tmp = ntfs_ie_get_next(tmp); 3450a8ac0c1SNamjae Jeon } 3460a8ac0c1SNamjae Jeon 3470a8ac0c1SNamjae Jeon return ie_prev; 3480a8ac0c1SNamjae Jeon } 3490a8ac0c1SNamjae Jeon 3500a8ac0c1SNamjae Jeon static int ntfs_ih_numof_entries(struct index_header *ih) 3510a8ac0c1SNamjae Jeon { 3520a8ac0c1SNamjae Jeon int n; 3530a8ac0c1SNamjae Jeon struct index_entry *ie; 3540a8ac0c1SNamjae Jeon u8 *end; 3550a8ac0c1SNamjae Jeon 3560a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 3570a8ac0c1SNamjae Jeon 3580a8ac0c1SNamjae Jeon end = ntfs_ie_get_end(ih); 3590a8ac0c1SNamjae Jeon ie = ntfs_ie_get_first(ih); 3600a8ac0c1SNamjae Jeon for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++) 3610a8ac0c1SNamjae Jeon ie = ntfs_ie_get_next(ie); 3620a8ac0c1SNamjae Jeon return n; 3630a8ac0c1SNamjae Jeon } 3640a8ac0c1SNamjae Jeon 3650a8ac0c1SNamjae Jeon static int ntfs_ih_one_entry(struct index_header *ih) 3660a8ac0c1SNamjae Jeon { 3670a8ac0c1SNamjae Jeon return (ntfs_ih_numof_entries(ih) == 1); 3680a8ac0c1SNamjae Jeon } 3690a8ac0c1SNamjae Jeon 3700a8ac0c1SNamjae Jeon static int ntfs_ih_zero_entry(struct index_header *ih) 3710a8ac0c1SNamjae Jeon { 3720a8ac0c1SNamjae Jeon return (ntfs_ih_numof_entries(ih) == 0); 3730a8ac0c1SNamjae Jeon } 3740a8ac0c1SNamjae Jeon 3750a8ac0c1SNamjae Jeon static void ntfs_ie_delete(struct index_header *ih, struct index_entry *ie) 3760a8ac0c1SNamjae Jeon { 3770a8ac0c1SNamjae Jeon u32 new_size; 3780a8ac0c1SNamjae Jeon 3790a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 3800a8ac0c1SNamjae Jeon 3810a8ac0c1SNamjae Jeon new_size = le32_to_cpu(ih->index_length) - le16_to_cpu(ie->length); 3820a8ac0c1SNamjae Jeon ih->index_length = cpu_to_le32(new_size); 3830a8ac0c1SNamjae Jeon memmove(ie, (u8 *)ie + le16_to_cpu(ie->length), 3840a8ac0c1SNamjae Jeon new_size - ((u8 *)ie - (u8 *)ih)); 3850a8ac0c1SNamjae Jeon } 3860a8ac0c1SNamjae Jeon 3870a8ac0c1SNamjae Jeon static void ntfs_ie_set_vcn(struct index_entry *ie, s64 vcn) 3880a8ac0c1SNamjae Jeon { 3890a8ac0c1SNamjae Jeon *ntfs_ie_get_vcn_addr(ie) = cpu_to_le64(vcn); 3900a8ac0c1SNamjae Jeon } 3910a8ac0c1SNamjae Jeon 3920a8ac0c1SNamjae Jeon /* 3930a8ac0c1SNamjae Jeon * Insert @ie index entry at @pos entry. Used @ih values should be ok already. 3940a8ac0c1SNamjae Jeon */ 3950a8ac0c1SNamjae Jeon static void ntfs_ie_insert(struct index_header *ih, struct index_entry *ie, 3960a8ac0c1SNamjae Jeon struct index_entry *pos) 3970a8ac0c1SNamjae Jeon { 3980a8ac0c1SNamjae Jeon int ie_size = le16_to_cpu(ie->length); 3990a8ac0c1SNamjae Jeon 4000a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 4010a8ac0c1SNamjae Jeon 4020a8ac0c1SNamjae Jeon ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) + ie_size); 4030a8ac0c1SNamjae Jeon memmove((u8 *)pos + ie_size, pos, 4040a8ac0c1SNamjae Jeon le32_to_cpu(ih->index_length) - ((u8 *)pos - (u8 *)ih) - ie_size); 4050a8ac0c1SNamjae Jeon memcpy(pos, ie, ie_size); 4060a8ac0c1SNamjae Jeon } 4070a8ac0c1SNamjae Jeon 4080a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_dup(struct index_entry *ie) 4090a8ac0c1SNamjae Jeon { 4100a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 4110a8ac0c1SNamjae Jeon 4120a8ac0c1SNamjae Jeon return kmemdup(ie, le16_to_cpu(ie->length), GFP_NOFS); 4130a8ac0c1SNamjae Jeon } 4140a8ac0c1SNamjae Jeon 4150a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_dup_novcn(struct index_entry *ie) 4160a8ac0c1SNamjae Jeon { 4170a8ac0c1SNamjae Jeon struct index_entry *dup; 4180a8ac0c1SNamjae Jeon int size = le16_to_cpu(ie->length); 4190a8ac0c1SNamjae Jeon 4200a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 4210a8ac0c1SNamjae Jeon 4220a8ac0c1SNamjae Jeon if (ie->flags & INDEX_ENTRY_NODE) 4230a8ac0c1SNamjae Jeon size -= sizeof(s64); 4240a8ac0c1SNamjae Jeon 4250a8ac0c1SNamjae Jeon dup = kmemdup(ie, size, GFP_NOFS); 4260a8ac0c1SNamjae Jeon if (dup) { 4270a8ac0c1SNamjae Jeon dup->flags &= ~INDEX_ENTRY_NODE; 4280a8ac0c1SNamjae Jeon dup->length = cpu_to_le16(size); 4290a8ac0c1SNamjae Jeon } 4300a8ac0c1SNamjae Jeon return dup; 4310a8ac0c1SNamjae Jeon } 4320a8ac0c1SNamjae Jeon 4330a8ac0c1SNamjae Jeon /* 4340a8ac0c1SNamjae Jeon * Check the consistency of an index block 4350a8ac0c1SNamjae Jeon * 4360a8ac0c1SNamjae Jeon * Make sure the index block does not overflow from the index record. 4370a8ac0c1SNamjae Jeon * The size of block is assumed to have been checked to be what is 4380a8ac0c1SNamjae Jeon * defined in the index root. 4390a8ac0c1SNamjae Jeon * 4400a8ac0c1SNamjae Jeon * Returns 0 if no error was found -1 otherwise (with errno unchanged) 4410a8ac0c1SNamjae Jeon * 4420a8ac0c1SNamjae Jeon * |<--->| offsetof(struct index_block, index) 4430a8ac0c1SNamjae Jeon * | |<--->| sizeof(struct index_header) 4440a8ac0c1SNamjae Jeon * | | | 4450a8ac0c1SNamjae Jeon * | | | seq index entries unused 4460a8ac0c1SNamjae Jeon * |=====|=====|=====|===========================|==============| 4470a8ac0c1SNamjae Jeon * | | | | | 4480a8ac0c1SNamjae Jeon * | |<--------->| entries_offset | | 4490a8ac0c1SNamjae Jeon * | |<---------------- index_length ------->| | 4500a8ac0c1SNamjae Jeon * | |<--------------------- allocated_size --------------->| 4510a8ac0c1SNamjae Jeon * |<--------------------------- block_size ------------------->| 4520a8ac0c1SNamjae Jeon * 4530a8ac0c1SNamjae Jeon * size(struct index_header) <= ent_offset < ind_length <= alloc_size < bk_size 4540a8ac0c1SNamjae Jeon */ 4550a8ac0c1SNamjae Jeon static int ntfs_index_block_inconsistent(struct ntfs_index_context *icx, 4560a8ac0c1SNamjae Jeon struct index_block *ib, s64 vcn) 4570a8ac0c1SNamjae Jeon { 4580a8ac0c1SNamjae Jeon u32 ib_size = (unsigned int)le32_to_cpu(ib->index.allocated_size) + 4590a8ac0c1SNamjae Jeon offsetof(struct index_block, index); 4600a8ac0c1SNamjae Jeon struct super_block *sb = icx->idx_ni->vol->sb; 4610a8ac0c1SNamjae Jeon unsigned long long inum = icx->idx_ni->mft_no; 4620a8ac0c1SNamjae Jeon 4630a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 4640a8ac0c1SNamjae Jeon 4650a8ac0c1SNamjae Jeon if (!ntfs_is_indx_record(ib->magic)) { 4660a8ac0c1SNamjae Jeon 4670a8ac0c1SNamjae Jeon ntfs_error(sb, "Corrupt index block signature: vcn %lld inode %llu\n", 4680a8ac0c1SNamjae Jeon vcn, (unsigned long long)icx->idx_ni->mft_no); 4690a8ac0c1SNamjae Jeon return -1; 4700a8ac0c1SNamjae Jeon } 4710a8ac0c1SNamjae Jeon 4720a8ac0c1SNamjae Jeon if (le64_to_cpu(ib->index_block_vcn) != vcn) { 4730a8ac0c1SNamjae Jeon ntfs_error(sb, 4740a8ac0c1SNamjae Jeon "Corrupt index block: s64 (%lld) is different from expected s64 (%lld) in inode %llu\n", 4750a8ac0c1SNamjae Jeon (long long)le64_to_cpu(ib->index_block_vcn), 4760a8ac0c1SNamjae Jeon vcn, inum); 4770a8ac0c1SNamjae Jeon return -1; 4780a8ac0c1SNamjae Jeon } 4790a8ac0c1SNamjae Jeon 4800a8ac0c1SNamjae Jeon if (ib_size != icx->block_size) { 4810a8ac0c1SNamjae Jeon ntfs_error(sb, 4820a8ac0c1SNamjae Jeon "Corrupt index block : s64 (%lld) of inode %llu has a size (%u) differing from the index specified size (%u)\n", 4830a8ac0c1SNamjae Jeon vcn, inum, ib_size, icx->block_size); 4840a8ac0c1SNamjae Jeon return -1; 4850a8ac0c1SNamjae Jeon } 4860a8ac0c1SNamjae Jeon 4870a8ac0c1SNamjae Jeon if (le32_to_cpu(ib->index.entries_offset) < sizeof(struct index_header)) { 4880a8ac0c1SNamjae Jeon ntfs_error(sb, "Invalid index entry offset in inode %lld\n", inum); 4890a8ac0c1SNamjae Jeon return -1; 4900a8ac0c1SNamjae Jeon } 4910a8ac0c1SNamjae Jeon if (le32_to_cpu(ib->index.index_length) <= 4920a8ac0c1SNamjae Jeon le32_to_cpu(ib->index.entries_offset)) { 4930a8ac0c1SNamjae Jeon ntfs_error(sb, "No space for index entries in inode %lld\n", inum); 4940a8ac0c1SNamjae Jeon return -1; 4950a8ac0c1SNamjae Jeon } 4960a8ac0c1SNamjae Jeon if (le32_to_cpu(ib->index.allocated_size) < 4970a8ac0c1SNamjae Jeon le32_to_cpu(ib->index.index_length)) { 4980a8ac0c1SNamjae Jeon ntfs_error(sb, "Index entries overflow in inode %lld\n", inum); 4990a8ac0c1SNamjae Jeon return -1; 5000a8ac0c1SNamjae Jeon } 5010a8ac0c1SNamjae Jeon 5020a8ac0c1SNamjae Jeon return 0; 5030a8ac0c1SNamjae Jeon } 5040a8ac0c1SNamjae Jeon 5050a8ac0c1SNamjae Jeon static struct index_root *ntfs_ir_lookup(struct ntfs_inode *ni, __le16 *name, 5060a8ac0c1SNamjae Jeon u32 name_len, struct ntfs_attr_search_ctx **ctx) 5070a8ac0c1SNamjae Jeon { 5080a8ac0c1SNamjae Jeon struct attr_record *a; 5090a8ac0c1SNamjae Jeon struct index_root *ir = NULL; 5100a8ac0c1SNamjae Jeon 5110a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 5120a8ac0c1SNamjae Jeon *ctx = ntfs_attr_get_search_ctx(ni, NULL); 5130a8ac0c1SNamjae Jeon if (!*ctx) { 5140a8ac0c1SNamjae Jeon ntfs_error(ni->vol->sb, "%s, Failed to get search context", __func__); 5150a8ac0c1SNamjae Jeon return NULL; 5160a8ac0c1SNamjae Jeon } 5170a8ac0c1SNamjae Jeon 5180a8ac0c1SNamjae Jeon if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, 5190a8ac0c1SNamjae Jeon 0, NULL, 0, *ctx)) { 5200a8ac0c1SNamjae Jeon ntfs_error(ni->vol->sb, "Failed to lookup $INDEX_ROOT"); 5211e9ea7e0SNamjae Jeon goto err_out; 5221e9ea7e0SNamjae Jeon } 5230a8ac0c1SNamjae Jeon 5240a8ac0c1SNamjae Jeon a = (*ctx)->attr; 5250a8ac0c1SNamjae Jeon if (a->non_resident) { 5260a8ac0c1SNamjae Jeon ntfs_error(ni->vol->sb, "Non-resident $INDEX_ROOT detected"); 5271e9ea7e0SNamjae Jeon goto err_out; 5281e9ea7e0SNamjae Jeon } 5290a8ac0c1SNamjae Jeon 5300a8ac0c1SNamjae Jeon ir = (struct index_root *)((char *)a + le16_to_cpu(a->data.resident.value_offset)); 5310a8ac0c1SNamjae Jeon err_out: 5320a8ac0c1SNamjae Jeon if (!ir) { 5330a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(*ctx); 5340a8ac0c1SNamjae Jeon *ctx = NULL; 5350a8ac0c1SNamjae Jeon } 5360a8ac0c1SNamjae Jeon return ir; 5370a8ac0c1SNamjae Jeon } 5380a8ac0c1SNamjae Jeon 5390a8ac0c1SNamjae Jeon static struct index_root *ntfs_ir_lookup2(struct ntfs_inode *ni, __le16 *name, u32 len) 5400a8ac0c1SNamjae Jeon { 5410a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx; 5420a8ac0c1SNamjae Jeon struct index_root *ir; 5430a8ac0c1SNamjae Jeon 5440a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup(ni, name, len, &ctx); 5450a8ac0c1SNamjae Jeon if (ir) 5460a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 5470a8ac0c1SNamjae Jeon return ir; 5480a8ac0c1SNamjae Jeon } 5490a8ac0c1SNamjae Jeon 5500a8ac0c1SNamjae Jeon /* 5510a8ac0c1SNamjae Jeon * Find a key in the index block. 5520a8ac0c1SNamjae Jeon */ 5530a8ac0c1SNamjae Jeon static int ntfs_ie_lookup(const void *key, const u32 key_len, 5540a8ac0c1SNamjae Jeon struct ntfs_index_context *icx, struct index_header *ih, 5550a8ac0c1SNamjae Jeon s64 *vcn, struct index_entry **ie_out) 5560a8ac0c1SNamjae Jeon { 5570a8ac0c1SNamjae Jeon struct index_entry *ie; 5580a8ac0c1SNamjae Jeon u8 *index_end; 5590a8ac0c1SNamjae Jeon int rc, item = 0; 5600a8ac0c1SNamjae Jeon 5610a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 5620a8ac0c1SNamjae Jeon 5630a8ac0c1SNamjae Jeon index_end = ntfs_ie_get_end(ih); 5640a8ac0c1SNamjae Jeon 5651e9ea7e0SNamjae Jeon /* 5661e9ea7e0SNamjae Jeon * Loop until we exceed valid memory (corruption case) or until we 5671e9ea7e0SNamjae Jeon * reach the last entry. 5681e9ea7e0SNamjae Jeon */ 5690a8ac0c1SNamjae Jeon for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) { 5701e9ea7e0SNamjae Jeon /* Bounds checks. */ 5710a8ac0c1SNamjae Jeon if ((u8 *)ie + sizeof(struct index_entry_header) > index_end || 5720a8ac0c1SNamjae Jeon (u8 *)ie + le16_to_cpu(ie->length) > index_end) { 5730a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, 5740a8ac0c1SNamjae Jeon "Index entry out of bounds in inode %llu.\n", 5750a8ac0c1SNamjae Jeon (unsigned long long)icx->idx_ni->mft_no); 5760a8ac0c1SNamjae Jeon return -ERANGE; 5770a8ac0c1SNamjae Jeon } 5780a8ac0c1SNamjae Jeon 5791e9ea7e0SNamjae Jeon /* 5801e9ea7e0SNamjae Jeon * The last entry cannot contain a key. It can however contain 5811e9ea7e0SNamjae Jeon * a pointer to a child node in the B+tree so we just break out. 5821e9ea7e0SNamjae Jeon */ 5830a8ac0c1SNamjae Jeon if (ntfs_ie_end(ie)) 5841e9ea7e0SNamjae Jeon break; 5850a8ac0c1SNamjae Jeon 5861e9ea7e0SNamjae Jeon /* 5871e9ea7e0SNamjae Jeon * Not a perfect match, need to do full blown collation so we 5881e9ea7e0SNamjae Jeon * know which way in the B+tree we have to go. 5891e9ea7e0SNamjae Jeon */ 5900a8ac0c1SNamjae Jeon rc = ntfs_collate(icx->idx_ni->vol, icx->cr, key, key_len, &ie->key, 5910a8ac0c1SNamjae Jeon le16_to_cpu(ie->key_length)); 5920a8ac0c1SNamjae Jeon if (rc == -EINVAL) { 5930a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, 5940a8ac0c1SNamjae Jeon "Collation error. Perhaps a filename contains invalid characters?\n"); 5950a8ac0c1SNamjae Jeon return -ERANGE; 5960a8ac0c1SNamjae Jeon } 5971e9ea7e0SNamjae Jeon /* 5981e9ea7e0SNamjae Jeon * If @key collates before the key of the current entry, there 5991e9ea7e0SNamjae Jeon * is definitely no such key in this index but we might need to 6001e9ea7e0SNamjae Jeon * descend into the B+tree so we just break out of the loop. 6011e9ea7e0SNamjae Jeon */ 6021e9ea7e0SNamjae Jeon if (rc == -1) 6031e9ea7e0SNamjae Jeon break; 6040a8ac0c1SNamjae Jeon 6050a8ac0c1SNamjae Jeon if (!rc) { 6060a8ac0c1SNamjae Jeon *ie_out = ie; 6070a8ac0c1SNamjae Jeon icx->parent_pos[icx->pindex] = item; 6080a8ac0c1SNamjae Jeon return 0; 6090a8ac0c1SNamjae Jeon } 6100a8ac0c1SNamjae Jeon 6110a8ac0c1SNamjae Jeon item++; 6121e9ea7e0SNamjae Jeon } 6131e9ea7e0SNamjae Jeon /* 6140a8ac0c1SNamjae Jeon * We have finished with this index block without success. Check for the 6150a8ac0c1SNamjae Jeon * presence of a child node and if not present return with errno ENOENT, 6160a8ac0c1SNamjae Jeon * otherwise we will keep searching in another index block. 6171e9ea7e0SNamjae Jeon */ 6181e9ea7e0SNamjae Jeon if (!(ie->flags & INDEX_ENTRY_NODE)) { 6190a8ac0c1SNamjae Jeon ntfs_debug("Index entry wasn't found.\n"); 6200a8ac0c1SNamjae Jeon *ie_out = ie; 6210a8ac0c1SNamjae Jeon return -ENOENT; 6221e9ea7e0SNamjae Jeon } 6230a8ac0c1SNamjae Jeon 6241e9ea7e0SNamjae Jeon /* Get the starting vcn of the index_block holding the child node. */ 6250a8ac0c1SNamjae Jeon *vcn = ntfs_ie_get_vcn(ie); 6260a8ac0c1SNamjae Jeon if (*vcn < 0) { 6270a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Negative vcn in inode %llu\n", 6280a8ac0c1SNamjae Jeon (unsigned long long)icx->idx_ni->mft_no); 6290a8ac0c1SNamjae Jeon return -EINVAL; 6300a8ac0c1SNamjae Jeon } 6310a8ac0c1SNamjae Jeon 6320a8ac0c1SNamjae Jeon ntfs_debug("Parent entry number %d\n", item); 6330a8ac0c1SNamjae Jeon icx->parent_pos[icx->pindex] = item; 6340a8ac0c1SNamjae Jeon 6350a8ac0c1SNamjae Jeon return -EAGAIN; 6360a8ac0c1SNamjae Jeon } 6370a8ac0c1SNamjae Jeon 6380a8ac0c1SNamjae Jeon struct ntfs_inode *ntfs_ia_open(struct ntfs_index_context *icx, struct ntfs_inode *ni) 6390a8ac0c1SNamjae Jeon { 6400a8ac0c1SNamjae Jeon struct inode *ia_vi; 6410a8ac0c1SNamjae Jeon 6420a8ac0c1SNamjae Jeon ia_vi = ntfs_index_iget(VFS_I(ni), icx->name, icx->name_len); 6430a8ac0c1SNamjae Jeon if (IS_ERR(ia_vi)) { 6440a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, 6450a8ac0c1SNamjae Jeon "Failed to open index allocation of inode %llu", 6460a8ac0c1SNamjae Jeon (unsigned long long)ni->mft_no); 6470a8ac0c1SNamjae Jeon return NULL; 6480a8ac0c1SNamjae Jeon } 6490a8ac0c1SNamjae Jeon 6500a8ac0c1SNamjae Jeon return NTFS_I(ia_vi); 6510a8ac0c1SNamjae Jeon } 6520a8ac0c1SNamjae Jeon 6530a8ac0c1SNamjae Jeon static int ntfs_ib_read(struct ntfs_index_context *icx, s64 vcn, struct index_block *dst) 6540a8ac0c1SNamjae Jeon { 6550a8ac0c1SNamjae Jeon s64 pos, ret; 6560a8ac0c1SNamjae Jeon 6570a8ac0c1SNamjae Jeon ntfs_debug("vcn: %lld\n", vcn); 6580a8ac0c1SNamjae Jeon 6590a8ac0c1SNamjae Jeon pos = ntfs_ib_vcn_to_pos(icx, vcn); 6600a8ac0c1SNamjae Jeon 6610a8ac0c1SNamjae Jeon ret = ntfs_inode_attr_pread(VFS_I(icx->ia_ni), pos, icx->block_size, (u8 *)dst); 6620a8ac0c1SNamjae Jeon if (ret != icx->block_size) { 6630a8ac0c1SNamjae Jeon if (ret == -1) 6640a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to read index block"); 6650a8ac0c1SNamjae Jeon else 6660a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, 6670a8ac0c1SNamjae Jeon "Failed to read full index block at %lld\n", pos); 6680a8ac0c1SNamjae Jeon return -1; 6690a8ac0c1SNamjae Jeon } 6700a8ac0c1SNamjae Jeon 6710a8ac0c1SNamjae Jeon post_read_mst_fixup((struct ntfs_record *)((u8 *)dst), icx->block_size); 6720a8ac0c1SNamjae Jeon if (ntfs_index_block_inconsistent(icx, dst, vcn)) 6730a8ac0c1SNamjae Jeon return -1; 6740a8ac0c1SNamjae Jeon 6750a8ac0c1SNamjae Jeon return 0; 6760a8ac0c1SNamjae Jeon } 6770a8ac0c1SNamjae Jeon 6780a8ac0c1SNamjae Jeon static int ntfs_icx_parent_inc(struct ntfs_index_context *icx) 6790a8ac0c1SNamjae Jeon { 6800a8ac0c1SNamjae Jeon icx->pindex++; 6810a8ac0c1SNamjae Jeon if (icx->pindex >= MAX_PARENT_VCN) { 6820a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Index is over %d level deep", MAX_PARENT_VCN); 6830a8ac0c1SNamjae Jeon return -EOPNOTSUPP; 6840a8ac0c1SNamjae Jeon } 6850a8ac0c1SNamjae Jeon return 0; 6860a8ac0c1SNamjae Jeon } 6870a8ac0c1SNamjae Jeon 6880a8ac0c1SNamjae Jeon static int ntfs_icx_parent_dec(struct ntfs_index_context *icx) 6890a8ac0c1SNamjae Jeon { 6900a8ac0c1SNamjae Jeon icx->pindex--; 6910a8ac0c1SNamjae Jeon if (icx->pindex < 0) { 6920a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Corrupt index pointer (%d)", icx->pindex); 6930a8ac0c1SNamjae Jeon return -EINVAL; 6940a8ac0c1SNamjae Jeon } 6950a8ac0c1SNamjae Jeon return 0; 6960a8ac0c1SNamjae Jeon } 6970a8ac0c1SNamjae Jeon 6981e9ea7e0SNamjae Jeon /* 6990a8ac0c1SNamjae Jeon * ntfs_index_lookup - find a key in an index and return its index entry 7000a8ac0c1SNamjae Jeon * @key: key for which to search in the index 7010a8ac0c1SNamjae Jeon * @key_len: length of @key in bytes 7020a8ac0c1SNamjae Jeon * @icx: context describing the index and the returned entry 7030a8ac0c1SNamjae Jeon * 7040a8ac0c1SNamjae Jeon * Before calling ntfs_index_lookup(), @icx must have been obtained from a 7050a8ac0c1SNamjae Jeon * call to ntfs_index_ctx_get(). 7060a8ac0c1SNamjae Jeon * 7070a8ac0c1SNamjae Jeon * Look for the @key in the index specified by the index lookup context @icx. 7080a8ac0c1SNamjae Jeon * ntfs_index_lookup() walks the contents of the index looking for the @key. 7090a8ac0c1SNamjae Jeon * 7100a8ac0c1SNamjae Jeon * If the @key is found in the index, 0 is returned and @icx is setup to 7110a8ac0c1SNamjae Jeon * describe the index entry containing the matching @key. @icx->entry is the 7120a8ac0c1SNamjae Jeon * index entry and @icx->data and @icx->data_len are the index entry data and 7130a8ac0c1SNamjae Jeon * its length in bytes, respectively. 7140a8ac0c1SNamjae Jeon * 7150a8ac0c1SNamjae Jeon * If the @key is not found in the index, -ENOENT is returned and 7160a8ac0c1SNamjae Jeon * @icx is setup to describe the index entry whose key collates immediately 7170a8ac0c1SNamjae Jeon * after the search @key, i.e. this is the position in the index at which 7180a8ac0c1SNamjae Jeon * an index entry with a key of @key would need to be inserted. 7190a8ac0c1SNamjae Jeon * 7200a8ac0c1SNamjae Jeon * When finished with the entry and its data, call ntfs_index_ctx_put() to free 7210a8ac0c1SNamjae Jeon * the context and other associated resources. 7220a8ac0c1SNamjae Jeon * 7230a8ac0c1SNamjae Jeon * If the index entry was modified, call ntfs_index_entry_mark_dirty() before 7240a8ac0c1SNamjae Jeon * the call to ntfs_index_ctx_put() to ensure that the changes are written 7250a8ac0c1SNamjae Jeon * to disk. 7261e9ea7e0SNamjae Jeon */ 7270a8ac0c1SNamjae Jeon int ntfs_index_lookup(const void *key, const u32 key_len, struct ntfs_index_context *icx) 7280a8ac0c1SNamjae Jeon { 7290a8ac0c1SNamjae Jeon s64 old_vcn, vcn; 7300a8ac0c1SNamjae Jeon struct ntfs_inode *ni = icx->idx_ni; 7310a8ac0c1SNamjae Jeon struct super_block *sb = ni->vol->sb; 7320a8ac0c1SNamjae Jeon struct index_root *ir; 7330a8ac0c1SNamjae Jeon struct index_entry *ie; 7340a8ac0c1SNamjae Jeon struct index_block *ib = NULL; 7350a8ac0c1SNamjae Jeon int err = 0; 7360a8ac0c1SNamjae Jeon 7370a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 7380a8ac0c1SNamjae Jeon 7390a8ac0c1SNamjae Jeon if (!key) { 7400a8ac0c1SNamjae Jeon ntfs_error(sb, "key: %p key_len: %d", key, key_len); 7410a8ac0c1SNamjae Jeon return -EINVAL; 7420a8ac0c1SNamjae Jeon } 7430a8ac0c1SNamjae Jeon 7440a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &icx->actx); 7450a8ac0c1SNamjae Jeon if (!ir) 7460a8ac0c1SNamjae Jeon return -EIO; 7470a8ac0c1SNamjae Jeon 7480a8ac0c1SNamjae Jeon icx->block_size = le32_to_cpu(ir->index_block_size); 7490a8ac0c1SNamjae Jeon if (icx->block_size < NTFS_BLOCK_SIZE) { 7500a8ac0c1SNamjae Jeon err = -EINVAL; 7510a8ac0c1SNamjae Jeon ntfs_error(sb, 7520a8ac0c1SNamjae Jeon "Index block size (%d) is smaller than the sector size (%d)", 7530a8ac0c1SNamjae Jeon icx->block_size, NTFS_BLOCK_SIZE); 7541e9ea7e0SNamjae Jeon goto err_out; 7551e9ea7e0SNamjae Jeon } 7560a8ac0c1SNamjae Jeon 7570a8ac0c1SNamjae Jeon if (ni->vol->cluster_size <= icx->block_size) 7580a8ac0c1SNamjae Jeon icx->vcn_size_bits = ni->vol->cluster_size_bits; 7590a8ac0c1SNamjae Jeon else 7600a8ac0c1SNamjae Jeon icx->vcn_size_bits = ni->vol->sector_size_bits; 7610a8ac0c1SNamjae Jeon 7620a8ac0c1SNamjae Jeon icx->cr = ir->collation_rule; 7630a8ac0c1SNamjae Jeon if (!ntfs_is_collation_rule_supported(icx->cr)) { 7640a8ac0c1SNamjae Jeon err = -EOPNOTSUPP; 7650a8ac0c1SNamjae Jeon ntfs_error(sb, "Unknown collation rule 0x%x", 7660a8ac0c1SNamjae Jeon (unsigned int)le32_to_cpu(icx->cr)); 7670a8ac0c1SNamjae Jeon goto err_out; 7681e9ea7e0SNamjae Jeon } 7690a8ac0c1SNamjae Jeon 7700a8ac0c1SNamjae Jeon old_vcn = VCN_INDEX_ROOT_PARENT; 7710a8ac0c1SNamjae Jeon err = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie); 7720a8ac0c1SNamjae Jeon if (err == -ERANGE || err == -EINVAL) 7730a8ac0c1SNamjae Jeon goto err_out; 7740a8ac0c1SNamjae Jeon 7750a8ac0c1SNamjae Jeon icx->ir = ir; 7760a8ac0c1SNamjae Jeon if (err != -EAGAIN) { 7770a8ac0c1SNamjae Jeon icx->is_in_root = true; 7780a8ac0c1SNamjae Jeon icx->parent_vcn[icx->pindex] = old_vcn; 7791e9ea7e0SNamjae Jeon goto done; 7801e9ea7e0SNamjae Jeon } 7810a8ac0c1SNamjae Jeon 7821e9ea7e0SNamjae Jeon /* Child node present, descend into it. */ 7830a8ac0c1SNamjae Jeon icx->ia_ni = ntfs_ia_open(icx, ni); 7840a8ac0c1SNamjae Jeon if (!icx->ia_ni) { 7850a8ac0c1SNamjae Jeon err = -ENOENT; 7860a8ac0c1SNamjae Jeon goto err_out; 7871e9ea7e0SNamjae Jeon } 7880a8ac0c1SNamjae Jeon 7890a8ac0c1SNamjae Jeon ib = kvzalloc(icx->block_size, GFP_NOFS); 7900a8ac0c1SNamjae Jeon if (!ib) { 7910a8ac0c1SNamjae Jeon err = -ENOMEM; 7920a8ac0c1SNamjae Jeon goto err_out; 7930a8ac0c1SNamjae Jeon } 7940a8ac0c1SNamjae Jeon 7950a8ac0c1SNamjae Jeon descend_into_child_node: 7960a8ac0c1SNamjae Jeon icx->parent_vcn[icx->pindex] = old_vcn; 7970a8ac0c1SNamjae Jeon if (ntfs_icx_parent_inc(icx)) { 7980a8ac0c1SNamjae Jeon err = -EIO; 7990a8ac0c1SNamjae Jeon goto err_out; 8000a8ac0c1SNamjae Jeon } 8010a8ac0c1SNamjae Jeon old_vcn = vcn; 8020a8ac0c1SNamjae Jeon 8030a8ac0c1SNamjae Jeon ntfs_debug("Descend into node with s64 %lld.\n", vcn); 8040a8ac0c1SNamjae Jeon 8050a8ac0c1SNamjae Jeon if (ntfs_ib_read(icx, vcn, ib)) { 8060a8ac0c1SNamjae Jeon err = -EIO; 8070a8ac0c1SNamjae Jeon goto err_out; 8080a8ac0c1SNamjae Jeon } 8090a8ac0c1SNamjae Jeon err = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie); 8100a8ac0c1SNamjae Jeon if (err != -EAGAIN) { 8110a8ac0c1SNamjae Jeon if (err == -EINVAL || err == -ERANGE) 8120a8ac0c1SNamjae Jeon goto err_out; 8130a8ac0c1SNamjae Jeon 8140a8ac0c1SNamjae Jeon icx->is_in_root = false; 8150a8ac0c1SNamjae Jeon icx->ib = ib; 8160a8ac0c1SNamjae Jeon icx->parent_vcn[icx->pindex] = vcn; 8170a8ac0c1SNamjae Jeon goto done; 8180a8ac0c1SNamjae Jeon } 8190a8ac0c1SNamjae Jeon 8200a8ac0c1SNamjae Jeon if ((ib->index.flags & NODE_MASK) == LEAF_NODE) { 8210a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, 8220a8ac0c1SNamjae Jeon "Index entry with child node found in a leaf node in inode 0x%llx.\n", 8230a8ac0c1SNamjae Jeon (unsigned long long)ni->mft_no); 8240a8ac0c1SNamjae Jeon goto err_out; 8250a8ac0c1SNamjae Jeon } 8260a8ac0c1SNamjae Jeon 8270a8ac0c1SNamjae Jeon goto descend_into_child_node; 8281e9ea7e0SNamjae Jeon err_out: 8290a8ac0c1SNamjae Jeon if (icx->actx) { 8300a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(icx->actx); 8310a8ac0c1SNamjae Jeon icx->actx = NULL; 8320a8ac0c1SNamjae Jeon } 8330a8ac0c1SNamjae Jeon kvfree(ib); 8341e9ea7e0SNamjae Jeon if (!err) 8351e9ea7e0SNamjae Jeon err = -EIO; 8361e9ea7e0SNamjae Jeon return err; 8370a8ac0c1SNamjae Jeon done: 8380a8ac0c1SNamjae Jeon icx->entry = ie; 8390a8ac0c1SNamjae Jeon icx->data = (u8 *)ie + offsetof(struct index_entry, key); 8400a8ac0c1SNamjae Jeon icx->data_len = le16_to_cpu(ie->key_length); 8410a8ac0c1SNamjae Jeon ntfs_debug("Done.\n"); 8420a8ac0c1SNamjae Jeon return err; 8430a8ac0c1SNamjae Jeon 8440a8ac0c1SNamjae Jeon } 8450a8ac0c1SNamjae Jeon 8460a8ac0c1SNamjae Jeon static struct index_block *ntfs_ib_alloc(s64 ib_vcn, u32 ib_size, 8470a8ac0c1SNamjae Jeon u8 node_type) 8480a8ac0c1SNamjae Jeon { 8490a8ac0c1SNamjae Jeon struct index_block *ib; 8500a8ac0c1SNamjae Jeon int ih_size = sizeof(struct index_header); 8510a8ac0c1SNamjae Jeon 8520a8ac0c1SNamjae Jeon ntfs_debug("Entering ib_vcn = %lld ib_size = %u\n", ib_vcn, ib_size); 8530a8ac0c1SNamjae Jeon 8540a8ac0c1SNamjae Jeon ib = kvzalloc(ib_size, GFP_NOFS); 8550a8ac0c1SNamjae Jeon if (!ib) 8560a8ac0c1SNamjae Jeon return NULL; 8570a8ac0c1SNamjae Jeon 8580a8ac0c1SNamjae Jeon ib->magic = magic_INDX; 8590a8ac0c1SNamjae Jeon ib->usa_ofs = cpu_to_le16(sizeof(struct index_block)); 8600a8ac0c1SNamjae Jeon ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1); 8610a8ac0c1SNamjae Jeon /* Set USN to 1 */ 8620a8ac0c1SNamjae Jeon *(__le16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = cpu_to_le16(1); 8630a8ac0c1SNamjae Jeon ib->lsn = 0; 8640a8ac0c1SNamjae Jeon ib->index_block_vcn = cpu_to_le64(ib_vcn); 8650a8ac0c1SNamjae Jeon ib->index.entries_offset = cpu_to_le32((ih_size + 8660a8ac0c1SNamjae Jeon le16_to_cpu(ib->usa_count) * 2 + 7) & ~7); 8670a8ac0c1SNamjae Jeon ib->index.index_length = 0; 8680a8ac0c1SNamjae Jeon ib->index.allocated_size = cpu_to_le32(ib_size - 8690a8ac0c1SNamjae Jeon (sizeof(struct index_block) - ih_size)); 8700a8ac0c1SNamjae Jeon ib->index.flags = node_type; 8710a8ac0c1SNamjae Jeon 8720a8ac0c1SNamjae Jeon return ib; 8730a8ac0c1SNamjae Jeon } 8740a8ac0c1SNamjae Jeon 8750a8ac0c1SNamjae Jeon /* 8760a8ac0c1SNamjae Jeon * Find the median by going through all the entries 8770a8ac0c1SNamjae Jeon */ 8780a8ac0c1SNamjae Jeon static struct index_entry *ntfs_ie_get_median(struct index_header *ih) 8790a8ac0c1SNamjae Jeon { 8800a8ac0c1SNamjae Jeon struct index_entry *ie, *ie_start; 8810a8ac0c1SNamjae Jeon u8 *ie_end; 8820a8ac0c1SNamjae Jeon int i = 0, median; 8830a8ac0c1SNamjae Jeon 8840a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 8850a8ac0c1SNamjae Jeon 8860a8ac0c1SNamjae Jeon ie = ie_start = ntfs_ie_get_first(ih); 8870a8ac0c1SNamjae Jeon ie_end = (u8 *)ntfs_ie_get_end(ih); 8880a8ac0c1SNamjae Jeon 8890a8ac0c1SNamjae Jeon while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) { 8900a8ac0c1SNamjae Jeon ie = ntfs_ie_get_next(ie); 8910a8ac0c1SNamjae Jeon i++; 8920a8ac0c1SNamjae Jeon } 8930a8ac0c1SNamjae Jeon /* 8940a8ac0c1SNamjae Jeon * NOTE: this could be also the entry at the half of the index block. 8950a8ac0c1SNamjae Jeon */ 8960a8ac0c1SNamjae Jeon median = i / 2 - 1; 8970a8ac0c1SNamjae Jeon 8980a8ac0c1SNamjae Jeon ntfs_debug("Entries: %d median: %d\n", i, median); 8990a8ac0c1SNamjae Jeon 9000a8ac0c1SNamjae Jeon for (i = 0, ie = ie_start; i <= median; i++) 9010a8ac0c1SNamjae Jeon ie = ntfs_ie_get_next(ie); 9020a8ac0c1SNamjae Jeon 9030a8ac0c1SNamjae Jeon return ie; 9040a8ac0c1SNamjae Jeon } 9050a8ac0c1SNamjae Jeon 9060a8ac0c1SNamjae Jeon static u64 ntfs_ibm_vcn_to_pos(struct ntfs_index_context *icx, s64 vcn) 9070a8ac0c1SNamjae Jeon { 9080a8ac0c1SNamjae Jeon u64 pos = ntfs_ib_vcn_to_pos(icx, vcn); 9090a8ac0c1SNamjae Jeon 9100a8ac0c1SNamjae Jeon do_div(pos, icx->block_size); 9110a8ac0c1SNamjae Jeon return pos; 9120a8ac0c1SNamjae Jeon } 9130a8ac0c1SNamjae Jeon 9140a8ac0c1SNamjae Jeon static s64 ntfs_ibm_pos_to_vcn(struct ntfs_index_context *icx, s64 pos) 9150a8ac0c1SNamjae Jeon { 9160a8ac0c1SNamjae Jeon return ntfs_ib_pos_to_vcn(icx, pos * icx->block_size); 9170a8ac0c1SNamjae Jeon } 9180a8ac0c1SNamjae Jeon 9190a8ac0c1SNamjae Jeon static int ntfs_ibm_add(struct ntfs_index_context *icx) 9200a8ac0c1SNamjae Jeon { 9210a8ac0c1SNamjae Jeon u8 bmp[8]; 9220a8ac0c1SNamjae Jeon 9230a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 9240a8ac0c1SNamjae Jeon 9250a8ac0c1SNamjae Jeon if (ntfs_attr_exist(icx->idx_ni, AT_BITMAP, icx->name, icx->name_len)) 9260a8ac0c1SNamjae Jeon return 0; 9270a8ac0c1SNamjae Jeon /* 9280a8ac0c1SNamjae Jeon * AT_BITMAP must be at least 8 bytes. 9290a8ac0c1SNamjae Jeon */ 9300a8ac0c1SNamjae Jeon memset(bmp, 0, sizeof(bmp)); 9310a8ac0c1SNamjae Jeon if (ntfs_attr_add(icx->idx_ni, AT_BITMAP, icx->name, icx->name_len, 9320a8ac0c1SNamjae Jeon bmp, sizeof(bmp))) { 9330a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to add AT_BITMAP"); 9340a8ac0c1SNamjae Jeon return -EINVAL; 9350a8ac0c1SNamjae Jeon } 9360a8ac0c1SNamjae Jeon 9370a8ac0c1SNamjae Jeon return 0; 9380a8ac0c1SNamjae Jeon } 9390a8ac0c1SNamjae Jeon 9400a8ac0c1SNamjae Jeon static int ntfs_ibm_modify(struct ntfs_index_context *icx, s64 vcn, int set) 9410a8ac0c1SNamjae Jeon { 9420a8ac0c1SNamjae Jeon u8 byte; 9430a8ac0c1SNamjae Jeon u64 pos = ntfs_ibm_vcn_to_pos(icx, vcn); 9440a8ac0c1SNamjae Jeon u32 bpos = pos / 8; 9450a8ac0c1SNamjae Jeon u32 bit = 1 << (pos % 8); 9460a8ac0c1SNamjae Jeon struct ntfs_inode *bmp_ni; 9470a8ac0c1SNamjae Jeon struct inode *bmp_vi; 9480a8ac0c1SNamjae Jeon int ret = 0; 9490a8ac0c1SNamjae Jeon 9500a8ac0c1SNamjae Jeon ntfs_debug("%s vcn: %lld\n", set ? "set" : "clear", vcn); 9510a8ac0c1SNamjae Jeon 9520a8ac0c1SNamjae Jeon bmp_vi = ntfs_attr_iget(VFS_I(icx->idx_ni), AT_BITMAP, icx->name, icx->name_len); 9530a8ac0c1SNamjae Jeon if (IS_ERR(bmp_vi)) { 9540a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to open $BITMAP attribute"); 9550a8ac0c1SNamjae Jeon return PTR_ERR(bmp_vi); 9560a8ac0c1SNamjae Jeon } 9570a8ac0c1SNamjae Jeon 9580a8ac0c1SNamjae Jeon bmp_ni = NTFS_I(bmp_vi); 9590a8ac0c1SNamjae Jeon 9600a8ac0c1SNamjae Jeon if (set) { 9610a8ac0c1SNamjae Jeon if (bmp_ni->data_size < bpos + 1) { 9620a8ac0c1SNamjae Jeon ret = ntfs_attr_truncate(bmp_ni, (bmp_ni->data_size + 8) & ~7); 9630a8ac0c1SNamjae Jeon if (ret) { 9640a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to truncate AT_BITMAP"); 9650a8ac0c1SNamjae Jeon goto err; 9660a8ac0c1SNamjae Jeon } 9670a8ac0c1SNamjae Jeon i_size_write(bmp_vi, (loff_t)bmp_ni->data_size); 9680a8ac0c1SNamjae Jeon } 9690a8ac0c1SNamjae Jeon } 9700a8ac0c1SNamjae Jeon 9710a8ac0c1SNamjae Jeon if (ntfs_inode_attr_pread(bmp_vi, bpos, 1, &byte) != 1) { 9720a8ac0c1SNamjae Jeon ret = -EIO; 9730a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to read $BITMAP"); 9740a8ac0c1SNamjae Jeon goto err; 9750a8ac0c1SNamjae Jeon } 9760a8ac0c1SNamjae Jeon 9770a8ac0c1SNamjae Jeon if (set) 9780a8ac0c1SNamjae Jeon byte |= bit; 9790a8ac0c1SNamjae Jeon else 9800a8ac0c1SNamjae Jeon byte &= ~bit; 9810a8ac0c1SNamjae Jeon 9820a8ac0c1SNamjae Jeon if (ntfs_inode_attr_pwrite(bmp_vi, bpos, 1, &byte, false) != 1) { 9830a8ac0c1SNamjae Jeon ret = -EIO; 9840a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to write $Bitmap"); 9850a8ac0c1SNamjae Jeon goto err; 9860a8ac0c1SNamjae Jeon } 9870a8ac0c1SNamjae Jeon 9880a8ac0c1SNamjae Jeon err: 9890a8ac0c1SNamjae Jeon iput(bmp_vi); 9900a8ac0c1SNamjae Jeon return ret; 9910a8ac0c1SNamjae Jeon } 9920a8ac0c1SNamjae Jeon 9930a8ac0c1SNamjae Jeon static int ntfs_ibm_set(struct ntfs_index_context *icx, s64 vcn) 9940a8ac0c1SNamjae Jeon { 9950a8ac0c1SNamjae Jeon return ntfs_ibm_modify(icx, vcn, 1); 9960a8ac0c1SNamjae Jeon } 9970a8ac0c1SNamjae Jeon 9980a8ac0c1SNamjae Jeon static int ntfs_ibm_clear(struct ntfs_index_context *icx, s64 vcn) 9990a8ac0c1SNamjae Jeon { 10000a8ac0c1SNamjae Jeon return ntfs_ibm_modify(icx, vcn, 0); 10010a8ac0c1SNamjae Jeon } 10020a8ac0c1SNamjae Jeon 10030a8ac0c1SNamjae Jeon static s64 ntfs_ibm_get_free(struct ntfs_index_context *icx) 10040a8ac0c1SNamjae Jeon { 10050a8ac0c1SNamjae Jeon u8 *bm; 10060a8ac0c1SNamjae Jeon int bit; 10070a8ac0c1SNamjae Jeon s64 vcn, byte, size; 10080a8ac0c1SNamjae Jeon 10090a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 10100a8ac0c1SNamjae Jeon 10110a8ac0c1SNamjae Jeon bm = ntfs_attr_readall(icx->idx_ni, AT_BITMAP, icx->name, icx->name_len, 10120a8ac0c1SNamjae Jeon &size); 10130a8ac0c1SNamjae Jeon if (!bm) 10140a8ac0c1SNamjae Jeon return (s64)-1; 10150a8ac0c1SNamjae Jeon 10160a8ac0c1SNamjae Jeon for (byte = 0; byte < size; byte++) { 10170a8ac0c1SNamjae Jeon if (bm[byte] == 255) 10180a8ac0c1SNamjae Jeon continue; 10190a8ac0c1SNamjae Jeon 10200a8ac0c1SNamjae Jeon for (bit = 0; bit < 8; bit++) { 10210a8ac0c1SNamjae Jeon if (!(bm[byte] & (1 << bit))) { 10220a8ac0c1SNamjae Jeon vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); 10230a8ac0c1SNamjae Jeon goto out; 10240a8ac0c1SNamjae Jeon } 10250a8ac0c1SNamjae Jeon } 10260a8ac0c1SNamjae Jeon } 10270a8ac0c1SNamjae Jeon 10280a8ac0c1SNamjae Jeon vcn = ntfs_ibm_pos_to_vcn(icx, size * 8); 10290a8ac0c1SNamjae Jeon out: 10300a8ac0c1SNamjae Jeon ntfs_debug("allocated vcn: %lld\n", vcn); 10310a8ac0c1SNamjae Jeon 10320a8ac0c1SNamjae Jeon if (ntfs_ibm_set(icx, vcn)) 10330a8ac0c1SNamjae Jeon vcn = (s64)-1; 10340a8ac0c1SNamjae Jeon 10350a8ac0c1SNamjae Jeon kvfree(bm); 10360a8ac0c1SNamjae Jeon return vcn; 10370a8ac0c1SNamjae Jeon } 10380a8ac0c1SNamjae Jeon 10390a8ac0c1SNamjae Jeon static struct index_block *ntfs_ir_to_ib(struct index_root *ir, s64 ib_vcn) 10400a8ac0c1SNamjae Jeon { 10410a8ac0c1SNamjae Jeon struct index_block *ib; 10420a8ac0c1SNamjae Jeon struct index_entry *ie_last; 10430a8ac0c1SNamjae Jeon char *ies_start, *ies_end; 10440a8ac0c1SNamjae Jeon int i; 10450a8ac0c1SNamjae Jeon 10460a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 10470a8ac0c1SNamjae Jeon 10480a8ac0c1SNamjae Jeon ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), LEAF_NODE); 10490a8ac0c1SNamjae Jeon if (!ib) 10500a8ac0c1SNamjae Jeon return NULL; 10510a8ac0c1SNamjae Jeon 10520a8ac0c1SNamjae Jeon ies_start = (char *)ntfs_ie_get_first(&ir->index); 10530a8ac0c1SNamjae Jeon ies_end = (char *)ntfs_ie_get_end(&ir->index); 10540a8ac0c1SNamjae Jeon ie_last = ntfs_ie_get_last((struct index_entry *)ies_start, ies_end); 10550a8ac0c1SNamjae Jeon /* 10560a8ac0c1SNamjae Jeon * Copy all entries, including the termination entry 10570a8ac0c1SNamjae Jeon * as well, which can never have any data. 10580a8ac0c1SNamjae Jeon */ 10590a8ac0c1SNamjae Jeon i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length); 10600a8ac0c1SNamjae Jeon memcpy(ntfs_ie_get_first(&ib->index), ies_start, i); 10610a8ac0c1SNamjae Jeon 10620a8ac0c1SNamjae Jeon ib->index.flags = ir->index.flags; 10630a8ac0c1SNamjae Jeon ib->index.index_length = cpu_to_le32(i + 10640a8ac0c1SNamjae Jeon le32_to_cpu(ib->index.entries_offset)); 10650a8ac0c1SNamjae Jeon return ib; 10660a8ac0c1SNamjae Jeon } 10670a8ac0c1SNamjae Jeon 10680a8ac0c1SNamjae Jeon static void ntfs_ir_nill(struct index_root *ir) 10690a8ac0c1SNamjae Jeon { 10700a8ac0c1SNamjae Jeon struct index_entry *ie_last; 10710a8ac0c1SNamjae Jeon char *ies_start, *ies_end; 10720a8ac0c1SNamjae Jeon 10730a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 10740a8ac0c1SNamjae Jeon 10750a8ac0c1SNamjae Jeon ies_start = (char *)ntfs_ie_get_first(&ir->index); 10760a8ac0c1SNamjae Jeon ies_end = (char *)ntfs_ie_get_end(&ir->index); 10770a8ac0c1SNamjae Jeon ie_last = ntfs_ie_get_last((struct index_entry *)ies_start, ies_end); 10780a8ac0c1SNamjae Jeon /* 10790a8ac0c1SNamjae Jeon * Move the index root termination entry forward 10800a8ac0c1SNamjae Jeon */ 10810a8ac0c1SNamjae Jeon if ((char *)ie_last > ies_start) { 10820a8ac0c1SNamjae Jeon memmove((char *)ntfs_ie_get_first(&ir->index), 10830a8ac0c1SNamjae Jeon (char *)ie_last, le16_to_cpu(ie_last->length)); 10840a8ac0c1SNamjae Jeon ie_last = (struct index_entry *)ies_start; 10850a8ac0c1SNamjae Jeon } 10860a8ac0c1SNamjae Jeon } 10870a8ac0c1SNamjae Jeon 10880a8ac0c1SNamjae Jeon static int ntfs_ib_copy_tail(struct ntfs_index_context *icx, struct index_block *src, 10890a8ac0c1SNamjae Jeon struct index_entry *median, s64 new_vcn) 10900a8ac0c1SNamjae Jeon { 10910a8ac0c1SNamjae Jeon u8 *ies_end; 10920a8ac0c1SNamjae Jeon struct index_entry *ie_head; /* first entry after the median */ 10930a8ac0c1SNamjae Jeon int tail_size, ret; 10940a8ac0c1SNamjae Jeon struct index_block *dst; 10950a8ac0c1SNamjae Jeon 10960a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 10970a8ac0c1SNamjae Jeon 10980a8ac0c1SNamjae Jeon dst = ntfs_ib_alloc(new_vcn, icx->block_size, 10990a8ac0c1SNamjae Jeon src->index.flags & NODE_MASK); 11000a8ac0c1SNamjae Jeon if (!dst) 11010a8ac0c1SNamjae Jeon return -ENOMEM; 11020a8ac0c1SNamjae Jeon 11030a8ac0c1SNamjae Jeon ie_head = ntfs_ie_get_next(median); 11040a8ac0c1SNamjae Jeon 11050a8ac0c1SNamjae Jeon ies_end = (u8 *)ntfs_ie_get_end(&src->index); 11060a8ac0c1SNamjae Jeon tail_size = ies_end - (u8 *)ie_head; 11070a8ac0c1SNamjae Jeon memcpy(ntfs_ie_get_first(&dst->index), ie_head, tail_size); 11080a8ac0c1SNamjae Jeon 11090a8ac0c1SNamjae Jeon dst->index.index_length = cpu_to_le32(tail_size + 11100a8ac0c1SNamjae Jeon le32_to_cpu(dst->index.entries_offset)); 11110a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, dst); 11120a8ac0c1SNamjae Jeon 11130a8ac0c1SNamjae Jeon kvfree(dst); 11140a8ac0c1SNamjae Jeon return ret; 11150a8ac0c1SNamjae Jeon } 11160a8ac0c1SNamjae Jeon 11170a8ac0c1SNamjae Jeon static int ntfs_ib_cut_tail(struct ntfs_index_context *icx, struct index_block *ib, 11180a8ac0c1SNamjae Jeon struct index_entry *ie) 11190a8ac0c1SNamjae Jeon { 11200a8ac0c1SNamjae Jeon char *ies_start, *ies_end; 11210a8ac0c1SNamjae Jeon struct index_entry *ie_last; 11220a8ac0c1SNamjae Jeon int ret; 11230a8ac0c1SNamjae Jeon 11240a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 11250a8ac0c1SNamjae Jeon 11260a8ac0c1SNamjae Jeon ies_start = (char *)ntfs_ie_get_first(&ib->index); 11270a8ac0c1SNamjae Jeon ies_end = (char *)ntfs_ie_get_end(&ib->index); 11280a8ac0c1SNamjae Jeon 11290a8ac0c1SNamjae Jeon ie_last = ntfs_ie_get_last((struct index_entry *)ies_start, ies_end); 11300a8ac0c1SNamjae Jeon if (ie_last->flags & INDEX_ENTRY_NODE) 11310a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie_last, ntfs_ie_get_vcn(ie)); 11320a8ac0c1SNamjae Jeon 11330a8ac0c1SNamjae Jeon unsafe_memcpy(ie, ie_last, le16_to_cpu(ie_last->length), 11340a8ac0c1SNamjae Jeon /* alloc is larger than ie_last->length, see ntfs_ie_get_last() */); 11350a8ac0c1SNamjae Jeon 11360a8ac0c1SNamjae Jeon ib->index.index_length = cpu_to_le32(((char *)ie - ies_start) + 11370a8ac0c1SNamjae Jeon le16_to_cpu(ie->length) + le32_to_cpu(ib->index.entries_offset)); 11380a8ac0c1SNamjae Jeon 11390a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, ib); 11400a8ac0c1SNamjae Jeon return ret; 11410a8ac0c1SNamjae Jeon } 11420a8ac0c1SNamjae Jeon 11430a8ac0c1SNamjae Jeon static int ntfs_ia_add(struct ntfs_index_context *icx) 11440a8ac0c1SNamjae Jeon { 11450a8ac0c1SNamjae Jeon int ret; 11460a8ac0c1SNamjae Jeon 11470a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 11480a8ac0c1SNamjae Jeon 11490a8ac0c1SNamjae Jeon ret = ntfs_ibm_add(icx); 11500a8ac0c1SNamjae Jeon if (ret) 11510a8ac0c1SNamjae Jeon return ret; 11520a8ac0c1SNamjae Jeon 11530a8ac0c1SNamjae Jeon if (!ntfs_attr_exist(icx->idx_ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) { 11540a8ac0c1SNamjae Jeon ret = ntfs_attr_add(icx->idx_ni, AT_INDEX_ALLOCATION, icx->name, 11550a8ac0c1SNamjae Jeon icx->name_len, NULL, 0); 11560a8ac0c1SNamjae Jeon if (ret) { 11570a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to add AT_INDEX_ALLOCATION"); 11580a8ac0c1SNamjae Jeon return ret; 11590a8ac0c1SNamjae Jeon } 11600a8ac0c1SNamjae Jeon } 11610a8ac0c1SNamjae Jeon 11620a8ac0c1SNamjae Jeon icx->ia_ni = ntfs_ia_open(icx, icx->idx_ni); 11630a8ac0c1SNamjae Jeon if (!icx->ia_ni) 11640a8ac0c1SNamjae Jeon return -ENOENT; 11650a8ac0c1SNamjae Jeon 11660a8ac0c1SNamjae Jeon return 0; 11670a8ac0c1SNamjae Jeon } 11680a8ac0c1SNamjae Jeon 11690a8ac0c1SNamjae Jeon static int ntfs_ir_reparent(struct ntfs_index_context *icx) 11700a8ac0c1SNamjae Jeon { 11710a8ac0c1SNamjae Jeon struct ntfs_attr_search_ctx *ctx = NULL; 11720a8ac0c1SNamjae Jeon struct index_root *ir; 11730a8ac0c1SNamjae Jeon struct index_entry *ie; 11740a8ac0c1SNamjae Jeon struct index_block *ib = NULL; 11750a8ac0c1SNamjae Jeon s64 new_ib_vcn; 11760a8ac0c1SNamjae Jeon int ix_root_size; 11770a8ac0c1SNamjae Jeon int ret = 0; 11780a8ac0c1SNamjae Jeon 11790a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 11800a8ac0c1SNamjae Jeon 11810a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup2(icx->idx_ni, icx->name, icx->name_len); 11820a8ac0c1SNamjae Jeon if (!ir) { 11830a8ac0c1SNamjae Jeon ret = -ENOENT; 11840a8ac0c1SNamjae Jeon goto out; 11850a8ac0c1SNamjae Jeon } 11860a8ac0c1SNamjae Jeon 11870a8ac0c1SNamjae Jeon if ((ir->index.flags & NODE_MASK) == SMALL_INDEX) { 11880a8ac0c1SNamjae Jeon ret = ntfs_ia_add(icx); 11890a8ac0c1SNamjae Jeon if (ret) 11900a8ac0c1SNamjae Jeon goto out; 11910a8ac0c1SNamjae Jeon } 11920a8ac0c1SNamjae Jeon 11930a8ac0c1SNamjae Jeon new_ib_vcn = ntfs_ibm_get_free(icx); 11940a8ac0c1SNamjae Jeon if (new_ib_vcn < 0) { 11950a8ac0c1SNamjae Jeon ret = -EINVAL; 11960a8ac0c1SNamjae Jeon goto out; 11970a8ac0c1SNamjae Jeon } 11980a8ac0c1SNamjae Jeon 11990a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup2(icx->idx_ni, icx->name, icx->name_len); 12000a8ac0c1SNamjae Jeon if (!ir) { 12010a8ac0c1SNamjae Jeon ret = -ENOENT; 12020a8ac0c1SNamjae Jeon goto clear_bmp; 12030a8ac0c1SNamjae Jeon } 12040a8ac0c1SNamjae Jeon 12050a8ac0c1SNamjae Jeon ib = ntfs_ir_to_ib(ir, new_ib_vcn); 12060a8ac0c1SNamjae Jeon if (ib == NULL) { 12070a8ac0c1SNamjae Jeon ret = -EIO; 12080a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to move index root to index block"); 12090a8ac0c1SNamjae Jeon goto clear_bmp; 12100a8ac0c1SNamjae Jeon } 12110a8ac0c1SNamjae Jeon 12120a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, ib); 12130a8ac0c1SNamjae Jeon if (ret) 12140a8ac0c1SNamjae Jeon goto clear_bmp; 12150a8ac0c1SNamjae Jeon 12160a8ac0c1SNamjae Jeon retry: 12170a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup(icx->idx_ni, icx->name, icx->name_len, &ctx); 12180a8ac0c1SNamjae Jeon if (!ir) { 12190a8ac0c1SNamjae Jeon ret = -ENOENT; 12200a8ac0c1SNamjae Jeon goto clear_bmp; 12210a8ac0c1SNamjae Jeon } 12220a8ac0c1SNamjae Jeon 12230a8ac0c1SNamjae Jeon ntfs_ir_nill(ir); 12240a8ac0c1SNamjae Jeon 12250a8ac0c1SNamjae Jeon ie = ntfs_ie_get_first(&ir->index); 12260a8ac0c1SNamjae Jeon ie->flags |= INDEX_ENTRY_NODE; 12270a8ac0c1SNamjae Jeon ie->length = cpu_to_le16(sizeof(struct index_entry_header) + sizeof(s64)); 12280a8ac0c1SNamjae Jeon 12290a8ac0c1SNamjae Jeon ir->index.flags = LARGE_INDEX; 12300a8ac0c1SNamjae Jeon NInoSetIndexAllocPresent(icx->idx_ni); 12310a8ac0c1SNamjae Jeon ir->index.index_length = cpu_to_le32(le32_to_cpu(ir->index.entries_offset) + 12320a8ac0c1SNamjae Jeon le16_to_cpu(ie->length)); 12330a8ac0c1SNamjae Jeon ir->index.allocated_size = ir->index.index_length; 12340a8ac0c1SNamjae Jeon 12350a8ac0c1SNamjae Jeon ix_root_size = sizeof(struct index_root) - sizeof(struct index_header) + 12360a8ac0c1SNamjae Jeon le32_to_cpu(ir->index.allocated_size); 12370a8ac0c1SNamjae Jeon ret = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, ix_root_size); 12380a8ac0c1SNamjae Jeon if (ret) { 12390a8ac0c1SNamjae Jeon /* 12400a8ac0c1SNamjae Jeon * When there is no space to build a non-resident 12410a8ac0c1SNamjae Jeon * index, we may have to move the root to an extent 12420a8ac0c1SNamjae Jeon */ 12430a8ac0c1SNamjae Jeon if ((ret == -ENOSPC) && (ctx->al_entry || !ntfs_inode_add_attrlist(icx->idx_ni))) { 12440a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 12450a8ac0c1SNamjae Jeon ctx = NULL; 12460a8ac0c1SNamjae Jeon ir = ntfs_ir_lookup(icx->idx_ni, icx->name, icx->name_len, &ctx); 12470a8ac0c1SNamjae Jeon if (ir && !ntfs_attr_record_move_away(ctx, ix_root_size - 12480a8ac0c1SNamjae Jeon le32_to_cpu(ctx->attr->data.resident.value_length))) { 12490a8ac0c1SNamjae Jeon if (ntfs_attrlist_update(ctx->base_ntfs_ino ? 12500a8ac0c1SNamjae Jeon ctx->base_ntfs_ino : ctx->ntfs_ino)) 12510a8ac0c1SNamjae Jeon goto clear_bmp; 12520a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 12530a8ac0c1SNamjae Jeon ctx = NULL; 12540a8ac0c1SNamjae Jeon goto retry; 12550a8ac0c1SNamjae Jeon } 12560a8ac0c1SNamjae Jeon } 12570a8ac0c1SNamjae Jeon goto clear_bmp; 12580a8ac0c1SNamjae Jeon } else { 12590a8ac0c1SNamjae Jeon icx->idx_ni->data_size = icx->idx_ni->initialized_size = ix_root_size; 12600a8ac0c1SNamjae Jeon icx->idx_ni->allocated_size = (ix_root_size + 7) & ~7; 12610a8ac0c1SNamjae Jeon } 12620a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie, new_ib_vcn); 12630a8ac0c1SNamjae Jeon 12640a8ac0c1SNamjae Jeon err_out: 12650a8ac0c1SNamjae Jeon kvfree(ib); 12660a8ac0c1SNamjae Jeon if (ctx) 12670a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 12680a8ac0c1SNamjae Jeon out: 12690a8ac0c1SNamjae Jeon return ret; 12700a8ac0c1SNamjae Jeon clear_bmp: 12710a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, new_ib_vcn); 12721e9ea7e0SNamjae Jeon goto err_out; 12731e9ea7e0SNamjae Jeon } 12740a8ac0c1SNamjae Jeon 12750a8ac0c1SNamjae Jeon /* 12760a8ac0c1SNamjae Jeon * ntfs_ir_truncate - Truncate index root attribute 12770a8ac0c1SNamjae Jeon * @icx: index context 12780a8ac0c1SNamjae Jeon * @data_size: new data size for the index root 12790a8ac0c1SNamjae Jeon */ 12800a8ac0c1SNamjae Jeon static int ntfs_ir_truncate(struct ntfs_index_context *icx, int data_size) 12810a8ac0c1SNamjae Jeon { 12820a8ac0c1SNamjae Jeon int ret; 12830a8ac0c1SNamjae Jeon 12840a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 12850a8ac0c1SNamjae Jeon 12860a8ac0c1SNamjae Jeon /* 12870a8ac0c1SNamjae Jeon * INDEX_ROOT must be resident and its entries can be moved to 12880a8ac0c1SNamjae Jeon * struct index_block, so ENOSPC isn't a real error. 12890a8ac0c1SNamjae Jeon */ 12900a8ac0c1SNamjae Jeon ret = ntfs_attr_truncate(icx->idx_ni, data_size + offsetof(struct index_root, index)); 12910a8ac0c1SNamjae Jeon if (!ret) { 12920a8ac0c1SNamjae Jeon i_size_write(VFS_I(icx->idx_ni), icx->idx_ni->initialized_size); 12930a8ac0c1SNamjae Jeon icx->ir = ntfs_ir_lookup2(icx->idx_ni, icx->name, icx->name_len); 12940a8ac0c1SNamjae Jeon if (!icx->ir) 12950a8ac0c1SNamjae Jeon return -ENOENT; 12960a8ac0c1SNamjae Jeon 12970a8ac0c1SNamjae Jeon icx->ir->index.allocated_size = cpu_to_le32(data_size); 12980a8ac0c1SNamjae Jeon } else if (ret != -ENOSPC) 12990a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to truncate INDEX_ROOT"); 13000a8ac0c1SNamjae Jeon 13010a8ac0c1SNamjae Jeon return ret; 13020a8ac0c1SNamjae Jeon } 13030a8ac0c1SNamjae Jeon 13040a8ac0c1SNamjae Jeon /* 13050a8ac0c1SNamjae Jeon * ntfs_ir_make_space - Make more space for the index root attribute 13060a8ac0c1SNamjae Jeon * @icx: index context 13070a8ac0c1SNamjae Jeon * @data_size: required data size for the index root 13080a8ac0c1SNamjae Jeon */ 13090a8ac0c1SNamjae Jeon static int ntfs_ir_make_space(struct ntfs_index_context *icx, int data_size) 13100a8ac0c1SNamjae Jeon { 13110a8ac0c1SNamjae Jeon int ret; 13120a8ac0c1SNamjae Jeon 13130a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 13140a8ac0c1SNamjae Jeon 13150a8ac0c1SNamjae Jeon ret = ntfs_ir_truncate(icx, data_size); 13160a8ac0c1SNamjae Jeon if (ret == -ENOSPC) { 13170a8ac0c1SNamjae Jeon ret = ntfs_ir_reparent(icx); 13180a8ac0c1SNamjae Jeon if (!ret) 13190a8ac0c1SNamjae Jeon ret = -EAGAIN; 13200a8ac0c1SNamjae Jeon else 13210a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to modify INDEX_ROOT"); 13220a8ac0c1SNamjae Jeon } 13230a8ac0c1SNamjae Jeon 13240a8ac0c1SNamjae Jeon return ret; 13250a8ac0c1SNamjae Jeon } 13260a8ac0c1SNamjae Jeon 13270a8ac0c1SNamjae Jeon /* 13280a8ac0c1SNamjae Jeon * NOTE: 'ie' must be a copy of a real index entry. 13290a8ac0c1SNamjae Jeon */ 13300a8ac0c1SNamjae Jeon static int ntfs_ie_add_vcn(struct index_entry **ie) 13310a8ac0c1SNamjae Jeon { 13320a8ac0c1SNamjae Jeon struct index_entry *p, *old = *ie; 13330a8ac0c1SNamjae Jeon 13340a8ac0c1SNamjae Jeon old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(s64)); 13350a8ac0c1SNamjae Jeon p = krealloc(old, le16_to_cpu(old->length), GFP_NOFS); 13360a8ac0c1SNamjae Jeon if (!p) 13370a8ac0c1SNamjae Jeon return -ENOMEM; 13380a8ac0c1SNamjae Jeon 13390a8ac0c1SNamjae Jeon p->flags |= INDEX_ENTRY_NODE; 13400a8ac0c1SNamjae Jeon *ie = p; 13410a8ac0c1SNamjae Jeon return 0; 13420a8ac0c1SNamjae Jeon } 13430a8ac0c1SNamjae Jeon 13440a8ac0c1SNamjae Jeon static int ntfs_ih_insert(struct index_header *ih, struct index_entry *orig_ie, s64 new_vcn, 13450a8ac0c1SNamjae Jeon int pos) 13460a8ac0c1SNamjae Jeon { 13470a8ac0c1SNamjae Jeon struct index_entry *ie_node, *ie; 13480a8ac0c1SNamjae Jeon int ret = 0; 13490a8ac0c1SNamjae Jeon s64 old_vcn; 13500a8ac0c1SNamjae Jeon 13510a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 13520a8ac0c1SNamjae Jeon ie = ntfs_ie_dup(orig_ie); 13530a8ac0c1SNamjae Jeon if (!ie) 13540a8ac0c1SNamjae Jeon return -ENOMEM; 13550a8ac0c1SNamjae Jeon 13560a8ac0c1SNamjae Jeon if (!(ie->flags & INDEX_ENTRY_NODE)) { 13570a8ac0c1SNamjae Jeon ret = ntfs_ie_add_vcn(&ie); 13580a8ac0c1SNamjae Jeon if (ret) 13590a8ac0c1SNamjae Jeon goto out; 13600a8ac0c1SNamjae Jeon } 13610a8ac0c1SNamjae Jeon 13620a8ac0c1SNamjae Jeon ie_node = ntfs_ie_get_by_pos(ih, pos); 13630a8ac0c1SNamjae Jeon old_vcn = ntfs_ie_get_vcn(ie_node); 13640a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie_node, new_vcn); 13650a8ac0c1SNamjae Jeon 13660a8ac0c1SNamjae Jeon ntfs_ie_insert(ih, ie, ie_node); 13670a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie_node, old_vcn); 13680a8ac0c1SNamjae Jeon out: 13690a8ac0c1SNamjae Jeon kfree(ie); 13700a8ac0c1SNamjae Jeon return ret; 13710a8ac0c1SNamjae Jeon } 13720a8ac0c1SNamjae Jeon 13730a8ac0c1SNamjae Jeon static s64 ntfs_icx_parent_vcn(struct ntfs_index_context *icx) 13740a8ac0c1SNamjae Jeon { 13750a8ac0c1SNamjae Jeon return icx->parent_vcn[icx->pindex]; 13760a8ac0c1SNamjae Jeon } 13770a8ac0c1SNamjae Jeon 13780a8ac0c1SNamjae Jeon static s64 ntfs_icx_parent_pos(struct ntfs_index_context *icx) 13790a8ac0c1SNamjae Jeon { 13800a8ac0c1SNamjae Jeon return icx->parent_pos[icx->pindex]; 13810a8ac0c1SNamjae Jeon } 13820a8ac0c1SNamjae Jeon 13830a8ac0c1SNamjae Jeon static int ntfs_ir_insert_median(struct ntfs_index_context *icx, struct index_entry *median, 13840a8ac0c1SNamjae Jeon s64 new_vcn) 13850a8ac0c1SNamjae Jeon { 13860a8ac0c1SNamjae Jeon u32 new_size; 13870a8ac0c1SNamjae Jeon int ret; 13880a8ac0c1SNamjae Jeon 13890a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 13900a8ac0c1SNamjae Jeon 13910a8ac0c1SNamjae Jeon icx->ir = ntfs_ir_lookup2(icx->idx_ni, icx->name, icx->name_len); 13920a8ac0c1SNamjae Jeon if (!icx->ir) 13930a8ac0c1SNamjae Jeon return -ENOENT; 13940a8ac0c1SNamjae Jeon 13950a8ac0c1SNamjae Jeon new_size = le32_to_cpu(icx->ir->index.index_length) + 13960a8ac0c1SNamjae Jeon le16_to_cpu(median->length); 13970a8ac0c1SNamjae Jeon if (!(median->flags & INDEX_ENTRY_NODE)) 13980a8ac0c1SNamjae Jeon new_size += sizeof(s64); 13990a8ac0c1SNamjae Jeon 14000a8ac0c1SNamjae Jeon ret = ntfs_ir_make_space(icx, new_size); 14010a8ac0c1SNamjae Jeon if (ret) 14020a8ac0c1SNamjae Jeon return ret; 14030a8ac0c1SNamjae Jeon 14040a8ac0c1SNamjae Jeon icx->ir = ntfs_ir_lookup2(icx->idx_ni, icx->name, icx->name_len); 14050a8ac0c1SNamjae Jeon if (!icx->ir) 14060a8ac0c1SNamjae Jeon return -ENOENT; 14070a8ac0c1SNamjae Jeon 14080a8ac0c1SNamjae Jeon return ntfs_ih_insert(&icx->ir->index, median, new_vcn, 14090a8ac0c1SNamjae Jeon ntfs_icx_parent_pos(icx)); 14100a8ac0c1SNamjae Jeon } 14110a8ac0c1SNamjae Jeon 14120a8ac0c1SNamjae Jeon static int ntfs_ib_split(struct ntfs_index_context *icx, struct index_block *ib); 14130a8ac0c1SNamjae Jeon 14140a8ac0c1SNamjae Jeon struct split_info { 14150a8ac0c1SNamjae Jeon struct list_head entry; 14160a8ac0c1SNamjae Jeon s64 new_vcn; 14170a8ac0c1SNamjae Jeon struct index_block *ib; 14180a8ac0c1SNamjae Jeon }; 14190a8ac0c1SNamjae Jeon 14200a8ac0c1SNamjae Jeon static int ntfs_ib_insert(struct ntfs_index_context *icx, struct index_entry *ie, s64 new_vcn, 14210a8ac0c1SNamjae Jeon struct split_info *si) 14220a8ac0c1SNamjae Jeon { 14230a8ac0c1SNamjae Jeon struct index_block *ib; 14240a8ac0c1SNamjae Jeon u32 idx_size, allocated_size; 14250a8ac0c1SNamjae Jeon int err; 14260a8ac0c1SNamjae Jeon s64 old_vcn; 14270a8ac0c1SNamjae Jeon 14280a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 14290a8ac0c1SNamjae Jeon 14300a8ac0c1SNamjae Jeon ib = kvzalloc(icx->block_size, GFP_NOFS); 14310a8ac0c1SNamjae Jeon if (!ib) 14320a8ac0c1SNamjae Jeon return -ENOMEM; 14330a8ac0c1SNamjae Jeon 14340a8ac0c1SNamjae Jeon old_vcn = ntfs_icx_parent_vcn(icx); 14350a8ac0c1SNamjae Jeon 14360a8ac0c1SNamjae Jeon err = ntfs_ib_read(icx, old_vcn, ib); 14370a8ac0c1SNamjae Jeon if (err) 14380a8ac0c1SNamjae Jeon goto err_out; 14390a8ac0c1SNamjae Jeon 14400a8ac0c1SNamjae Jeon idx_size = le32_to_cpu(ib->index.index_length); 14410a8ac0c1SNamjae Jeon allocated_size = le32_to_cpu(ib->index.allocated_size); 14420a8ac0c1SNamjae Jeon if (idx_size + le16_to_cpu(ie->length) + sizeof(s64) > allocated_size) { 14430a8ac0c1SNamjae Jeon si->ib = ib; 14440a8ac0c1SNamjae Jeon si->new_vcn = new_vcn; 14450a8ac0c1SNamjae Jeon return -EAGAIN; 14460a8ac0c1SNamjae Jeon } 14470a8ac0c1SNamjae Jeon 14480a8ac0c1SNamjae Jeon err = ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx)); 14490a8ac0c1SNamjae Jeon if (err) 14500a8ac0c1SNamjae Jeon goto err_out; 14510a8ac0c1SNamjae Jeon 14520a8ac0c1SNamjae Jeon err = ntfs_ib_write(icx, ib); 14530a8ac0c1SNamjae Jeon 14540a8ac0c1SNamjae Jeon err_out: 14550a8ac0c1SNamjae Jeon kvfree(ib); 14560a8ac0c1SNamjae Jeon return err; 14570a8ac0c1SNamjae Jeon } 14580a8ac0c1SNamjae Jeon 14590a8ac0c1SNamjae Jeon /* 14600a8ac0c1SNamjae Jeon * ntfs_ib_split - Split an index block 14610a8ac0c1SNamjae Jeon * @icx: index context 14620a8ac0c1SNamjae Jeon * @ib: index block to split 14630a8ac0c1SNamjae Jeon */ 14640a8ac0c1SNamjae Jeon static int ntfs_ib_split(struct ntfs_index_context *icx, struct index_block *ib) 14650a8ac0c1SNamjae Jeon { 14660a8ac0c1SNamjae Jeon struct index_entry *median; 14670a8ac0c1SNamjae Jeon s64 new_vcn; 14680a8ac0c1SNamjae Jeon int ret; 14690a8ac0c1SNamjae Jeon struct split_info *si; 14700a8ac0c1SNamjae Jeon LIST_HEAD(ntfs_cut_tail_list); 14710a8ac0c1SNamjae Jeon 14720a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 14730a8ac0c1SNamjae Jeon 14740a8ac0c1SNamjae Jeon resplit: 14750a8ac0c1SNamjae Jeon ret = ntfs_icx_parent_dec(icx); 14760a8ac0c1SNamjae Jeon if (ret) 14770a8ac0c1SNamjae Jeon goto out; 14780a8ac0c1SNamjae Jeon 14790a8ac0c1SNamjae Jeon median = ntfs_ie_get_median(&ib->index); 14800a8ac0c1SNamjae Jeon new_vcn = ntfs_ibm_get_free(icx); 14810a8ac0c1SNamjae Jeon if (new_vcn < 0) { 14820a8ac0c1SNamjae Jeon ret = -EINVAL; 14830a8ac0c1SNamjae Jeon goto out; 14840a8ac0c1SNamjae Jeon } 14850a8ac0c1SNamjae Jeon 14860a8ac0c1SNamjae Jeon ret = ntfs_ib_copy_tail(icx, ib, median, new_vcn); 14870a8ac0c1SNamjae Jeon if (ret) { 14880a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, new_vcn); 14890a8ac0c1SNamjae Jeon goto out; 14900a8ac0c1SNamjae Jeon } 14910a8ac0c1SNamjae Jeon 14920a8ac0c1SNamjae Jeon if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { 14930a8ac0c1SNamjae Jeon ret = ntfs_ir_insert_median(icx, median, new_vcn); 14940a8ac0c1SNamjae Jeon if (ret) { 14950a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, new_vcn); 14960a8ac0c1SNamjae Jeon goto out; 14970a8ac0c1SNamjae Jeon } 14980a8ac0c1SNamjae Jeon } else { 14990a8ac0c1SNamjae Jeon si = kzalloc(sizeof(struct split_info), GFP_NOFS); 15000a8ac0c1SNamjae Jeon if (!si) { 15010a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, new_vcn); 15020a8ac0c1SNamjae Jeon ret = -ENOMEM; 15030a8ac0c1SNamjae Jeon goto out; 15040a8ac0c1SNamjae Jeon } 15050a8ac0c1SNamjae Jeon 15060a8ac0c1SNamjae Jeon ret = ntfs_ib_insert(icx, median, new_vcn, si); 15070a8ac0c1SNamjae Jeon if (ret == -EAGAIN) { 15080a8ac0c1SNamjae Jeon list_add_tail(&si->entry, &ntfs_cut_tail_list); 15090a8ac0c1SNamjae Jeon ib = si->ib; 15100a8ac0c1SNamjae Jeon goto resplit; 15110a8ac0c1SNamjae Jeon } else if (ret) { 15120a8ac0c1SNamjae Jeon kvfree(si->ib); 15130a8ac0c1SNamjae Jeon kfree(si); 15140a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, new_vcn); 15150a8ac0c1SNamjae Jeon goto out; 15160a8ac0c1SNamjae Jeon } 15170a8ac0c1SNamjae Jeon kfree(si); 15180a8ac0c1SNamjae Jeon } 15190a8ac0c1SNamjae Jeon 15200a8ac0c1SNamjae Jeon ret = ntfs_ib_cut_tail(icx, ib, median); 15210a8ac0c1SNamjae Jeon 15220a8ac0c1SNamjae Jeon out: 15230a8ac0c1SNamjae Jeon while (!list_empty(&ntfs_cut_tail_list)) { 15240a8ac0c1SNamjae Jeon si = list_last_entry(&ntfs_cut_tail_list, struct split_info, entry); 15250a8ac0c1SNamjae Jeon ntfs_ibm_clear(icx, si->new_vcn); 15260a8ac0c1SNamjae Jeon kvfree(si->ib); 15270a8ac0c1SNamjae Jeon list_del(&si->entry); 15280a8ac0c1SNamjae Jeon kfree(si); 15290a8ac0c1SNamjae Jeon if (!ret) 15300a8ac0c1SNamjae Jeon ret = -EAGAIN; 15310a8ac0c1SNamjae Jeon } 15320a8ac0c1SNamjae Jeon 15330a8ac0c1SNamjae Jeon return ret; 15340a8ac0c1SNamjae Jeon } 15350a8ac0c1SNamjae Jeon 15360a8ac0c1SNamjae Jeon int ntfs_ie_add(struct ntfs_index_context *icx, struct index_entry *ie) 15370a8ac0c1SNamjae Jeon { 15380a8ac0c1SNamjae Jeon struct index_header *ih; 15390a8ac0c1SNamjae Jeon int allocated_size, new_size; 15400a8ac0c1SNamjae Jeon int ret; 15410a8ac0c1SNamjae Jeon 15420a8ac0c1SNamjae Jeon while (1) { 15430a8ac0c1SNamjae Jeon ret = ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx); 15440a8ac0c1SNamjae Jeon if (!ret) { 15450a8ac0c1SNamjae Jeon ret = -EEXIST; 15460a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Index already have such entry"); 15470a8ac0c1SNamjae Jeon goto err_out; 15480a8ac0c1SNamjae Jeon } 15490a8ac0c1SNamjae Jeon if (ret != -ENOENT) { 15500a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Failed to find place for new entry"); 15510a8ac0c1SNamjae Jeon goto err_out; 15520a8ac0c1SNamjae Jeon } 15530a8ac0c1SNamjae Jeon ret = 0; 15540a8ac0c1SNamjae Jeon 15550a8ac0c1SNamjae Jeon if (icx->is_in_root) 15560a8ac0c1SNamjae Jeon ih = &icx->ir->index; 15570a8ac0c1SNamjae Jeon else 15580a8ac0c1SNamjae Jeon ih = &icx->ib->index; 15590a8ac0c1SNamjae Jeon 15600a8ac0c1SNamjae Jeon allocated_size = le32_to_cpu(ih->allocated_size); 15610a8ac0c1SNamjae Jeon new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length); 15620a8ac0c1SNamjae Jeon 15630a8ac0c1SNamjae Jeon if (new_size <= allocated_size) 15640a8ac0c1SNamjae Jeon break; 15650a8ac0c1SNamjae Jeon 15660a8ac0c1SNamjae Jeon ntfs_debug("index block sizes: allocated: %d needed: %d\n", 15670a8ac0c1SNamjae Jeon allocated_size, new_size); 15680a8ac0c1SNamjae Jeon 15690a8ac0c1SNamjae Jeon if (icx->is_in_root) 15700a8ac0c1SNamjae Jeon ret = ntfs_ir_make_space(icx, new_size); 15710a8ac0c1SNamjae Jeon else 15720a8ac0c1SNamjae Jeon ret = ntfs_ib_split(icx, icx->ib); 15730a8ac0c1SNamjae Jeon if (ret && ret != -EAGAIN) 15740a8ac0c1SNamjae Jeon goto err_out; 15750a8ac0c1SNamjae Jeon 15760a8ac0c1SNamjae Jeon mark_mft_record_dirty(icx->actx->ntfs_ino); 15770a8ac0c1SNamjae Jeon ntfs_index_ctx_reinit(icx); 15780a8ac0c1SNamjae Jeon } 15790a8ac0c1SNamjae Jeon 15800a8ac0c1SNamjae Jeon ntfs_ie_insert(ih, ie, icx->entry); 15810a8ac0c1SNamjae Jeon ntfs_index_entry_mark_dirty(icx); 15820a8ac0c1SNamjae Jeon 15830a8ac0c1SNamjae Jeon err_out: 15840a8ac0c1SNamjae Jeon ntfs_debug("%s\n", ret ? "Failed" : "Done"); 15850a8ac0c1SNamjae Jeon return ret; 15860a8ac0c1SNamjae Jeon } 15870a8ac0c1SNamjae Jeon 15880a8ac0c1SNamjae Jeon /* 15890a8ac0c1SNamjae Jeon * ntfs_index_add_filename - add filename to directory index 15900a8ac0c1SNamjae Jeon * @ni: ntfs inode describing directory to which index add filename 15910a8ac0c1SNamjae Jeon * @fn: FILE_NAME attribute to add 15920a8ac0c1SNamjae Jeon * @mref: reference of the inode which @fn describes 15930a8ac0c1SNamjae Jeon */ 15940a8ac0c1SNamjae Jeon int ntfs_index_add_filename(struct ntfs_inode *ni, struct file_name_attr *fn, u64 mref) 15950a8ac0c1SNamjae Jeon { 15960a8ac0c1SNamjae Jeon struct index_entry *ie; 15970a8ac0c1SNamjae Jeon struct ntfs_index_context *icx; 15980a8ac0c1SNamjae Jeon int fn_size, ie_size, err; 15990a8ac0c1SNamjae Jeon 16000a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 16010a8ac0c1SNamjae Jeon 16020a8ac0c1SNamjae Jeon if (!ni || !fn) 16030a8ac0c1SNamjae Jeon return -EINVAL; 16040a8ac0c1SNamjae Jeon 16050a8ac0c1SNamjae Jeon fn_size = (fn->file_name_length * sizeof(__le16)) + 16060a8ac0c1SNamjae Jeon sizeof(struct file_name_attr); 16070a8ac0c1SNamjae Jeon ie_size = (sizeof(struct index_entry_header) + fn_size + 7) & ~7; 16080a8ac0c1SNamjae Jeon 16090a8ac0c1SNamjae Jeon ie = kzalloc(ie_size, GFP_NOFS); 16100a8ac0c1SNamjae Jeon if (!ie) 16110a8ac0c1SNamjae Jeon return -ENOMEM; 16120a8ac0c1SNamjae Jeon 16130a8ac0c1SNamjae Jeon ie->data.dir.indexed_file = cpu_to_le64(mref); 16140a8ac0c1SNamjae Jeon ie->length = cpu_to_le16(ie_size); 16150a8ac0c1SNamjae Jeon ie->key_length = cpu_to_le16(fn_size); 16160a8ac0c1SNamjae Jeon 16170a8ac0c1SNamjae Jeon unsafe_memcpy(&ie->key, fn, fn_size, 16180a8ac0c1SNamjae Jeon /* "fn_size" was correctly calculated above */); 16190a8ac0c1SNamjae Jeon 16200a8ac0c1SNamjae Jeon icx = ntfs_index_ctx_get(ni, I30, 4); 16210a8ac0c1SNamjae Jeon if (!icx) { 16220a8ac0c1SNamjae Jeon err = -ENOMEM; 16230a8ac0c1SNamjae Jeon goto out; 16240a8ac0c1SNamjae Jeon } 16250a8ac0c1SNamjae Jeon 16260a8ac0c1SNamjae Jeon err = ntfs_ie_add(icx, ie); 16270a8ac0c1SNamjae Jeon ntfs_index_ctx_put(icx); 16280a8ac0c1SNamjae Jeon out: 16290a8ac0c1SNamjae Jeon kfree(ie); 16300a8ac0c1SNamjae Jeon return err; 16310a8ac0c1SNamjae Jeon } 16320a8ac0c1SNamjae Jeon 16330a8ac0c1SNamjae Jeon static int ntfs_ih_takeout(struct ntfs_index_context *icx, struct index_header *ih, 16340a8ac0c1SNamjae Jeon struct index_entry *ie, struct index_block *ib) 16350a8ac0c1SNamjae Jeon { 16360a8ac0c1SNamjae Jeon struct index_entry *ie_roam; 16370a8ac0c1SNamjae Jeon int freed_space; 16380a8ac0c1SNamjae Jeon bool full; 16390a8ac0c1SNamjae Jeon int ret = 0; 16400a8ac0c1SNamjae Jeon 16410a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 16420a8ac0c1SNamjae Jeon 16430a8ac0c1SNamjae Jeon full = ih->index_length == ih->allocated_size; 16440a8ac0c1SNamjae Jeon ie_roam = ntfs_ie_dup_novcn(ie); 16450a8ac0c1SNamjae Jeon if (!ie_roam) 16460a8ac0c1SNamjae Jeon return -ENOMEM; 16470a8ac0c1SNamjae Jeon 16480a8ac0c1SNamjae Jeon ntfs_ie_delete(ih, ie); 16490a8ac0c1SNamjae Jeon 16500a8ac0c1SNamjae Jeon if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { 16510a8ac0c1SNamjae Jeon /* 16520a8ac0c1SNamjae Jeon * Recover the space which may have been freed 16530a8ac0c1SNamjae Jeon * while deleting an entry from root index 16540a8ac0c1SNamjae Jeon */ 16550a8ac0c1SNamjae Jeon freed_space = le32_to_cpu(ih->allocated_size) - 16560a8ac0c1SNamjae Jeon le32_to_cpu(ih->index_length); 16570a8ac0c1SNamjae Jeon if (full && (freed_space > 0) && !(freed_space & 7)) { 16580a8ac0c1SNamjae Jeon ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 16590a8ac0c1SNamjae Jeon /* do nothing if truncation fails */ 16600a8ac0c1SNamjae Jeon } 16610a8ac0c1SNamjae Jeon 16620a8ac0c1SNamjae Jeon mark_mft_record_dirty(icx->actx->ntfs_ino); 16630a8ac0c1SNamjae Jeon } else { 16640a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, ib); 16650a8ac0c1SNamjae Jeon if (ret) 16660a8ac0c1SNamjae Jeon goto out; 16670a8ac0c1SNamjae Jeon } 16680a8ac0c1SNamjae Jeon 16690a8ac0c1SNamjae Jeon ntfs_index_ctx_reinit(icx); 16700a8ac0c1SNamjae Jeon 16710a8ac0c1SNamjae Jeon ret = ntfs_ie_add(icx, ie_roam); 16720a8ac0c1SNamjae Jeon out: 16730a8ac0c1SNamjae Jeon kfree(ie_roam); 16740a8ac0c1SNamjae Jeon return ret; 16750a8ac0c1SNamjae Jeon } 16760a8ac0c1SNamjae Jeon 16770a8ac0c1SNamjae Jeon /* 16780a8ac0c1SNamjae Jeon * Used if an empty index block to be deleted has END entry as the parent 16790a8ac0c1SNamjae Jeon * in the INDEX_ROOT which is the only one there. 16800a8ac0c1SNamjae Jeon */ 16810a8ac0c1SNamjae Jeon static void ntfs_ir_leafify(struct ntfs_index_context *icx, struct index_header *ih) 16820a8ac0c1SNamjae Jeon { 16830a8ac0c1SNamjae Jeon struct index_entry *ie; 16840a8ac0c1SNamjae Jeon 16850a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 16860a8ac0c1SNamjae Jeon 16870a8ac0c1SNamjae Jeon ie = ntfs_ie_get_first(ih); 16880a8ac0c1SNamjae Jeon ie->flags &= ~INDEX_ENTRY_NODE; 16890a8ac0c1SNamjae Jeon ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(s64)); 16900a8ac0c1SNamjae Jeon 16910a8ac0c1SNamjae Jeon ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - sizeof(s64)); 16920a8ac0c1SNamjae Jeon ih->flags &= ~LARGE_INDEX; 16930a8ac0c1SNamjae Jeon NInoClearIndexAllocPresent(icx->idx_ni); 16940a8ac0c1SNamjae Jeon 16950a8ac0c1SNamjae Jeon /* Not fatal error */ 16960a8ac0c1SNamjae Jeon ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 16970a8ac0c1SNamjae Jeon } 16980a8ac0c1SNamjae Jeon 16990a8ac0c1SNamjae Jeon /* 17000a8ac0c1SNamjae Jeon * Used if an empty index block to be deleted has END entry as the parent 17010a8ac0c1SNamjae Jeon * in the INDEX_ROOT which is not the only one there. 17020a8ac0c1SNamjae Jeon */ 17030a8ac0c1SNamjae Jeon static int ntfs_ih_reparent_end(struct ntfs_index_context *icx, struct index_header *ih, 17040a8ac0c1SNamjae Jeon struct index_block *ib) 17050a8ac0c1SNamjae Jeon { 17060a8ac0c1SNamjae Jeon struct index_entry *ie, *ie_prev; 17070a8ac0c1SNamjae Jeon 17080a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 17090a8ac0c1SNamjae Jeon 17100a8ac0c1SNamjae Jeon ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx)); 17110a8ac0c1SNamjae Jeon ie_prev = ntfs_ie_prev(ih, ie); 17120a8ac0c1SNamjae Jeon if (!ie_prev) 17130a8ac0c1SNamjae Jeon return -EIO; 17140a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev)); 17150a8ac0c1SNamjae Jeon 17160a8ac0c1SNamjae Jeon return ntfs_ih_takeout(icx, ih, ie_prev, ib); 17170a8ac0c1SNamjae Jeon } 17180a8ac0c1SNamjae Jeon 17190a8ac0c1SNamjae Jeon static int ntfs_index_rm_leaf(struct ntfs_index_context *icx) 17200a8ac0c1SNamjae Jeon { 17210a8ac0c1SNamjae Jeon struct index_block *ib = NULL; 17220a8ac0c1SNamjae Jeon struct index_header *parent_ih; 17230a8ac0c1SNamjae Jeon struct index_entry *ie; 17240a8ac0c1SNamjae Jeon int ret; 17250a8ac0c1SNamjae Jeon 17260a8ac0c1SNamjae Jeon ntfs_debug("pindex: %d\n", icx->pindex); 17270a8ac0c1SNamjae Jeon 17280a8ac0c1SNamjae Jeon ret = ntfs_icx_parent_dec(icx); 17290a8ac0c1SNamjae Jeon if (ret) 17300a8ac0c1SNamjae Jeon return ret; 17310a8ac0c1SNamjae Jeon 17320a8ac0c1SNamjae Jeon ret = ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1]); 17330a8ac0c1SNamjae Jeon if (ret) 17340a8ac0c1SNamjae Jeon return ret; 17350a8ac0c1SNamjae Jeon 17360a8ac0c1SNamjae Jeon if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) 17370a8ac0c1SNamjae Jeon parent_ih = &icx->ir->index; 17380a8ac0c1SNamjae Jeon else { 17390a8ac0c1SNamjae Jeon ib = kvzalloc(icx->block_size, GFP_NOFS); 17400a8ac0c1SNamjae Jeon if (!ib) 17410a8ac0c1SNamjae Jeon return -ENOMEM; 17420a8ac0c1SNamjae Jeon 17430a8ac0c1SNamjae Jeon ret = ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib); 17440a8ac0c1SNamjae Jeon if (ret) 17450a8ac0c1SNamjae Jeon goto out; 17460a8ac0c1SNamjae Jeon 17470a8ac0c1SNamjae Jeon parent_ih = &ib->index; 17480a8ac0c1SNamjae Jeon } 17490a8ac0c1SNamjae Jeon 17500a8ac0c1SNamjae Jeon ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx)); 17510a8ac0c1SNamjae Jeon if (!ntfs_ie_end(ie)) { 17520a8ac0c1SNamjae Jeon ret = ntfs_ih_takeout(icx, parent_ih, ie, ib); 17530a8ac0c1SNamjae Jeon goto out; 17540a8ac0c1SNamjae Jeon } 17550a8ac0c1SNamjae Jeon 17560a8ac0c1SNamjae Jeon if (ntfs_ih_zero_entry(parent_ih)) { 17570a8ac0c1SNamjae Jeon if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { 17580a8ac0c1SNamjae Jeon ntfs_ir_leafify(icx, parent_ih); 17590a8ac0c1SNamjae Jeon goto out; 17600a8ac0c1SNamjae Jeon } 17610a8ac0c1SNamjae Jeon 17620a8ac0c1SNamjae Jeon ret = ntfs_index_rm_leaf(icx); 17630a8ac0c1SNamjae Jeon goto out; 17640a8ac0c1SNamjae Jeon } 17650a8ac0c1SNamjae Jeon 17660a8ac0c1SNamjae Jeon ret = ntfs_ih_reparent_end(icx, parent_ih, ib); 17670a8ac0c1SNamjae Jeon out: 17680a8ac0c1SNamjae Jeon kvfree(ib); 17690a8ac0c1SNamjae Jeon return ret; 17700a8ac0c1SNamjae Jeon } 17710a8ac0c1SNamjae Jeon 17720a8ac0c1SNamjae Jeon static int ntfs_index_rm_node(struct ntfs_index_context *icx) 17730a8ac0c1SNamjae Jeon { 17740a8ac0c1SNamjae Jeon int entry_pos, pindex; 17750a8ac0c1SNamjae Jeon s64 vcn; 17760a8ac0c1SNamjae Jeon struct index_block *ib = NULL; 17770a8ac0c1SNamjae Jeon struct index_entry *ie_succ, *ie, *entry = icx->entry; 17780a8ac0c1SNamjae Jeon struct index_header *ih; 17790a8ac0c1SNamjae Jeon u32 new_size; 17800a8ac0c1SNamjae Jeon int delta, ret; 17810a8ac0c1SNamjae Jeon 17820a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 17830a8ac0c1SNamjae Jeon 17840a8ac0c1SNamjae Jeon if (!icx->ia_ni) { 17850a8ac0c1SNamjae Jeon icx->ia_ni = ntfs_ia_open(icx, icx->idx_ni); 17860a8ac0c1SNamjae Jeon if (!icx->ia_ni) 17870a8ac0c1SNamjae Jeon return -EINVAL; 17880a8ac0c1SNamjae Jeon } 17890a8ac0c1SNamjae Jeon 17900a8ac0c1SNamjae Jeon ib = kvzalloc(icx->block_size, GFP_NOFS); 17910a8ac0c1SNamjae Jeon if (!ib) 17920a8ac0c1SNamjae Jeon return -ENOMEM; 17930a8ac0c1SNamjae Jeon 17940a8ac0c1SNamjae Jeon ie_succ = ntfs_ie_get_next(icx->entry); 17950a8ac0c1SNamjae Jeon entry_pos = icx->parent_pos[icx->pindex]++; 17960a8ac0c1SNamjae Jeon pindex = icx->pindex; 17970a8ac0c1SNamjae Jeon descend: 17980a8ac0c1SNamjae Jeon vcn = ntfs_ie_get_vcn(ie_succ); 17990a8ac0c1SNamjae Jeon ret = ntfs_ib_read(icx, vcn, ib); 18000a8ac0c1SNamjae Jeon if (ret) 18010a8ac0c1SNamjae Jeon goto out; 18020a8ac0c1SNamjae Jeon 18030a8ac0c1SNamjae Jeon ie_succ = ntfs_ie_get_first(&ib->index); 18040a8ac0c1SNamjae Jeon 18050a8ac0c1SNamjae Jeon ret = ntfs_icx_parent_inc(icx); 18060a8ac0c1SNamjae Jeon if (ret) 18070a8ac0c1SNamjae Jeon goto out; 18080a8ac0c1SNamjae Jeon 18090a8ac0c1SNamjae Jeon icx->parent_vcn[icx->pindex] = vcn; 18100a8ac0c1SNamjae Jeon icx->parent_pos[icx->pindex] = 0; 18110a8ac0c1SNamjae Jeon 18120a8ac0c1SNamjae Jeon if ((ib->index.flags & NODE_MASK) == INDEX_NODE) 18130a8ac0c1SNamjae Jeon goto descend; 18140a8ac0c1SNamjae Jeon 18150a8ac0c1SNamjae Jeon if (ntfs_ih_zero_entry(&ib->index)) { 18160a8ac0c1SNamjae Jeon ret = -EIO; 18170a8ac0c1SNamjae Jeon ntfs_error(icx->idx_ni->vol->sb, "Empty index block"); 18180a8ac0c1SNamjae Jeon goto out; 18190a8ac0c1SNamjae Jeon } 18200a8ac0c1SNamjae Jeon 18210a8ac0c1SNamjae Jeon ie = ntfs_ie_dup(ie_succ); 18220a8ac0c1SNamjae Jeon if (!ie) { 18230a8ac0c1SNamjae Jeon ret = -ENOMEM; 18240a8ac0c1SNamjae Jeon goto out; 18250a8ac0c1SNamjae Jeon } 18260a8ac0c1SNamjae Jeon 18270a8ac0c1SNamjae Jeon ret = ntfs_ie_add_vcn(&ie); 18280a8ac0c1SNamjae Jeon if (ret) 18290a8ac0c1SNamjae Jeon goto out2; 18300a8ac0c1SNamjae Jeon 18310a8ac0c1SNamjae Jeon ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(icx->entry)); 18320a8ac0c1SNamjae Jeon 18330a8ac0c1SNamjae Jeon if (icx->is_in_root) 18340a8ac0c1SNamjae Jeon ih = &icx->ir->index; 18350a8ac0c1SNamjae Jeon else 18360a8ac0c1SNamjae Jeon ih = &icx->ib->index; 18370a8ac0c1SNamjae Jeon 18380a8ac0c1SNamjae Jeon delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length); 18390a8ac0c1SNamjae Jeon new_size = le32_to_cpu(ih->index_length) + delta; 18400a8ac0c1SNamjae Jeon if (delta > 0) { 18410a8ac0c1SNamjae Jeon if (icx->is_in_root) { 18420a8ac0c1SNamjae Jeon ret = ntfs_ir_make_space(icx, new_size); 18430a8ac0c1SNamjae Jeon if (ret != 0) 18440a8ac0c1SNamjae Jeon goto out2; 18450a8ac0c1SNamjae Jeon 18460a8ac0c1SNamjae Jeon ih = &icx->ir->index; 18470a8ac0c1SNamjae Jeon entry = ntfs_ie_get_by_pos(ih, entry_pos); 18480a8ac0c1SNamjae Jeon 18490a8ac0c1SNamjae Jeon } else if (new_size > le32_to_cpu(ih->allocated_size)) { 18500a8ac0c1SNamjae Jeon icx->pindex = pindex; 18510a8ac0c1SNamjae Jeon ret = ntfs_ib_split(icx, icx->ib); 18520a8ac0c1SNamjae Jeon if (!ret) 18530a8ac0c1SNamjae Jeon ret = -EAGAIN; 18540a8ac0c1SNamjae Jeon goto out2; 18550a8ac0c1SNamjae Jeon } 18560a8ac0c1SNamjae Jeon } 18570a8ac0c1SNamjae Jeon 18580a8ac0c1SNamjae Jeon ntfs_ie_delete(ih, entry); 18590a8ac0c1SNamjae Jeon ntfs_ie_insert(ih, ie, entry); 18600a8ac0c1SNamjae Jeon 18610a8ac0c1SNamjae Jeon if (icx->is_in_root) 18620a8ac0c1SNamjae Jeon ret = ntfs_ir_truncate(icx, new_size); 18630a8ac0c1SNamjae Jeon else 18640a8ac0c1SNamjae Jeon ret = ntfs_icx_ib_write(icx); 18650a8ac0c1SNamjae Jeon if (ret) 18660a8ac0c1SNamjae Jeon goto out2; 18670a8ac0c1SNamjae Jeon 18680a8ac0c1SNamjae Jeon ntfs_ie_delete(&ib->index, ie_succ); 18690a8ac0c1SNamjae Jeon 18700a8ac0c1SNamjae Jeon if (ntfs_ih_zero_entry(&ib->index)) 18710a8ac0c1SNamjae Jeon ret = ntfs_index_rm_leaf(icx); 18720a8ac0c1SNamjae Jeon else 18730a8ac0c1SNamjae Jeon ret = ntfs_ib_write(icx, ib); 18740a8ac0c1SNamjae Jeon 18750a8ac0c1SNamjae Jeon out2: 18760a8ac0c1SNamjae Jeon kfree(ie); 18770a8ac0c1SNamjae Jeon out: 18780a8ac0c1SNamjae Jeon kvfree(ib); 18790a8ac0c1SNamjae Jeon return ret; 18800a8ac0c1SNamjae Jeon } 18810a8ac0c1SNamjae Jeon 18820a8ac0c1SNamjae Jeon /* 18830a8ac0c1SNamjae Jeon * ntfs_index_rm - remove entry from the index 18840a8ac0c1SNamjae Jeon * @icx: index context describing entry to delete 18850a8ac0c1SNamjae Jeon * 18860a8ac0c1SNamjae Jeon * Delete entry described by @icx from the index. Index context is always 18870a8ac0c1SNamjae Jeon * reinitialized after use of this function, so it can be used for index 18880a8ac0c1SNamjae Jeon * lookup once again. 18890a8ac0c1SNamjae Jeon */ 18900a8ac0c1SNamjae Jeon int ntfs_index_rm(struct ntfs_index_context *icx) 18910a8ac0c1SNamjae Jeon { 18920a8ac0c1SNamjae Jeon struct index_header *ih; 18930a8ac0c1SNamjae Jeon int ret = 0; 18940a8ac0c1SNamjae Jeon 18950a8ac0c1SNamjae Jeon ntfs_debug("Entering\n"); 18960a8ac0c1SNamjae Jeon 18970a8ac0c1SNamjae Jeon if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) { 18980a8ac0c1SNamjae Jeon ret = -EINVAL; 18990a8ac0c1SNamjae Jeon goto err_out; 19000a8ac0c1SNamjae Jeon } 19010a8ac0c1SNamjae Jeon if (icx->is_in_root) 19020a8ac0c1SNamjae Jeon ih = &icx->ir->index; 19030a8ac0c1SNamjae Jeon else 19040a8ac0c1SNamjae Jeon ih = &icx->ib->index; 19050a8ac0c1SNamjae Jeon 19060a8ac0c1SNamjae Jeon if (icx->entry->flags & INDEX_ENTRY_NODE) { 19070a8ac0c1SNamjae Jeon ret = ntfs_index_rm_node(icx); 19080a8ac0c1SNamjae Jeon if (ret) 19090a8ac0c1SNamjae Jeon goto err_out; 19100a8ac0c1SNamjae Jeon } else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) { 19110a8ac0c1SNamjae Jeon ntfs_ie_delete(ih, icx->entry); 19120a8ac0c1SNamjae Jeon 19130a8ac0c1SNamjae Jeon if (icx->is_in_root) 19140a8ac0c1SNamjae Jeon ret = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 19150a8ac0c1SNamjae Jeon else 19160a8ac0c1SNamjae Jeon ret = ntfs_icx_ib_write(icx); 19170a8ac0c1SNamjae Jeon if (ret) 19180a8ac0c1SNamjae Jeon goto err_out; 19190a8ac0c1SNamjae Jeon } else { 19200a8ac0c1SNamjae Jeon ret = ntfs_index_rm_leaf(icx); 19210a8ac0c1SNamjae Jeon if (ret) 19220a8ac0c1SNamjae Jeon goto err_out; 19230a8ac0c1SNamjae Jeon } 19240a8ac0c1SNamjae Jeon 19250a8ac0c1SNamjae Jeon return 0; 19260a8ac0c1SNamjae Jeon err_out: 19270a8ac0c1SNamjae Jeon return ret; 19280a8ac0c1SNamjae Jeon } 19290a8ac0c1SNamjae Jeon 19300a8ac0c1SNamjae Jeon int ntfs_index_remove(struct ntfs_inode *dir_ni, const void *key, const u32 keylen) 19310a8ac0c1SNamjae Jeon { 19320a8ac0c1SNamjae Jeon int ret = 0; 19330a8ac0c1SNamjae Jeon struct ntfs_index_context *icx; 19340a8ac0c1SNamjae Jeon 19350a8ac0c1SNamjae Jeon icx = ntfs_index_ctx_get(dir_ni, I30, 4); 19360a8ac0c1SNamjae Jeon if (!icx) 19370a8ac0c1SNamjae Jeon return -EINVAL; 19380a8ac0c1SNamjae Jeon 19390a8ac0c1SNamjae Jeon while (1) { 19400a8ac0c1SNamjae Jeon ret = ntfs_index_lookup(key, keylen, icx); 19410a8ac0c1SNamjae Jeon if (ret) 19420a8ac0c1SNamjae Jeon goto err_out; 19430a8ac0c1SNamjae Jeon 19440a8ac0c1SNamjae Jeon ret = ntfs_index_rm(icx); 19450a8ac0c1SNamjae Jeon if (ret && ret != -EAGAIN) 19460a8ac0c1SNamjae Jeon goto err_out; 19470a8ac0c1SNamjae Jeon else if (!ret) 19480a8ac0c1SNamjae Jeon break; 19490a8ac0c1SNamjae Jeon 19500a8ac0c1SNamjae Jeon mark_mft_record_dirty(icx->actx->ntfs_ino); 19510a8ac0c1SNamjae Jeon ntfs_index_ctx_reinit(icx); 19520a8ac0c1SNamjae Jeon } 19530a8ac0c1SNamjae Jeon 19540a8ac0c1SNamjae Jeon mark_mft_record_dirty(icx->actx->ntfs_ino); 19550a8ac0c1SNamjae Jeon 19560a8ac0c1SNamjae Jeon ntfs_index_ctx_put(icx); 19570a8ac0c1SNamjae Jeon return 0; 19580a8ac0c1SNamjae Jeon err_out: 19590a8ac0c1SNamjae Jeon ntfs_index_ctx_put(icx); 19600a8ac0c1SNamjae Jeon ntfs_error(dir_ni->vol->sb, "Delete failed"); 19610a8ac0c1SNamjae Jeon return ret; 19620a8ac0c1SNamjae Jeon } 19630a8ac0c1SNamjae Jeon 19640a8ac0c1SNamjae Jeon /* 19650a8ac0c1SNamjae Jeon * ntfs_index_walk_down - walk down the index tree (leaf bound) 19660a8ac0c1SNamjae Jeon * until there are no subnode in the first index entry returns 19670a8ac0c1SNamjae Jeon * the entry at the bottom left in subnode 19680a8ac0c1SNamjae Jeon */ 19690a8ac0c1SNamjae Jeon struct index_entry *ntfs_index_walk_down(struct index_entry *ie, struct ntfs_index_context *ictx) 19700a8ac0c1SNamjae Jeon { 19710a8ac0c1SNamjae Jeon struct index_entry *entry; 19720a8ac0c1SNamjae Jeon s64 vcn; 19730a8ac0c1SNamjae Jeon 19740a8ac0c1SNamjae Jeon entry = ie; 19750a8ac0c1SNamjae Jeon do { 19760a8ac0c1SNamjae Jeon vcn = ntfs_ie_get_vcn(entry); 19770a8ac0c1SNamjae Jeon if (ictx->is_in_root) { 19780a8ac0c1SNamjae Jeon /* down from level zero */ 19790a8ac0c1SNamjae Jeon ictx->ir = NULL; 19800a8ac0c1SNamjae Jeon ictx->ib = kvzalloc(ictx->block_size, GFP_NOFS); 19810a8ac0c1SNamjae Jeon ictx->pindex = 1; 19820a8ac0c1SNamjae Jeon ictx->is_in_root = false; 19830a8ac0c1SNamjae Jeon } else { 19840a8ac0c1SNamjae Jeon /* down from non-zero level */ 19850a8ac0c1SNamjae Jeon ictx->pindex++; 19860a8ac0c1SNamjae Jeon } 19870a8ac0c1SNamjae Jeon 19880a8ac0c1SNamjae Jeon ictx->parent_pos[ictx->pindex] = 0; 19890a8ac0c1SNamjae Jeon ictx->parent_vcn[ictx->pindex] = vcn; 19900a8ac0c1SNamjae Jeon if (!ntfs_ib_read(ictx, vcn, ictx->ib)) { 19910a8ac0c1SNamjae Jeon ictx->entry = ntfs_ie_get_first(&ictx->ib->index); 19920a8ac0c1SNamjae Jeon entry = ictx->entry; 19930a8ac0c1SNamjae Jeon } else 19940a8ac0c1SNamjae Jeon entry = NULL; 19950a8ac0c1SNamjae Jeon } while (entry && (entry->flags & INDEX_ENTRY_NODE)); 19960a8ac0c1SNamjae Jeon 19970a8ac0c1SNamjae Jeon return entry; 19980a8ac0c1SNamjae Jeon } 19990a8ac0c1SNamjae Jeon 20000a8ac0c1SNamjae Jeon /* 20010a8ac0c1SNamjae Jeon * ntfs_index_walk_up - walk up the index tree (root bound) until 20020a8ac0c1SNamjae Jeon * there is a valid data entry in parent returns the parent entry 20030a8ac0c1SNamjae Jeon * or NULL if no more parent. 20040a8ac0c1SNamjae Jeon * @ie: current index entry 20050a8ac0c1SNamjae Jeon * @ictx: index context 20060a8ac0c1SNamjae Jeon */ 20070a8ac0c1SNamjae Jeon static struct index_entry *ntfs_index_walk_up(struct index_entry *ie, 20080a8ac0c1SNamjae Jeon struct ntfs_index_context *ictx) 20090a8ac0c1SNamjae Jeon { 2010*068a35fdSHyunchul Lee struct index_entry *entry = ie; 20110a8ac0c1SNamjae Jeon s64 vcn; 20120a8ac0c1SNamjae Jeon 2013*068a35fdSHyunchul Lee if (ictx->pindex <= 0) 2014*068a35fdSHyunchul Lee return NULL; 2015*068a35fdSHyunchul Lee 20160a8ac0c1SNamjae Jeon do { 20170a8ac0c1SNamjae Jeon ictx->pindex--; 20180a8ac0c1SNamjae Jeon if (!ictx->pindex) { 20190a8ac0c1SNamjae Jeon /* we have reached the root */ 20200a8ac0c1SNamjae Jeon kfree(ictx->ib); 20210a8ac0c1SNamjae Jeon ictx->ib = NULL; 20220a8ac0c1SNamjae Jeon ictx->is_in_root = true; 20230a8ac0c1SNamjae Jeon /* a new search context is to be allocated */ 20240a8ac0c1SNamjae Jeon if (ictx->actx) 20250a8ac0c1SNamjae Jeon ntfs_attr_put_search_ctx(ictx->actx); 20260a8ac0c1SNamjae Jeon ictx->ir = ntfs_ir_lookup(ictx->idx_ni, ictx->name, 20270a8ac0c1SNamjae Jeon ictx->name_len, &ictx->actx); 20280a8ac0c1SNamjae Jeon if (ictx->ir) 2029*068a35fdSHyunchul Lee entry = ntfs_ie_get_by_pos( 2030*068a35fdSHyunchul Lee &ictx->ir->index, 20310a8ac0c1SNamjae Jeon ictx->parent_pos[ictx->pindex]); 20320a8ac0c1SNamjae Jeon else 20330a8ac0c1SNamjae Jeon entry = NULL; 20340a8ac0c1SNamjae Jeon } else { 20350a8ac0c1SNamjae Jeon /* up into non-root node */ 20360a8ac0c1SNamjae Jeon vcn = ictx->parent_vcn[ictx->pindex]; 20370a8ac0c1SNamjae Jeon if (!ntfs_ib_read(ictx, vcn, ictx->ib)) { 2038*068a35fdSHyunchul Lee entry = ntfs_ie_get_by_pos( 2039*068a35fdSHyunchul Lee &ictx->ib->index, 20400a8ac0c1SNamjae Jeon ictx->parent_pos[ictx->pindex]); 20410a8ac0c1SNamjae Jeon } else 20420a8ac0c1SNamjae Jeon entry = NULL; 20430a8ac0c1SNamjae Jeon } 20440a8ac0c1SNamjae Jeon ictx->entry = entry; 20450a8ac0c1SNamjae Jeon } while (entry && (ictx->pindex > 0) && 20460a8ac0c1SNamjae Jeon (entry->flags & INDEX_ENTRY_END)); 20470a8ac0c1SNamjae Jeon return entry; 20480a8ac0c1SNamjae Jeon } 20490a8ac0c1SNamjae Jeon 20500a8ac0c1SNamjae Jeon /* 20510a8ac0c1SNamjae Jeon * ntfs_index_next - get next entry in an index according to collating sequence. 20520a8ac0c1SNamjae Jeon * Returns next entry or NULL if none. 20530a8ac0c1SNamjae Jeon * 20540a8ac0c1SNamjae Jeon * Sample layout : 20550a8ac0c1SNamjae Jeon * 20560a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ n ptrs to subnodes 20570a8ac0c1SNamjae Jeon * | | | 10| 25| 33| | | | n-1 keys in between 20580a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ no key in last entry 20590a8ac0c1SNamjae Jeon * | A | A 20600a8ac0c1SNamjae Jeon * | | | +-------------------------------+ 20610a8ac0c1SNamjae Jeon * +--------------------------+ | +-----+ | 20620a8ac0c1SNamjae Jeon * | +--+ | | 20630a8ac0c1SNamjae Jeon * V | V | 20640a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ 20650a8ac0c1SNamjae Jeon * | 11| 12| 13| 14| 15| 16| 17| | | | 26| 27| 28| 29| 30| 31| 32| | 20660a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ 20670a8ac0c1SNamjae Jeon * | | 20680a8ac0c1SNamjae Jeon * +-----------------------+ | 20690a8ac0c1SNamjae Jeon * | | 20700a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ 20710a8ac0c1SNamjae Jeon * | 18| 19| 20| 21| 22| 23| 24| | 20720a8ac0c1SNamjae Jeon * +---+---+---+---+---+---+---+---+ 20730a8ac0c1SNamjae Jeon * 20740a8ac0c1SNamjae Jeon * @ie: current index entry 20750a8ac0c1SNamjae Jeon * @ictx: index context 20760a8ac0c1SNamjae Jeon */ 20770a8ac0c1SNamjae Jeon struct index_entry *ntfs_index_next(struct index_entry *ie, struct ntfs_index_context *ictx) 20780a8ac0c1SNamjae Jeon { 20790a8ac0c1SNamjae Jeon struct index_entry *next; 20800a8ac0c1SNamjae Jeon __le16 flags; 20810a8ac0c1SNamjae Jeon 20820a8ac0c1SNamjae Jeon /* 20830a8ac0c1SNamjae Jeon * lookup() may have returned an invalid node 20840a8ac0c1SNamjae Jeon * when searching for a partial key 20850a8ac0c1SNamjae Jeon * if this happens, walk up 20860a8ac0c1SNamjae Jeon */ 20870a8ac0c1SNamjae Jeon if (ie->flags & INDEX_ENTRY_END) 20880a8ac0c1SNamjae Jeon next = ntfs_index_walk_up(ie, ictx); 20890a8ac0c1SNamjae Jeon else { 20900a8ac0c1SNamjae Jeon /* 20910a8ac0c1SNamjae Jeon * get next entry in same node 20920a8ac0c1SNamjae Jeon * there is always one after any entry with data 20930a8ac0c1SNamjae Jeon */ 20940a8ac0c1SNamjae Jeon next = (struct index_entry *)((char *)ie + le16_to_cpu(ie->length)); 20950a8ac0c1SNamjae Jeon ++ictx->parent_pos[ictx->pindex]; 20960a8ac0c1SNamjae Jeon flags = next->flags; 20970a8ac0c1SNamjae Jeon 20980a8ac0c1SNamjae Jeon /* walk down if it has a subnode */ 20990a8ac0c1SNamjae Jeon if (flags & INDEX_ENTRY_NODE) { 21000a8ac0c1SNamjae Jeon if (!ictx->ia_ni) 21010a8ac0c1SNamjae Jeon ictx->ia_ni = ntfs_ia_open(ictx, ictx->idx_ni); 21020a8ac0c1SNamjae Jeon 21030a8ac0c1SNamjae Jeon next = ntfs_index_walk_down(next, ictx); 21040a8ac0c1SNamjae Jeon } else { 21050a8ac0c1SNamjae Jeon 21060a8ac0c1SNamjae Jeon /* walk up it has no subnode, nor data */ 21070a8ac0c1SNamjae Jeon if (flags & INDEX_ENTRY_END) 21080a8ac0c1SNamjae Jeon next = ntfs_index_walk_up(next, ictx); 21090a8ac0c1SNamjae Jeon } 21100a8ac0c1SNamjae Jeon } 21110a8ac0c1SNamjae Jeon 21120a8ac0c1SNamjae Jeon /* return NULL if stuck at end of a block */ 21130a8ac0c1SNamjae Jeon if (next && (next->flags & INDEX_ENTRY_END)) 21140a8ac0c1SNamjae Jeon next = NULL; 21150a8ac0c1SNamjae Jeon 21160a8ac0c1SNamjae Jeon return next; 21170a8ac0c1SNamjae Jeon } 2118