162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/blkdev.h> 962306a36Sopenharmony_ci#include <linux/buffer_head.h> 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "debug.h" 1462306a36Sopenharmony_ci#include "ntfs.h" 1562306a36Sopenharmony_ci#include "ntfs_fs.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic const struct INDEX_NAMES { 1862306a36Sopenharmony_ci const __le16 *name; 1962306a36Sopenharmony_ci u8 name_len; 2062306a36Sopenharmony_ci} s_index_names[INDEX_MUTEX_TOTAL] = { 2162306a36Sopenharmony_ci { I30_NAME, ARRAY_SIZE(I30_NAME) }, { SII_NAME, ARRAY_SIZE(SII_NAME) }, 2262306a36Sopenharmony_ci { SDH_NAME, ARRAY_SIZE(SDH_NAME) }, { SO_NAME, ARRAY_SIZE(SO_NAME) }, 2362306a36Sopenharmony_ci { SQ_NAME, ARRAY_SIZE(SQ_NAME) }, { SR_NAME, ARRAY_SIZE(SR_NAME) }, 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * cmp_fnames - Compare two names in index. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * if l1 != 0 3062306a36Sopenharmony_ci * Both names are little endian on-disk ATTR_FILE_NAME structs. 3162306a36Sopenharmony_ci * else 3262306a36Sopenharmony_ci * key1 - cpu_str, key2 - ATTR_FILE_NAME 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistatic int cmp_fnames(const void *key1, size_t l1, const void *key2, size_t l2, 3562306a36Sopenharmony_ci const void *data) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci const struct ATTR_FILE_NAME *f2 = key2; 3862306a36Sopenharmony_ci const struct ntfs_sb_info *sbi = data; 3962306a36Sopenharmony_ci const struct ATTR_FILE_NAME *f1; 4062306a36Sopenharmony_ci u16 fsize2; 4162306a36Sopenharmony_ci bool both_case; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (l2 <= offsetof(struct ATTR_FILE_NAME, name)) 4462306a36Sopenharmony_ci return -1; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci fsize2 = fname_full_size(f2); 4762306a36Sopenharmony_ci if (l2 < fsize2) 4862306a36Sopenharmony_ci return -1; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci both_case = f2->type != FILE_NAME_DOS && !sbi->options->nocase; 5162306a36Sopenharmony_ci if (!l1) { 5262306a36Sopenharmony_ci const struct le_str *s2 = (struct le_str *)&f2->name_len; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* 5562306a36Sopenharmony_ci * If names are equal (case insensitive) 5662306a36Sopenharmony_ci * try to compare it case sensitive. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci return ntfs_cmp_names_cpu(key1, s2, sbi->upcase, both_case); 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci f1 = key1; 6262306a36Sopenharmony_ci return ntfs_cmp_names(f1->name, f1->name_len, f2->name, f2->name_len, 6362306a36Sopenharmony_ci sbi->upcase, both_case); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * cmp_uint - $SII of $Secure and $Q of Quota 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistatic int cmp_uint(const void *key1, size_t l1, const void *key2, size_t l2, 7062306a36Sopenharmony_ci const void *data) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci const u32 *k1 = key1; 7362306a36Sopenharmony_ci const u32 *k2 = key2; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (l2 < sizeof(u32)) 7662306a36Sopenharmony_ci return -1; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (*k1 < *k2) 7962306a36Sopenharmony_ci return -1; 8062306a36Sopenharmony_ci if (*k1 > *k2) 8162306a36Sopenharmony_ci return 1; 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * cmp_sdh - $SDH of $Secure 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cistatic int cmp_sdh(const void *key1, size_t l1, const void *key2, size_t l2, 8962306a36Sopenharmony_ci const void *data) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci const struct SECURITY_KEY *k1 = key1; 9262306a36Sopenharmony_ci const struct SECURITY_KEY *k2 = key2; 9362306a36Sopenharmony_ci u32 t1, t2; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (l2 < sizeof(struct SECURITY_KEY)) 9662306a36Sopenharmony_ci return -1; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci t1 = le32_to_cpu(k1->hash); 9962306a36Sopenharmony_ci t2 = le32_to_cpu(k2->hash); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* First value is a hash value itself. */ 10262306a36Sopenharmony_ci if (t1 < t2) 10362306a36Sopenharmony_ci return -1; 10462306a36Sopenharmony_ci if (t1 > t2) 10562306a36Sopenharmony_ci return 1; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* Second value is security Id. */ 10862306a36Sopenharmony_ci if (data) { 10962306a36Sopenharmony_ci t1 = le32_to_cpu(k1->sec_id); 11062306a36Sopenharmony_ci t2 = le32_to_cpu(k2->sec_id); 11162306a36Sopenharmony_ci if (t1 < t2) 11262306a36Sopenharmony_ci return -1; 11362306a36Sopenharmony_ci if (t1 > t2) 11462306a36Sopenharmony_ci return 1; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return 0; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * cmp_uints - $O of ObjId and "$R" for Reparse. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_cistatic int cmp_uints(const void *key1, size_t l1, const void *key2, size_t l2, 12462306a36Sopenharmony_ci const void *data) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci const __le32 *k1 = key1; 12762306a36Sopenharmony_ci const __le32 *k2 = key2; 12862306a36Sopenharmony_ci size_t count; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if ((size_t)data == 1) { 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * ni_delete_all -> ntfs_remove_reparse -> 13362306a36Sopenharmony_ci * delete all with this reference. 13462306a36Sopenharmony_ci * k1, k2 - pointers to REPARSE_KEY 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci k1 += 1; // Skip REPARSE_KEY.ReparseTag 13862306a36Sopenharmony_ci k2 += 1; // Skip REPARSE_KEY.ReparseTag 13962306a36Sopenharmony_ci if (l2 <= sizeof(int)) 14062306a36Sopenharmony_ci return -1; 14162306a36Sopenharmony_ci l2 -= sizeof(int); 14262306a36Sopenharmony_ci if (l1 <= sizeof(int)) 14362306a36Sopenharmony_ci return 1; 14462306a36Sopenharmony_ci l1 -= sizeof(int); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (l2 < sizeof(int)) 14862306a36Sopenharmony_ci return -1; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci for (count = min(l1, l2) >> 2; count > 0; --count, ++k1, ++k2) { 15162306a36Sopenharmony_ci u32 t1 = le32_to_cpu(*k1); 15262306a36Sopenharmony_ci u32 t2 = le32_to_cpu(*k2); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (t1 > t2) 15562306a36Sopenharmony_ci return 1; 15662306a36Sopenharmony_ci if (t1 < t2) 15762306a36Sopenharmony_ci return -1; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (l1 > l2) 16162306a36Sopenharmony_ci return 1; 16262306a36Sopenharmony_ci if (l1 < l2) 16362306a36Sopenharmony_ci return -1; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic inline NTFS_CMP_FUNC get_cmp_func(const struct INDEX_ROOT *root) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci switch (root->type) { 17162306a36Sopenharmony_ci case ATTR_NAME: 17262306a36Sopenharmony_ci if (root->rule == NTFS_COLLATION_TYPE_FILENAME) 17362306a36Sopenharmony_ci return &cmp_fnames; 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci case ATTR_ZERO: 17662306a36Sopenharmony_ci switch (root->rule) { 17762306a36Sopenharmony_ci case NTFS_COLLATION_TYPE_UINT: 17862306a36Sopenharmony_ci return &cmp_uint; 17962306a36Sopenharmony_ci case NTFS_COLLATION_TYPE_SECURITY_HASH: 18062306a36Sopenharmony_ci return &cmp_sdh; 18162306a36Sopenharmony_ci case NTFS_COLLATION_TYPE_UINTS: 18262306a36Sopenharmony_ci return &cmp_uints; 18362306a36Sopenharmony_ci default: 18462306a36Sopenharmony_ci break; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci default: 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return NULL; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistruct bmp_buf { 19562306a36Sopenharmony_ci struct ATTRIB *b; 19662306a36Sopenharmony_ci struct mft_inode *mi; 19762306a36Sopenharmony_ci struct buffer_head *bh; 19862306a36Sopenharmony_ci ulong *buf; 19962306a36Sopenharmony_ci size_t bit; 20062306a36Sopenharmony_ci u32 nbits; 20162306a36Sopenharmony_ci u64 new_valid; 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic int bmp_buf_get(struct ntfs_index *indx, struct ntfs_inode *ni, 20562306a36Sopenharmony_ci size_t bit, struct bmp_buf *bbuf) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct ATTRIB *b; 20862306a36Sopenharmony_ci size_t data_size, valid_size, vbo, off = bit >> 3; 20962306a36Sopenharmony_ci struct ntfs_sb_info *sbi = ni->mi.sbi; 21062306a36Sopenharmony_ci CLST vcn = off >> sbi->cluster_bits; 21162306a36Sopenharmony_ci struct ATTR_LIST_ENTRY *le = NULL; 21262306a36Sopenharmony_ci struct buffer_head *bh; 21362306a36Sopenharmony_ci struct super_block *sb; 21462306a36Sopenharmony_ci u32 blocksize; 21562306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci bbuf->bh = NULL; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len, 22062306a36Sopenharmony_ci &vcn, &bbuf->mi); 22162306a36Sopenharmony_ci bbuf->b = b; 22262306a36Sopenharmony_ci if (!b) 22362306a36Sopenharmony_ci return -EINVAL; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (!b->non_res) { 22662306a36Sopenharmony_ci data_size = le32_to_cpu(b->res.data_size); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (off >= data_size) 22962306a36Sopenharmony_ci return -EINVAL; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci bbuf->buf = (ulong *)resident_data(b); 23262306a36Sopenharmony_ci bbuf->bit = 0; 23362306a36Sopenharmony_ci bbuf->nbits = data_size * 8; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return 0; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci data_size = le64_to_cpu(b->nres.data_size); 23962306a36Sopenharmony_ci if (WARN_ON(off >= data_size)) { 24062306a36Sopenharmony_ci /* Looks like filesystem error. */ 24162306a36Sopenharmony_ci return -EINVAL; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci valid_size = le64_to_cpu(b->nres.valid_size); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci bh = ntfs_bread_run(sbi, &indx->bitmap_run, off); 24762306a36Sopenharmony_ci if (!bh) 24862306a36Sopenharmony_ci return -EIO; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (IS_ERR(bh)) 25162306a36Sopenharmony_ci return PTR_ERR(bh); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci bbuf->bh = bh; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (buffer_locked(bh)) 25662306a36Sopenharmony_ci __wait_on_buffer(bh); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci lock_buffer(bh); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci sb = sbi->sb; 26162306a36Sopenharmony_ci blocksize = sb->s_blocksize; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci vbo = off & ~(size_t)sbi->block_mask; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci bbuf->new_valid = vbo + blocksize; 26662306a36Sopenharmony_ci if (bbuf->new_valid <= valid_size) 26762306a36Sopenharmony_ci bbuf->new_valid = 0; 26862306a36Sopenharmony_ci else if (bbuf->new_valid > data_size) 26962306a36Sopenharmony_ci bbuf->new_valid = data_size; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (vbo >= valid_size) { 27262306a36Sopenharmony_ci memset(bh->b_data, 0, blocksize); 27362306a36Sopenharmony_ci } else if (vbo + blocksize > valid_size) { 27462306a36Sopenharmony_ci u32 voff = valid_size & sbi->block_mask; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci memset(bh->b_data + voff, 0, blocksize - voff); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci bbuf->buf = (ulong *)bh->b_data; 28062306a36Sopenharmony_ci bbuf->bit = 8 * (off & ~(size_t)sbi->block_mask); 28162306a36Sopenharmony_ci bbuf->nbits = 8 * blocksize; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return 0; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic void bmp_buf_put(struct bmp_buf *bbuf, bool dirty) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct buffer_head *bh = bbuf->bh; 28962306a36Sopenharmony_ci struct ATTRIB *b = bbuf->b; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (!bh) { 29262306a36Sopenharmony_ci if (b && !b->non_res && dirty) 29362306a36Sopenharmony_ci bbuf->mi->dirty = true; 29462306a36Sopenharmony_ci return; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (!dirty) 29862306a36Sopenharmony_ci goto out; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (bbuf->new_valid) { 30162306a36Sopenharmony_ci b->nres.valid_size = cpu_to_le64(bbuf->new_valid); 30262306a36Sopenharmony_ci bbuf->mi->dirty = true; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci set_buffer_uptodate(bh); 30662306a36Sopenharmony_ci mark_buffer_dirty(bh); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ciout: 30962306a36Sopenharmony_ci unlock_buffer(bh); 31062306a36Sopenharmony_ci put_bh(bh); 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* 31462306a36Sopenharmony_ci * indx_mark_used - Mark the bit @bit as used. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_cistatic int indx_mark_used(struct ntfs_index *indx, struct ntfs_inode *ni, 31762306a36Sopenharmony_ci size_t bit) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci int err; 32062306a36Sopenharmony_ci struct bmp_buf bbuf; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci err = bmp_buf_get(indx, ni, bit, &bbuf); 32362306a36Sopenharmony_ci if (err) 32462306a36Sopenharmony_ci return err; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci __set_bit_le(bit - bbuf.bit, bbuf.buf); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci bmp_buf_put(&bbuf, true); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/* 33462306a36Sopenharmony_ci * indx_mark_free - Mark the bit @bit as free. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_cistatic int indx_mark_free(struct ntfs_index *indx, struct ntfs_inode *ni, 33762306a36Sopenharmony_ci size_t bit) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci int err; 34062306a36Sopenharmony_ci struct bmp_buf bbuf; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci err = bmp_buf_get(indx, ni, bit, &bbuf); 34362306a36Sopenharmony_ci if (err) 34462306a36Sopenharmony_ci return err; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci __clear_bit_le(bit - bbuf.bit, bbuf.buf); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci bmp_buf_put(&bbuf, true); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return 0; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/* 35462306a36Sopenharmony_ci * scan_nres_bitmap 35562306a36Sopenharmony_ci * 35662306a36Sopenharmony_ci * If ntfs_readdir calls this function (indx_used_bit -> scan_nres_bitmap), 35762306a36Sopenharmony_ci * inode is shared locked and no ni_lock. 35862306a36Sopenharmony_ci * Use rw_semaphore for read/write access to bitmap_run. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_cistatic int scan_nres_bitmap(struct ntfs_inode *ni, struct ATTRIB *bitmap, 36162306a36Sopenharmony_ci struct ntfs_index *indx, size_t from, 36262306a36Sopenharmony_ci bool (*fn)(const ulong *buf, u32 bit, u32 bits, 36362306a36Sopenharmony_ci size_t *ret), 36462306a36Sopenharmony_ci size_t *ret) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct ntfs_sb_info *sbi = ni->mi.sbi; 36762306a36Sopenharmony_ci struct super_block *sb = sbi->sb; 36862306a36Sopenharmony_ci struct runs_tree *run = &indx->bitmap_run; 36962306a36Sopenharmony_ci struct rw_semaphore *lock = &indx->run_lock; 37062306a36Sopenharmony_ci u32 nbits = sb->s_blocksize * 8; 37162306a36Sopenharmony_ci u32 blocksize = sb->s_blocksize; 37262306a36Sopenharmony_ci u64 valid_size = le64_to_cpu(bitmap->nres.valid_size); 37362306a36Sopenharmony_ci u64 data_size = le64_to_cpu(bitmap->nres.data_size); 37462306a36Sopenharmony_ci sector_t eblock = bytes_to_block(sb, data_size); 37562306a36Sopenharmony_ci size_t vbo = from >> 3; 37662306a36Sopenharmony_ci sector_t blk = (vbo & sbi->cluster_mask) >> sb->s_blocksize_bits; 37762306a36Sopenharmony_ci sector_t vblock = vbo >> sb->s_blocksize_bits; 37862306a36Sopenharmony_ci sector_t blen, block; 37962306a36Sopenharmony_ci CLST lcn, clen, vcn, vcn_next; 38062306a36Sopenharmony_ci size_t idx; 38162306a36Sopenharmony_ci struct buffer_head *bh; 38262306a36Sopenharmony_ci bool ok; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci *ret = MINUS_ONE_T; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (vblock >= eblock) 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci from &= nbits - 1; 39062306a36Sopenharmony_ci vcn = vbo >> sbi->cluster_bits; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci down_read(lock); 39362306a36Sopenharmony_ci ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx); 39462306a36Sopenharmony_ci up_read(lock); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cinext_run: 39762306a36Sopenharmony_ci if (!ok) { 39862306a36Sopenharmony_ci int err; 39962306a36Sopenharmony_ci const struct INDEX_NAMES *name = &s_index_names[indx->type]; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci down_write(lock); 40262306a36Sopenharmony_ci err = attr_load_runs_vcn(ni, ATTR_BITMAP, name->name, 40362306a36Sopenharmony_ci name->name_len, run, vcn); 40462306a36Sopenharmony_ci up_write(lock); 40562306a36Sopenharmony_ci if (err) 40662306a36Sopenharmony_ci return err; 40762306a36Sopenharmony_ci down_read(lock); 40862306a36Sopenharmony_ci ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx); 40962306a36Sopenharmony_ci up_read(lock); 41062306a36Sopenharmony_ci if (!ok) 41162306a36Sopenharmony_ci return -EINVAL; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci blen = (sector_t)clen * sbi->blocks_per_cluster; 41562306a36Sopenharmony_ci block = (sector_t)lcn * sbi->blocks_per_cluster; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci for (; blk < blen; blk++, from = 0) { 41862306a36Sopenharmony_ci bh = ntfs_bread(sb, block + blk); 41962306a36Sopenharmony_ci if (!bh) 42062306a36Sopenharmony_ci return -EIO; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci vbo = (u64)vblock << sb->s_blocksize_bits; 42362306a36Sopenharmony_ci if (vbo >= valid_size) { 42462306a36Sopenharmony_ci memset(bh->b_data, 0, blocksize); 42562306a36Sopenharmony_ci } else if (vbo + blocksize > valid_size) { 42662306a36Sopenharmony_ci u32 voff = valid_size & sbi->block_mask; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci memset(bh->b_data + voff, 0, blocksize - voff); 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (vbo + blocksize > data_size) 43262306a36Sopenharmony_ci nbits = 8 * (data_size - vbo); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ok = nbits > from ? 43562306a36Sopenharmony_ci (*fn)((ulong *)bh->b_data, from, nbits, ret) : 43662306a36Sopenharmony_ci false; 43762306a36Sopenharmony_ci put_bh(bh); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (ok) { 44062306a36Sopenharmony_ci *ret += 8 * vbo; 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (++vblock >= eblock) { 44562306a36Sopenharmony_ci *ret = MINUS_ONE_T; 44662306a36Sopenharmony_ci return 0; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci blk = 0; 45062306a36Sopenharmony_ci vcn_next = vcn + clen; 45162306a36Sopenharmony_ci down_read(lock); 45262306a36Sopenharmony_ci ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) && vcn == vcn_next; 45362306a36Sopenharmony_ci if (!ok) 45462306a36Sopenharmony_ci vcn = vcn_next; 45562306a36Sopenharmony_ci up_read(lock); 45662306a36Sopenharmony_ci goto next_run; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic bool scan_for_free(const ulong *buf, u32 bit, u32 bits, size_t *ret) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci size_t pos = find_next_zero_bit_le(buf, bits, bit); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (pos >= bits) 46462306a36Sopenharmony_ci return false; 46562306a36Sopenharmony_ci *ret = pos; 46662306a36Sopenharmony_ci return true; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* 47062306a36Sopenharmony_ci * indx_find_free - Look for free bit. 47162306a36Sopenharmony_ci * 47262306a36Sopenharmony_ci * Return: -1 if no free bits. 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_cistatic int indx_find_free(struct ntfs_index *indx, struct ntfs_inode *ni, 47562306a36Sopenharmony_ci size_t *bit, struct ATTRIB **bitmap) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci struct ATTRIB *b; 47862306a36Sopenharmony_ci struct ATTR_LIST_ENTRY *le = NULL; 47962306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 48062306a36Sopenharmony_ci int err; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len, 48362306a36Sopenharmony_ci NULL, NULL); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci if (!b) 48662306a36Sopenharmony_ci return -ENOENT; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci *bitmap = b; 48962306a36Sopenharmony_ci *bit = MINUS_ONE_T; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci if (!b->non_res) { 49262306a36Sopenharmony_ci u32 nbits = 8 * le32_to_cpu(b->res.data_size); 49362306a36Sopenharmony_ci size_t pos = find_next_zero_bit_le(resident_data(b), nbits, 0); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (pos < nbits) 49662306a36Sopenharmony_ci *bit = pos; 49762306a36Sopenharmony_ci } else { 49862306a36Sopenharmony_ci err = scan_nres_bitmap(ni, b, indx, 0, &scan_for_free, bit); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (err) 50162306a36Sopenharmony_ci return err; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return 0; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic bool scan_for_used(const ulong *buf, u32 bit, u32 bits, size_t *ret) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci size_t pos = find_next_bit_le(buf, bits, bit); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (pos >= bits) 51262306a36Sopenharmony_ci return false; 51362306a36Sopenharmony_ci *ret = pos; 51462306a36Sopenharmony_ci return true; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci/* 51862306a36Sopenharmony_ci * indx_used_bit - Look for used bit. 51962306a36Sopenharmony_ci * 52062306a36Sopenharmony_ci * Return: MINUS_ONE_T if no used bits. 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ciint indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni, size_t *bit) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct ATTRIB *b; 52562306a36Sopenharmony_ci struct ATTR_LIST_ENTRY *le = NULL; 52662306a36Sopenharmony_ci size_t from = *bit; 52762306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 52862306a36Sopenharmony_ci int err; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len, 53162306a36Sopenharmony_ci NULL, NULL); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (!b) 53462306a36Sopenharmony_ci return -ENOENT; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci *bit = MINUS_ONE_T; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (!b->non_res) { 53962306a36Sopenharmony_ci u32 nbits = le32_to_cpu(b->res.data_size) * 8; 54062306a36Sopenharmony_ci size_t pos = find_next_bit_le(resident_data(b), nbits, from); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (pos < nbits) 54362306a36Sopenharmony_ci *bit = pos; 54462306a36Sopenharmony_ci } else { 54562306a36Sopenharmony_ci err = scan_nres_bitmap(ni, b, indx, from, &scan_for_used, bit); 54662306a36Sopenharmony_ci if (err) 54762306a36Sopenharmony_ci return err; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci return 0; 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci/* 55462306a36Sopenharmony_ci * hdr_find_split 55562306a36Sopenharmony_ci * 55662306a36Sopenharmony_ci * Find a point at which the index allocation buffer would like to be split. 55762306a36Sopenharmony_ci * NOTE: This function should never return 'END' entry NULL returns on error. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_cistatic const struct NTFS_DE *hdr_find_split(const struct INDEX_HDR *hdr) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci size_t o; 56262306a36Sopenharmony_ci const struct NTFS_DE *e = hdr_first_de(hdr); 56362306a36Sopenharmony_ci u32 used_2 = le32_to_cpu(hdr->used) >> 1; 56462306a36Sopenharmony_ci u16 esize; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!e || de_is_last(e)) 56762306a36Sopenharmony_ci return NULL; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci esize = le16_to_cpu(e->size); 57062306a36Sopenharmony_ci for (o = le32_to_cpu(hdr->de_off) + esize; o < used_2; o += esize) { 57162306a36Sopenharmony_ci const struct NTFS_DE *p = e; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci e = Add2Ptr(hdr, o); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* We must not return END entry. */ 57662306a36Sopenharmony_ci if (de_is_last(e)) 57762306a36Sopenharmony_ci return p; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci esize = le16_to_cpu(e->size); 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci return e; 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci/* 58662306a36Sopenharmony_ci * hdr_insert_head - Insert some entries at the beginning of the buffer. 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * It is used to insert entries into a newly-created buffer. 58962306a36Sopenharmony_ci */ 59062306a36Sopenharmony_cistatic const struct NTFS_DE *hdr_insert_head(struct INDEX_HDR *hdr, 59162306a36Sopenharmony_ci const void *ins, u32 ins_bytes) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci u32 to_move; 59462306a36Sopenharmony_ci struct NTFS_DE *e = hdr_first_de(hdr); 59562306a36Sopenharmony_ci u32 used = le32_to_cpu(hdr->used); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci if (!e) 59862306a36Sopenharmony_ci return NULL; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* Now we just make room for the inserted entries and jam it in. */ 60162306a36Sopenharmony_ci to_move = used - le32_to_cpu(hdr->de_off); 60262306a36Sopenharmony_ci memmove(Add2Ptr(e, ins_bytes), e, to_move); 60362306a36Sopenharmony_ci memcpy(e, ins, ins_bytes); 60462306a36Sopenharmony_ci hdr->used = cpu_to_le32(used + ins_bytes); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci return e; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci/* 61062306a36Sopenharmony_ci * index_hdr_check 61162306a36Sopenharmony_ci * 61262306a36Sopenharmony_ci * return true if INDEX_HDR is valid 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_cistatic bool index_hdr_check(const struct INDEX_HDR *hdr, u32 bytes) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci u32 end = le32_to_cpu(hdr->used); 61762306a36Sopenharmony_ci u32 tot = le32_to_cpu(hdr->total); 61862306a36Sopenharmony_ci u32 off = le32_to_cpu(hdr->de_off); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci if (!IS_ALIGNED(off, 8) || tot > bytes || end > tot || 62162306a36Sopenharmony_ci off + sizeof(struct NTFS_DE) > end) { 62262306a36Sopenharmony_ci /* incorrect index buffer. */ 62362306a36Sopenharmony_ci return false; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return true; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci/* 63062306a36Sopenharmony_ci * index_buf_check 63162306a36Sopenharmony_ci * 63262306a36Sopenharmony_ci * return true if INDEX_BUFFER seems is valid 63362306a36Sopenharmony_ci */ 63462306a36Sopenharmony_cistatic bool index_buf_check(const struct INDEX_BUFFER *ib, u32 bytes, 63562306a36Sopenharmony_ci const CLST *vbn) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci const struct NTFS_RECORD_HEADER *rhdr = &ib->rhdr; 63862306a36Sopenharmony_ci u16 fo = le16_to_cpu(rhdr->fix_off); 63962306a36Sopenharmony_ci u16 fn = le16_to_cpu(rhdr->fix_num); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci if (bytes <= offsetof(struct INDEX_BUFFER, ihdr) || 64262306a36Sopenharmony_ci rhdr->sign != NTFS_INDX_SIGNATURE || 64362306a36Sopenharmony_ci fo < sizeof(struct INDEX_BUFFER) 64462306a36Sopenharmony_ci /* Check index buffer vbn. */ 64562306a36Sopenharmony_ci || (vbn && *vbn != le64_to_cpu(ib->vbn)) || (fo % sizeof(short)) || 64662306a36Sopenharmony_ci fo + fn * sizeof(short) >= bytes || 64762306a36Sopenharmony_ci fn != ((bytes >> SECTOR_SHIFT) + 1)) { 64862306a36Sopenharmony_ci /* incorrect index buffer. */ 64962306a36Sopenharmony_ci return false; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci return index_hdr_check(&ib->ihdr, 65362306a36Sopenharmony_ci bytes - offsetof(struct INDEX_BUFFER, ihdr)); 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_civoid fnd_clear(struct ntfs_fnd *fnd) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci int i; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci for (i = fnd->level - 1; i >= 0; i--) { 66162306a36Sopenharmony_ci struct indx_node *n = fnd->nodes[i]; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (!n) 66462306a36Sopenharmony_ci continue; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci put_indx_node(n); 66762306a36Sopenharmony_ci fnd->nodes[i] = NULL; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci fnd->level = 0; 67062306a36Sopenharmony_ci fnd->root_de = NULL; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic int fnd_push(struct ntfs_fnd *fnd, struct indx_node *n, 67462306a36Sopenharmony_ci struct NTFS_DE *e) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci int i = fnd->level; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci if (i < 0 || i >= ARRAY_SIZE(fnd->nodes)) 67962306a36Sopenharmony_ci return -EINVAL; 68062306a36Sopenharmony_ci fnd->nodes[i] = n; 68162306a36Sopenharmony_ci fnd->de[i] = e; 68262306a36Sopenharmony_ci fnd->level += 1; 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic struct indx_node *fnd_pop(struct ntfs_fnd *fnd) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct indx_node *n; 68962306a36Sopenharmony_ci int i = fnd->level; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci i -= 1; 69262306a36Sopenharmony_ci n = fnd->nodes[i]; 69362306a36Sopenharmony_ci fnd->nodes[i] = NULL; 69462306a36Sopenharmony_ci fnd->level = i; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci return n; 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistatic bool fnd_is_empty(struct ntfs_fnd *fnd) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci if (!fnd->level) 70262306a36Sopenharmony_ci return !fnd->root_de; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci return !fnd->de[fnd->level - 1]; 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci/* 70862306a36Sopenharmony_ci * hdr_find_e - Locate an entry the index buffer. 70962306a36Sopenharmony_ci * 71062306a36Sopenharmony_ci * If no matching entry is found, it returns the first entry which is greater 71162306a36Sopenharmony_ci * than the desired entry If the search key is greater than all the entries the 71262306a36Sopenharmony_ci * buffer, it returns the 'end' entry. This function does a binary search of the 71362306a36Sopenharmony_ci * current index buffer, for the first entry that is <= to the search value. 71462306a36Sopenharmony_ci * 71562306a36Sopenharmony_ci * Return: NULL if error. 71662306a36Sopenharmony_ci */ 71762306a36Sopenharmony_cistatic struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, 71862306a36Sopenharmony_ci const struct INDEX_HDR *hdr, const void *key, 71962306a36Sopenharmony_ci size_t key_len, const void *ctx, int *diff) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct NTFS_DE *e, *found = NULL; 72262306a36Sopenharmony_ci NTFS_CMP_FUNC cmp = indx->cmp; 72362306a36Sopenharmony_ci int min_idx = 0, mid_idx, max_idx = 0; 72462306a36Sopenharmony_ci int diff2; 72562306a36Sopenharmony_ci int table_size = 8; 72662306a36Sopenharmony_ci u32 e_size, e_key_len; 72762306a36Sopenharmony_ci u32 end = le32_to_cpu(hdr->used); 72862306a36Sopenharmony_ci u32 off = le32_to_cpu(hdr->de_off); 72962306a36Sopenharmony_ci u32 total = le32_to_cpu(hdr->total); 73062306a36Sopenharmony_ci u16 offs[128]; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (unlikely(!cmp)) 73362306a36Sopenharmony_ci return NULL; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_cifill_table: 73662306a36Sopenharmony_ci if (end > total) 73762306a36Sopenharmony_ci return NULL; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (off + sizeof(struct NTFS_DE) > end) 74062306a36Sopenharmony_ci return NULL; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci e = Add2Ptr(hdr, off); 74362306a36Sopenharmony_ci e_size = le16_to_cpu(e->size); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) 74662306a36Sopenharmony_ci return NULL; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (!de_is_last(e)) { 74962306a36Sopenharmony_ci offs[max_idx] = off; 75062306a36Sopenharmony_ci off += e_size; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci max_idx++; 75362306a36Sopenharmony_ci if (max_idx < table_size) 75462306a36Sopenharmony_ci goto fill_table; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci max_idx--; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_cibinary_search: 76062306a36Sopenharmony_ci e_key_len = le16_to_cpu(e->key_size); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx); 76362306a36Sopenharmony_ci if (diff2 > 0) { 76462306a36Sopenharmony_ci if (found) { 76562306a36Sopenharmony_ci min_idx = mid_idx + 1; 76662306a36Sopenharmony_ci } else { 76762306a36Sopenharmony_ci if (de_is_last(e)) 76862306a36Sopenharmony_ci return NULL; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci max_idx = 0; 77162306a36Sopenharmony_ci table_size = min(table_size * 2, (int)ARRAY_SIZE(offs)); 77262306a36Sopenharmony_ci goto fill_table; 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci } else if (diff2 < 0) { 77562306a36Sopenharmony_ci if (found) 77662306a36Sopenharmony_ci max_idx = mid_idx - 1; 77762306a36Sopenharmony_ci else 77862306a36Sopenharmony_ci max_idx--; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci found = e; 78162306a36Sopenharmony_ci } else { 78262306a36Sopenharmony_ci *diff = 0; 78362306a36Sopenharmony_ci return e; 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (min_idx > max_idx) { 78762306a36Sopenharmony_ci *diff = -1; 78862306a36Sopenharmony_ci return found; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci mid_idx = (min_idx + max_idx) >> 1; 79262306a36Sopenharmony_ci e = Add2Ptr(hdr, offs[mid_idx]); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci goto binary_search; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci/* 79862306a36Sopenharmony_ci * hdr_insert_de - Insert an index entry into the buffer. 79962306a36Sopenharmony_ci * 80062306a36Sopenharmony_ci * 'before' should be a pointer previously returned from hdr_find_e. 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_cistatic struct NTFS_DE *hdr_insert_de(const struct ntfs_index *indx, 80362306a36Sopenharmony_ci struct INDEX_HDR *hdr, 80462306a36Sopenharmony_ci const struct NTFS_DE *de, 80562306a36Sopenharmony_ci struct NTFS_DE *before, const void *ctx) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci int diff; 80862306a36Sopenharmony_ci size_t off = PtrOffset(hdr, before); 80962306a36Sopenharmony_ci u32 used = le32_to_cpu(hdr->used); 81062306a36Sopenharmony_ci u32 total = le32_to_cpu(hdr->total); 81162306a36Sopenharmony_ci u16 de_size = le16_to_cpu(de->size); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* First, check to see if there's enough room. */ 81462306a36Sopenharmony_ci if (used + de_size > total) 81562306a36Sopenharmony_ci return NULL; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* We know there's enough space, so we know we'll succeed. */ 81862306a36Sopenharmony_ci if (before) { 81962306a36Sopenharmony_ci /* Check that before is inside Index. */ 82062306a36Sopenharmony_ci if (off >= used || off < le32_to_cpu(hdr->de_off) || 82162306a36Sopenharmony_ci off + le16_to_cpu(before->size) > total) { 82262306a36Sopenharmony_ci return NULL; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci goto ok; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci /* No insert point is applied. Get it manually. */ 82762306a36Sopenharmony_ci before = hdr_find_e(indx, hdr, de + 1, le16_to_cpu(de->key_size), ctx, 82862306a36Sopenharmony_ci &diff); 82962306a36Sopenharmony_ci if (!before) 83062306a36Sopenharmony_ci return NULL; 83162306a36Sopenharmony_ci off = PtrOffset(hdr, before); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ciok: 83462306a36Sopenharmony_ci /* Now we just make room for the entry and jam it in. */ 83562306a36Sopenharmony_ci memmove(Add2Ptr(before, de_size), before, used - off); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci hdr->used = cpu_to_le32(used + de_size); 83862306a36Sopenharmony_ci memcpy(before, de, de_size); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci return before; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci/* 84462306a36Sopenharmony_ci * hdr_delete_de - Remove an entry from the index buffer. 84562306a36Sopenharmony_ci */ 84662306a36Sopenharmony_cistatic inline struct NTFS_DE *hdr_delete_de(struct INDEX_HDR *hdr, 84762306a36Sopenharmony_ci struct NTFS_DE *re) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci u32 used = le32_to_cpu(hdr->used); 85062306a36Sopenharmony_ci u16 esize = le16_to_cpu(re->size); 85162306a36Sopenharmony_ci u32 off = PtrOffset(hdr, re); 85262306a36Sopenharmony_ci int bytes = used - (off + esize); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /* check INDEX_HDR valid before using INDEX_HDR */ 85562306a36Sopenharmony_ci if (!check_index_header(hdr, le32_to_cpu(hdr->total))) 85662306a36Sopenharmony_ci return NULL; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (off >= used || esize < sizeof(struct NTFS_DE) || 85962306a36Sopenharmony_ci bytes < sizeof(struct NTFS_DE)) 86062306a36Sopenharmony_ci return NULL; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci hdr->used = cpu_to_le32(used - esize); 86362306a36Sopenharmony_ci memmove(re, Add2Ptr(re, esize), bytes); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci return re; 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_civoid indx_clear(struct ntfs_index *indx) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci run_close(&indx->alloc_run); 87162306a36Sopenharmony_ci run_close(&indx->bitmap_run); 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ciint indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi, 87562306a36Sopenharmony_ci const struct ATTRIB *attr, enum index_mutex_classed type) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci u32 t32; 87862306a36Sopenharmony_ci const struct INDEX_ROOT *root = resident_data(attr); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci t32 = le32_to_cpu(attr->res.data_size); 88162306a36Sopenharmony_ci if (t32 <= offsetof(struct INDEX_ROOT, ihdr) || 88262306a36Sopenharmony_ci !index_hdr_check(&root->ihdr, 88362306a36Sopenharmony_ci t32 - offsetof(struct INDEX_ROOT, ihdr))) { 88462306a36Sopenharmony_ci goto out; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci /* Check root fields. */ 88862306a36Sopenharmony_ci if (!root->index_block_clst) 88962306a36Sopenharmony_ci goto out; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci indx->type = type; 89262306a36Sopenharmony_ci indx->idx2vbn_bits = __ffs(root->index_block_clst); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci t32 = le32_to_cpu(root->index_block_size); 89562306a36Sopenharmony_ci indx->index_bits = blksize_bits(t32); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci /* Check index record size. */ 89862306a36Sopenharmony_ci if (t32 < sbi->cluster_size) { 89962306a36Sopenharmony_ci /* Index record is smaller than a cluster, use 512 blocks. */ 90062306a36Sopenharmony_ci if (t32 != root->index_block_clst * SECTOR_SIZE) 90162306a36Sopenharmony_ci goto out; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci /* Check alignment to a cluster. */ 90462306a36Sopenharmony_ci if ((sbi->cluster_size >> SECTOR_SHIFT) & 90562306a36Sopenharmony_ci (root->index_block_clst - 1)) { 90662306a36Sopenharmony_ci goto out; 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci indx->vbn2vbo_bits = SECTOR_SHIFT; 91062306a36Sopenharmony_ci } else { 91162306a36Sopenharmony_ci /* Index record must be a multiple of cluster size. */ 91262306a36Sopenharmony_ci if (t32 != root->index_block_clst << sbi->cluster_bits) 91362306a36Sopenharmony_ci goto out; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci indx->vbn2vbo_bits = sbi->cluster_bits; 91662306a36Sopenharmony_ci } 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci init_rwsem(&indx->run_lock); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci indx->cmp = get_cmp_func(root); 92162306a36Sopenharmony_ci if (!indx->cmp) 92262306a36Sopenharmony_ci goto out; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci return 0; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ciout: 92762306a36Sopenharmony_ci ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 92862306a36Sopenharmony_ci return -EINVAL; 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic struct indx_node *indx_new(struct ntfs_index *indx, 93262306a36Sopenharmony_ci struct ntfs_inode *ni, CLST vbn, 93362306a36Sopenharmony_ci const __le64 *sub_vbn) 93462306a36Sopenharmony_ci{ 93562306a36Sopenharmony_ci int err; 93662306a36Sopenharmony_ci struct NTFS_DE *e; 93762306a36Sopenharmony_ci struct indx_node *r; 93862306a36Sopenharmony_ci struct INDEX_HDR *hdr; 93962306a36Sopenharmony_ci struct INDEX_BUFFER *index; 94062306a36Sopenharmony_ci u64 vbo = (u64)vbn << indx->vbn2vbo_bits; 94162306a36Sopenharmony_ci u32 bytes = 1u << indx->index_bits; 94262306a36Sopenharmony_ci u16 fn; 94362306a36Sopenharmony_ci u32 eo; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci r = kzalloc(sizeof(struct indx_node), GFP_NOFS); 94662306a36Sopenharmony_ci if (!r) 94762306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci index = kzalloc(bytes, GFP_NOFS); 95062306a36Sopenharmony_ci if (!index) { 95162306a36Sopenharmony_ci kfree(r); 95262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci err = ntfs_get_bh(ni->mi.sbi, &indx->alloc_run, vbo, bytes, &r->nb); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci if (err) { 95862306a36Sopenharmony_ci kfree(index); 95962306a36Sopenharmony_ci kfree(r); 96062306a36Sopenharmony_ci return ERR_PTR(err); 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci /* Create header. */ 96462306a36Sopenharmony_ci index->rhdr.sign = NTFS_INDX_SIGNATURE; 96562306a36Sopenharmony_ci index->rhdr.fix_off = cpu_to_le16(sizeof(struct INDEX_BUFFER)); // 0x28 96662306a36Sopenharmony_ci fn = (bytes >> SECTOR_SHIFT) + 1; // 9 96762306a36Sopenharmony_ci index->rhdr.fix_num = cpu_to_le16(fn); 96862306a36Sopenharmony_ci index->vbn = cpu_to_le64(vbn); 96962306a36Sopenharmony_ci hdr = &index->ihdr; 97062306a36Sopenharmony_ci eo = ALIGN(sizeof(struct INDEX_BUFFER) + fn * sizeof(short), 8); 97162306a36Sopenharmony_ci hdr->de_off = cpu_to_le32(eo); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci e = Add2Ptr(hdr, eo); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci if (sub_vbn) { 97662306a36Sopenharmony_ci e->flags = NTFS_IE_LAST | NTFS_IE_HAS_SUBNODES; 97762306a36Sopenharmony_ci e->size = cpu_to_le16(sizeof(struct NTFS_DE) + sizeof(u64)); 97862306a36Sopenharmony_ci hdr->used = 97962306a36Sopenharmony_ci cpu_to_le32(eo + sizeof(struct NTFS_DE) + sizeof(u64)); 98062306a36Sopenharmony_ci de_set_vbn_le(e, *sub_vbn); 98162306a36Sopenharmony_ci hdr->flags = 1; 98262306a36Sopenharmony_ci } else { 98362306a36Sopenharmony_ci e->size = cpu_to_le16(sizeof(struct NTFS_DE)); 98462306a36Sopenharmony_ci hdr->used = cpu_to_le32(eo + sizeof(struct NTFS_DE)); 98562306a36Sopenharmony_ci e->flags = NTFS_IE_LAST; 98662306a36Sopenharmony_ci } 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci hdr->total = cpu_to_le32(bytes - offsetof(struct INDEX_BUFFER, ihdr)); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci r->index = index; 99162306a36Sopenharmony_ci return r; 99262306a36Sopenharmony_ci} 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_cistruct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni, 99562306a36Sopenharmony_ci struct ATTRIB **attr, struct mft_inode **mi) 99662306a36Sopenharmony_ci{ 99762306a36Sopenharmony_ci struct ATTR_LIST_ENTRY *le = NULL; 99862306a36Sopenharmony_ci struct ATTRIB *a; 99962306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 100062306a36Sopenharmony_ci struct INDEX_ROOT *root; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci a = ni_find_attr(ni, NULL, &le, ATTR_ROOT, in->name, in->name_len, NULL, 100362306a36Sopenharmony_ci mi); 100462306a36Sopenharmony_ci if (!a) 100562306a36Sopenharmony_ci return NULL; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (attr) 100862306a36Sopenharmony_ci *attr = a; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci root = resident_data_ex(a, sizeof(struct INDEX_ROOT)); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci /* length check */ 101362306a36Sopenharmony_ci if (root && 101462306a36Sopenharmony_ci offsetof(struct INDEX_ROOT, ihdr) + le32_to_cpu(root->ihdr.used) > 101562306a36Sopenharmony_ci le32_to_cpu(a->res.data_size)) { 101662306a36Sopenharmony_ci return NULL; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci return root; 102062306a36Sopenharmony_ci} 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_cistatic int indx_write(struct ntfs_index *indx, struct ntfs_inode *ni, 102362306a36Sopenharmony_ci struct indx_node *node, int sync) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci struct INDEX_BUFFER *ib = node->index; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci return ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &node->nb, sync); 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci/* 103162306a36Sopenharmony_ci * indx_read 103262306a36Sopenharmony_ci * 103362306a36Sopenharmony_ci * If ntfs_readdir calls this function 103462306a36Sopenharmony_ci * inode is shared locked and no ni_lock. 103562306a36Sopenharmony_ci * Use rw_semaphore for read/write access to alloc_run. 103662306a36Sopenharmony_ci */ 103762306a36Sopenharmony_ciint indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn, 103862306a36Sopenharmony_ci struct indx_node **node) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci int err; 104162306a36Sopenharmony_ci struct INDEX_BUFFER *ib; 104262306a36Sopenharmony_ci struct runs_tree *run = &indx->alloc_run; 104362306a36Sopenharmony_ci struct rw_semaphore *lock = &indx->run_lock; 104462306a36Sopenharmony_ci u64 vbo = (u64)vbn << indx->vbn2vbo_bits; 104562306a36Sopenharmony_ci u32 bytes = 1u << indx->index_bits; 104662306a36Sopenharmony_ci struct indx_node *in = *node; 104762306a36Sopenharmony_ci const struct INDEX_NAMES *name; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci if (!in) { 105062306a36Sopenharmony_ci in = kzalloc(sizeof(struct indx_node), GFP_NOFS); 105162306a36Sopenharmony_ci if (!in) 105262306a36Sopenharmony_ci return -ENOMEM; 105362306a36Sopenharmony_ci } else { 105462306a36Sopenharmony_ci nb_put(&in->nb); 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci ib = in->index; 105862306a36Sopenharmony_ci if (!ib) { 105962306a36Sopenharmony_ci ib = kmalloc(bytes, GFP_NOFS); 106062306a36Sopenharmony_ci if (!ib) { 106162306a36Sopenharmony_ci err = -ENOMEM; 106262306a36Sopenharmony_ci goto out; 106362306a36Sopenharmony_ci } 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci down_read(lock); 106762306a36Sopenharmony_ci err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb); 106862306a36Sopenharmony_ci up_read(lock); 106962306a36Sopenharmony_ci if (!err) 107062306a36Sopenharmony_ci goto ok; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci if (err == -E_NTFS_FIXUP) 107362306a36Sopenharmony_ci goto ok; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci if (err != -ENOENT) 107662306a36Sopenharmony_ci goto out; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci name = &s_index_names[indx->type]; 107962306a36Sopenharmony_ci down_write(lock); 108062306a36Sopenharmony_ci err = attr_load_runs_range(ni, ATTR_ALLOC, name->name, name->name_len, 108162306a36Sopenharmony_ci run, vbo, vbo + bytes); 108262306a36Sopenharmony_ci up_write(lock); 108362306a36Sopenharmony_ci if (err) 108462306a36Sopenharmony_ci goto out; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci down_read(lock); 108762306a36Sopenharmony_ci err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb); 108862306a36Sopenharmony_ci up_read(lock); 108962306a36Sopenharmony_ci if (err == -E_NTFS_FIXUP) 109062306a36Sopenharmony_ci goto ok; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (err) 109362306a36Sopenharmony_ci goto out; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ciok: 109662306a36Sopenharmony_ci if (!index_buf_check(ib, bytes, &vbn)) { 109762306a36Sopenharmony_ci ntfs_inode_err(&ni->vfs_inode, "directory corrupted"); 109862306a36Sopenharmony_ci ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR); 109962306a36Sopenharmony_ci err = -EINVAL; 110062306a36Sopenharmony_ci goto out; 110162306a36Sopenharmony_ci } 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci if (err == -E_NTFS_FIXUP) { 110462306a36Sopenharmony_ci ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &in->nb, 0); 110562306a36Sopenharmony_ci err = 0; 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* check for index header length */ 110962306a36Sopenharmony_ci if (offsetof(struct INDEX_BUFFER, ihdr) + le32_to_cpu(ib->ihdr.used) > 111062306a36Sopenharmony_ci bytes) { 111162306a36Sopenharmony_ci err = -EINVAL; 111262306a36Sopenharmony_ci goto out; 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci in->index = ib; 111662306a36Sopenharmony_ci *node = in; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ciout: 111962306a36Sopenharmony_ci if (err == -E_NTFS_CORRUPT) { 112062306a36Sopenharmony_ci ntfs_inode_err(&ni->vfs_inode, "directory corrupted"); 112162306a36Sopenharmony_ci ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR); 112262306a36Sopenharmony_ci err = -EINVAL; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci if (ib != in->index) 112662306a36Sopenharmony_ci kfree(ib); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci if (*node != in) { 112962306a36Sopenharmony_ci nb_put(&in->nb); 113062306a36Sopenharmony_ci kfree(in); 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci return err; 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci/* 113762306a36Sopenharmony_ci * indx_find - Scan NTFS directory for given entry. 113862306a36Sopenharmony_ci */ 113962306a36Sopenharmony_ciint indx_find(struct ntfs_index *indx, struct ntfs_inode *ni, 114062306a36Sopenharmony_ci const struct INDEX_ROOT *root, const void *key, size_t key_len, 114162306a36Sopenharmony_ci const void *ctx, int *diff, struct NTFS_DE **entry, 114262306a36Sopenharmony_ci struct ntfs_fnd *fnd) 114362306a36Sopenharmony_ci{ 114462306a36Sopenharmony_ci int err; 114562306a36Sopenharmony_ci struct NTFS_DE *e; 114662306a36Sopenharmony_ci struct indx_node *node; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci if (!root) 114962306a36Sopenharmony_ci root = indx_get_root(&ni->dir, ni, NULL, NULL); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci if (!root) { 115262306a36Sopenharmony_ci /* Should not happen. */ 115362306a36Sopenharmony_ci return -EINVAL; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* Check cache. */ 115762306a36Sopenharmony_ci e = fnd->level ? fnd->de[fnd->level - 1] : fnd->root_de; 115862306a36Sopenharmony_ci if (e && !de_is_last(e) && 115962306a36Sopenharmony_ci !(*indx->cmp)(key, key_len, e + 1, le16_to_cpu(e->key_size), ctx)) { 116062306a36Sopenharmony_ci *entry = e; 116162306a36Sopenharmony_ci *diff = 0; 116262306a36Sopenharmony_ci return 0; 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci /* Soft finder reset. */ 116662306a36Sopenharmony_ci fnd_clear(fnd); 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci /* Lookup entry that is <= to the search value. */ 116962306a36Sopenharmony_ci e = hdr_find_e(indx, &root->ihdr, key, key_len, ctx, diff); 117062306a36Sopenharmony_ci if (!e) 117162306a36Sopenharmony_ci return -EINVAL; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci fnd->root_de = e; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci for (;;) { 117662306a36Sopenharmony_ci node = NULL; 117762306a36Sopenharmony_ci if (*diff >= 0 || !de_has_vcn_ex(e)) 117862306a36Sopenharmony_ci break; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci /* Read next level. */ 118162306a36Sopenharmony_ci err = indx_read(indx, ni, de_get_vbn(e), &node); 118262306a36Sopenharmony_ci if (err) { 118362306a36Sopenharmony_ci /* io error? */ 118462306a36Sopenharmony_ci return err; 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci /* Lookup entry that is <= to the search value. */ 118862306a36Sopenharmony_ci e = hdr_find_e(indx, &node->index->ihdr, key, key_len, ctx, 118962306a36Sopenharmony_ci diff); 119062306a36Sopenharmony_ci if (!e) { 119162306a36Sopenharmony_ci put_indx_node(node); 119262306a36Sopenharmony_ci return -EINVAL; 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci fnd_push(fnd, node, e); 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci *entry = e; 119962306a36Sopenharmony_ci return 0; 120062306a36Sopenharmony_ci} 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ciint indx_find_sort(struct ntfs_index *indx, struct ntfs_inode *ni, 120362306a36Sopenharmony_ci const struct INDEX_ROOT *root, struct NTFS_DE **entry, 120462306a36Sopenharmony_ci struct ntfs_fnd *fnd) 120562306a36Sopenharmony_ci{ 120662306a36Sopenharmony_ci int err; 120762306a36Sopenharmony_ci struct indx_node *n = NULL; 120862306a36Sopenharmony_ci struct NTFS_DE *e; 120962306a36Sopenharmony_ci size_t iter = 0; 121062306a36Sopenharmony_ci int level = fnd->level; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci if (!*entry) { 121362306a36Sopenharmony_ci /* Start find. */ 121462306a36Sopenharmony_ci e = hdr_first_de(&root->ihdr); 121562306a36Sopenharmony_ci if (!e) 121662306a36Sopenharmony_ci return 0; 121762306a36Sopenharmony_ci fnd_clear(fnd); 121862306a36Sopenharmony_ci fnd->root_de = e; 121962306a36Sopenharmony_ci } else if (!level) { 122062306a36Sopenharmony_ci if (de_is_last(fnd->root_de)) { 122162306a36Sopenharmony_ci *entry = NULL; 122262306a36Sopenharmony_ci return 0; 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci e = hdr_next_de(&root->ihdr, fnd->root_de); 122662306a36Sopenharmony_ci if (!e) 122762306a36Sopenharmony_ci return -EINVAL; 122862306a36Sopenharmony_ci fnd->root_de = e; 122962306a36Sopenharmony_ci } else { 123062306a36Sopenharmony_ci n = fnd->nodes[level - 1]; 123162306a36Sopenharmony_ci e = fnd->de[level - 1]; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if (de_is_last(e)) 123462306a36Sopenharmony_ci goto pop_level; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci e = hdr_next_de(&n->index->ihdr, e); 123762306a36Sopenharmony_ci if (!e) 123862306a36Sopenharmony_ci return -EINVAL; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci fnd->de[level - 1] = e; 124162306a36Sopenharmony_ci } 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci /* Just to avoid tree cycle. */ 124462306a36Sopenharmony_cinext_iter: 124562306a36Sopenharmony_ci if (iter++ >= 1000) 124662306a36Sopenharmony_ci return -EINVAL; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci while (de_has_vcn_ex(e)) { 124962306a36Sopenharmony_ci if (le16_to_cpu(e->size) < 125062306a36Sopenharmony_ci sizeof(struct NTFS_DE) + sizeof(u64)) { 125162306a36Sopenharmony_ci if (n) { 125262306a36Sopenharmony_ci fnd_pop(fnd); 125362306a36Sopenharmony_ci kfree(n); 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci return -EINVAL; 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci /* Read next level. */ 125962306a36Sopenharmony_ci err = indx_read(indx, ni, de_get_vbn(e), &n); 126062306a36Sopenharmony_ci if (err) 126162306a36Sopenharmony_ci return err; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* Try next level. */ 126462306a36Sopenharmony_ci e = hdr_first_de(&n->index->ihdr); 126562306a36Sopenharmony_ci if (!e) { 126662306a36Sopenharmony_ci kfree(n); 126762306a36Sopenharmony_ci return -EINVAL; 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci fnd_push(fnd, n, e); 127162306a36Sopenharmony_ci } 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci if (le16_to_cpu(e->size) > sizeof(struct NTFS_DE)) { 127462306a36Sopenharmony_ci *entry = e; 127562306a36Sopenharmony_ci return 0; 127662306a36Sopenharmony_ci } 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_cipop_level: 127962306a36Sopenharmony_ci for (;;) { 128062306a36Sopenharmony_ci if (!de_is_last(e)) 128162306a36Sopenharmony_ci goto next_iter; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* Pop one level. */ 128462306a36Sopenharmony_ci if (n) { 128562306a36Sopenharmony_ci fnd_pop(fnd); 128662306a36Sopenharmony_ci kfree(n); 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci level = fnd->level; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci if (level) { 129262306a36Sopenharmony_ci n = fnd->nodes[level - 1]; 129362306a36Sopenharmony_ci e = fnd->de[level - 1]; 129462306a36Sopenharmony_ci } else if (fnd->root_de) { 129562306a36Sopenharmony_ci n = NULL; 129662306a36Sopenharmony_ci e = fnd->root_de; 129762306a36Sopenharmony_ci fnd->root_de = NULL; 129862306a36Sopenharmony_ci } else { 129962306a36Sopenharmony_ci *entry = NULL; 130062306a36Sopenharmony_ci return 0; 130162306a36Sopenharmony_ci } 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (le16_to_cpu(e->size) > sizeof(struct NTFS_DE)) { 130462306a36Sopenharmony_ci *entry = e; 130562306a36Sopenharmony_ci if (!fnd->root_de) 130662306a36Sopenharmony_ci fnd->root_de = e; 130762306a36Sopenharmony_ci return 0; 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci} 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ciint indx_find_raw(struct ntfs_index *indx, struct ntfs_inode *ni, 131362306a36Sopenharmony_ci const struct INDEX_ROOT *root, struct NTFS_DE **entry, 131462306a36Sopenharmony_ci size_t *off, struct ntfs_fnd *fnd) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci int err; 131762306a36Sopenharmony_ci struct indx_node *n = NULL; 131862306a36Sopenharmony_ci struct NTFS_DE *e = NULL; 131962306a36Sopenharmony_ci struct NTFS_DE *e2; 132062306a36Sopenharmony_ci size_t bit; 132162306a36Sopenharmony_ci CLST next_used_vbn; 132262306a36Sopenharmony_ci CLST next_vbn; 132362306a36Sopenharmony_ci u32 record_size = ni->mi.sbi->record_size; 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci /* Use non sorted algorithm. */ 132662306a36Sopenharmony_ci if (!*entry) { 132762306a36Sopenharmony_ci /* This is the first call. */ 132862306a36Sopenharmony_ci e = hdr_first_de(&root->ihdr); 132962306a36Sopenharmony_ci if (!e) 133062306a36Sopenharmony_ci return 0; 133162306a36Sopenharmony_ci fnd_clear(fnd); 133262306a36Sopenharmony_ci fnd->root_de = e; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci /* The first call with setup of initial element. */ 133562306a36Sopenharmony_ci if (*off >= record_size) { 133662306a36Sopenharmony_ci next_vbn = (((*off - record_size) >> indx->index_bits)) 133762306a36Sopenharmony_ci << indx->idx2vbn_bits; 133862306a36Sopenharmony_ci /* Jump inside cycle 'for'. */ 133962306a36Sopenharmony_ci goto next; 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci /* Start enumeration from root. */ 134362306a36Sopenharmony_ci *off = 0; 134462306a36Sopenharmony_ci } else if (!fnd->root_de) 134562306a36Sopenharmony_ci return -EINVAL; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci for (;;) { 134862306a36Sopenharmony_ci /* Check if current entry can be used. */ 134962306a36Sopenharmony_ci if (e && le16_to_cpu(e->size) > sizeof(struct NTFS_DE)) 135062306a36Sopenharmony_ci goto ok; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci if (!fnd->level) { 135362306a36Sopenharmony_ci /* Continue to enumerate root. */ 135462306a36Sopenharmony_ci if (!de_is_last(fnd->root_de)) { 135562306a36Sopenharmony_ci e = hdr_next_de(&root->ihdr, fnd->root_de); 135662306a36Sopenharmony_ci if (!e) 135762306a36Sopenharmony_ci return -EINVAL; 135862306a36Sopenharmony_ci fnd->root_de = e; 135962306a36Sopenharmony_ci continue; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci /* Start to enumerate indexes from 0. */ 136362306a36Sopenharmony_ci next_vbn = 0; 136462306a36Sopenharmony_ci } else { 136562306a36Sopenharmony_ci /* Continue to enumerate indexes. */ 136662306a36Sopenharmony_ci e2 = fnd->de[fnd->level - 1]; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci n = fnd->nodes[fnd->level - 1]; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci if (!de_is_last(e2)) { 137162306a36Sopenharmony_ci e = hdr_next_de(&n->index->ihdr, e2); 137262306a36Sopenharmony_ci if (!e) 137362306a36Sopenharmony_ci return -EINVAL; 137462306a36Sopenharmony_ci fnd->de[fnd->level - 1] = e; 137562306a36Sopenharmony_ci continue; 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* Continue with next index. */ 137962306a36Sopenharmony_ci next_vbn = le64_to_cpu(n->index->vbn) + 138062306a36Sopenharmony_ci root->index_block_clst; 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cinext: 138462306a36Sopenharmony_ci /* Release current index. */ 138562306a36Sopenharmony_ci if (n) { 138662306a36Sopenharmony_ci fnd_pop(fnd); 138762306a36Sopenharmony_ci put_indx_node(n); 138862306a36Sopenharmony_ci n = NULL; 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci /* Skip all free indexes. */ 139262306a36Sopenharmony_ci bit = next_vbn >> indx->idx2vbn_bits; 139362306a36Sopenharmony_ci err = indx_used_bit(indx, ni, &bit); 139462306a36Sopenharmony_ci if (err == -ENOENT || bit == MINUS_ONE_T) { 139562306a36Sopenharmony_ci /* No used indexes. */ 139662306a36Sopenharmony_ci *entry = NULL; 139762306a36Sopenharmony_ci return 0; 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci next_used_vbn = bit << indx->idx2vbn_bits; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci /* Read buffer into memory. */ 140362306a36Sopenharmony_ci err = indx_read(indx, ni, next_used_vbn, &n); 140462306a36Sopenharmony_ci if (err) 140562306a36Sopenharmony_ci return err; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci e = hdr_first_de(&n->index->ihdr); 140862306a36Sopenharmony_ci fnd_push(fnd, n, e); 140962306a36Sopenharmony_ci if (!e) 141062306a36Sopenharmony_ci return -EINVAL; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ciok: 141462306a36Sopenharmony_ci /* Return offset to restore enumerator if necessary. */ 141562306a36Sopenharmony_ci if (!n) { 141662306a36Sopenharmony_ci /* 'e' points in root, */ 141762306a36Sopenharmony_ci *off = PtrOffset(&root->ihdr, e); 141862306a36Sopenharmony_ci } else { 141962306a36Sopenharmony_ci /* 'e' points in index, */ 142062306a36Sopenharmony_ci *off = (le64_to_cpu(n->index->vbn) << indx->vbn2vbo_bits) + 142162306a36Sopenharmony_ci record_size + PtrOffset(&n->index->ihdr, e); 142262306a36Sopenharmony_ci } 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci *entry = e; 142562306a36Sopenharmony_ci return 0; 142662306a36Sopenharmony_ci} 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci/* 142962306a36Sopenharmony_ci * indx_create_allocate - Create "Allocation + Bitmap" attributes. 143062306a36Sopenharmony_ci */ 143162306a36Sopenharmony_cistatic int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, 143262306a36Sopenharmony_ci CLST *vbn) 143362306a36Sopenharmony_ci{ 143462306a36Sopenharmony_ci int err; 143562306a36Sopenharmony_ci struct ntfs_sb_info *sbi = ni->mi.sbi; 143662306a36Sopenharmony_ci struct ATTRIB *bitmap; 143762306a36Sopenharmony_ci struct ATTRIB *alloc; 143862306a36Sopenharmony_ci u32 data_size = 1u << indx->index_bits; 143962306a36Sopenharmony_ci u32 alloc_size = ntfs_up_cluster(sbi, data_size); 144062306a36Sopenharmony_ci CLST len = alloc_size >> sbi->cluster_bits; 144162306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 144262306a36Sopenharmony_ci CLST alen; 144362306a36Sopenharmony_ci struct runs_tree run; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci run_init(&run); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci err = attr_allocate_clusters(sbi, &run, 0, 0, len, NULL, ALLOCATE_DEF, 144862306a36Sopenharmony_ci &alen, 0, NULL, NULL); 144962306a36Sopenharmony_ci if (err) 145062306a36Sopenharmony_ci goto out; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci err = ni_insert_nonresident(ni, ATTR_ALLOC, in->name, in->name_len, 145362306a36Sopenharmony_ci &run, 0, len, 0, &alloc, NULL, NULL); 145462306a36Sopenharmony_ci if (err) 145562306a36Sopenharmony_ci goto out1; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci alloc->nres.valid_size = alloc->nres.data_size = cpu_to_le64(data_size); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci err = ni_insert_resident(ni, bitmap_size(1), ATTR_BITMAP, in->name, 146062306a36Sopenharmony_ci in->name_len, &bitmap, NULL, NULL); 146162306a36Sopenharmony_ci if (err) 146262306a36Sopenharmony_ci goto out2; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (in->name == I30_NAME) { 146562306a36Sopenharmony_ci i_size_write(&ni->vfs_inode, data_size); 146662306a36Sopenharmony_ci inode_set_bytes(&ni->vfs_inode, alloc_size); 146762306a36Sopenharmony_ci } 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci memcpy(&indx->alloc_run, &run, sizeof(run)); 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci *vbn = 0; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci return 0; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ciout2: 147662306a36Sopenharmony_ci mi_remove_attr(NULL, &ni->mi, alloc); 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ciout1: 147962306a36Sopenharmony_ci run_deallocate(sbi, &run, false); 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ciout: 148262306a36Sopenharmony_ci return err; 148362306a36Sopenharmony_ci} 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci/* 148662306a36Sopenharmony_ci * indx_add_allocate - Add clusters to index. 148762306a36Sopenharmony_ci */ 148862306a36Sopenharmony_cistatic int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, 148962306a36Sopenharmony_ci CLST *vbn) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci int err; 149262306a36Sopenharmony_ci size_t bit; 149362306a36Sopenharmony_ci u64 data_size; 149462306a36Sopenharmony_ci u64 bmp_size, bmp_size_v; 149562306a36Sopenharmony_ci struct ATTRIB *bmp, *alloc; 149662306a36Sopenharmony_ci struct mft_inode *mi; 149762306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci err = indx_find_free(indx, ni, &bit, &bmp); 150062306a36Sopenharmony_ci if (err) 150162306a36Sopenharmony_ci goto out1; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (bit != MINUS_ONE_T) { 150462306a36Sopenharmony_ci bmp = NULL; 150562306a36Sopenharmony_ci } else { 150662306a36Sopenharmony_ci if (bmp->non_res) { 150762306a36Sopenharmony_ci bmp_size = le64_to_cpu(bmp->nres.data_size); 150862306a36Sopenharmony_ci bmp_size_v = le64_to_cpu(bmp->nres.valid_size); 150962306a36Sopenharmony_ci } else { 151062306a36Sopenharmony_ci bmp_size = bmp_size_v = le32_to_cpu(bmp->res.data_size); 151162306a36Sopenharmony_ci } 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci bit = bmp_size << 3; 151462306a36Sopenharmony_ci } 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci data_size = (u64)(bit + 1) << indx->index_bits; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci if (bmp) { 151962306a36Sopenharmony_ci /* Increase bitmap. */ 152062306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len, 152162306a36Sopenharmony_ci &indx->bitmap_run, bitmap_size(bit + 1), 152262306a36Sopenharmony_ci NULL, true, NULL); 152362306a36Sopenharmony_ci if (err) 152462306a36Sopenharmony_ci goto out1; 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci alloc = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, in->name, in->name_len, 152862306a36Sopenharmony_ci NULL, &mi); 152962306a36Sopenharmony_ci if (!alloc) { 153062306a36Sopenharmony_ci err = -EINVAL; 153162306a36Sopenharmony_ci if (bmp) 153262306a36Sopenharmony_ci goto out2; 153362306a36Sopenharmony_ci goto out1; 153462306a36Sopenharmony_ci } 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci /* Increase allocation. */ 153762306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len, 153862306a36Sopenharmony_ci &indx->alloc_run, data_size, &data_size, true, 153962306a36Sopenharmony_ci NULL); 154062306a36Sopenharmony_ci if (err) { 154162306a36Sopenharmony_ci if (bmp) 154262306a36Sopenharmony_ci goto out2; 154362306a36Sopenharmony_ci goto out1; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci if (in->name == I30_NAME) 154762306a36Sopenharmony_ci i_size_write(&ni->vfs_inode, data_size); 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci *vbn = bit << indx->idx2vbn_bits; 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci return 0; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ciout2: 155462306a36Sopenharmony_ci /* Ops. No space? */ 155562306a36Sopenharmony_ci attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len, 155662306a36Sopenharmony_ci &indx->bitmap_run, bmp_size, &bmp_size_v, false, NULL); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ciout1: 155962306a36Sopenharmony_ci return err; 156062306a36Sopenharmony_ci} 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci/* 156362306a36Sopenharmony_ci * indx_insert_into_root - Attempt to insert an entry into the index root. 156462306a36Sopenharmony_ci * 156562306a36Sopenharmony_ci * @undo - True if we undoing previous remove. 156662306a36Sopenharmony_ci * If necessary, it will twiddle the index b-tree. 156762306a36Sopenharmony_ci */ 156862306a36Sopenharmony_cistatic int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, 156962306a36Sopenharmony_ci const struct NTFS_DE *new_de, 157062306a36Sopenharmony_ci struct NTFS_DE *root_de, const void *ctx, 157162306a36Sopenharmony_ci struct ntfs_fnd *fnd, bool undo) 157262306a36Sopenharmony_ci{ 157362306a36Sopenharmony_ci int err = 0; 157462306a36Sopenharmony_ci struct NTFS_DE *e, *e0, *re; 157562306a36Sopenharmony_ci struct mft_inode *mi; 157662306a36Sopenharmony_ci struct ATTRIB *attr; 157762306a36Sopenharmony_ci struct INDEX_HDR *hdr; 157862306a36Sopenharmony_ci struct indx_node *n; 157962306a36Sopenharmony_ci CLST new_vbn; 158062306a36Sopenharmony_ci __le64 *sub_vbn, t_vbn; 158162306a36Sopenharmony_ci u16 new_de_size; 158262306a36Sopenharmony_ci u32 hdr_used, hdr_total, asize, to_move; 158362306a36Sopenharmony_ci u32 root_size, new_root_size; 158462306a36Sopenharmony_ci struct ntfs_sb_info *sbi; 158562306a36Sopenharmony_ci int ds_root; 158662306a36Sopenharmony_ci struct INDEX_ROOT *root, *a_root; 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci /* Get the record this root placed in. */ 158962306a36Sopenharmony_ci root = indx_get_root(indx, ni, &attr, &mi); 159062306a36Sopenharmony_ci if (!root) 159162306a36Sopenharmony_ci return -EINVAL; 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci /* 159462306a36Sopenharmony_ci * Try easy case: 159562306a36Sopenharmony_ci * hdr_insert_de will succeed if there's 159662306a36Sopenharmony_ci * room the root for the new entry. 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_ci hdr = &root->ihdr; 159962306a36Sopenharmony_ci sbi = ni->mi.sbi; 160062306a36Sopenharmony_ci new_de_size = le16_to_cpu(new_de->size); 160162306a36Sopenharmony_ci hdr_used = le32_to_cpu(hdr->used); 160262306a36Sopenharmony_ci hdr_total = le32_to_cpu(hdr->total); 160362306a36Sopenharmony_ci asize = le32_to_cpu(attr->size); 160462306a36Sopenharmony_ci root_size = le32_to_cpu(attr->res.data_size); 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci ds_root = new_de_size + hdr_used - hdr_total; 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci /* If 'undo' is set then reduce requirements. */ 160962306a36Sopenharmony_ci if ((undo || asize + ds_root < sbi->max_bytes_per_attr) && 161062306a36Sopenharmony_ci mi_resize_attr(mi, attr, ds_root)) { 161162306a36Sopenharmony_ci hdr->total = cpu_to_le32(hdr_total + ds_root); 161262306a36Sopenharmony_ci e = hdr_insert_de(indx, hdr, new_de, root_de, ctx); 161362306a36Sopenharmony_ci WARN_ON(!e); 161462306a36Sopenharmony_ci fnd_clear(fnd); 161562306a36Sopenharmony_ci fnd->root_de = e; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci return 0; 161862306a36Sopenharmony_ci } 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci /* Make a copy of root attribute to restore if error. */ 162162306a36Sopenharmony_ci a_root = kmemdup(attr, asize, GFP_NOFS); 162262306a36Sopenharmony_ci if (!a_root) 162362306a36Sopenharmony_ci return -ENOMEM; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci /* 162662306a36Sopenharmony_ci * Copy all the non-end entries from 162762306a36Sopenharmony_ci * the index root to the new buffer. 162862306a36Sopenharmony_ci */ 162962306a36Sopenharmony_ci to_move = 0; 163062306a36Sopenharmony_ci e0 = hdr_first_de(hdr); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* Calculate the size to copy. */ 163362306a36Sopenharmony_ci for (e = e0;; e = hdr_next_de(hdr, e)) { 163462306a36Sopenharmony_ci if (!e) { 163562306a36Sopenharmony_ci err = -EINVAL; 163662306a36Sopenharmony_ci goto out_free_root; 163762306a36Sopenharmony_ci } 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci if (de_is_last(e)) 164062306a36Sopenharmony_ci break; 164162306a36Sopenharmony_ci to_move += le16_to_cpu(e->size); 164262306a36Sopenharmony_ci } 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci if (!to_move) { 164562306a36Sopenharmony_ci re = NULL; 164662306a36Sopenharmony_ci } else { 164762306a36Sopenharmony_ci re = kmemdup(e0, to_move, GFP_NOFS); 164862306a36Sopenharmony_ci if (!re) { 164962306a36Sopenharmony_ci err = -ENOMEM; 165062306a36Sopenharmony_ci goto out_free_root; 165162306a36Sopenharmony_ci } 165262306a36Sopenharmony_ci } 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci sub_vbn = NULL; 165562306a36Sopenharmony_ci if (de_has_vcn(e)) { 165662306a36Sopenharmony_ci t_vbn = de_get_vbn_le(e); 165762306a36Sopenharmony_ci sub_vbn = &t_vbn; 165862306a36Sopenharmony_ci } 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci new_root_size = sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE) + 166162306a36Sopenharmony_ci sizeof(u64); 166262306a36Sopenharmony_ci ds_root = new_root_size - root_size; 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci if (ds_root > 0 && asize + ds_root > sbi->max_bytes_per_attr) { 166562306a36Sopenharmony_ci /* Make root external. */ 166662306a36Sopenharmony_ci err = -EOPNOTSUPP; 166762306a36Sopenharmony_ci goto out_free_re; 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci if (ds_root) 167162306a36Sopenharmony_ci mi_resize_attr(mi, attr, ds_root); 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci /* Fill first entry (vcn will be set later). */ 167462306a36Sopenharmony_ci e = (struct NTFS_DE *)(root + 1); 167562306a36Sopenharmony_ci memset(e, 0, sizeof(struct NTFS_DE)); 167662306a36Sopenharmony_ci e->size = cpu_to_le16(sizeof(struct NTFS_DE) + sizeof(u64)); 167762306a36Sopenharmony_ci e->flags = NTFS_IE_HAS_SUBNODES | NTFS_IE_LAST; 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci hdr->flags = 1; 168062306a36Sopenharmony_ci hdr->used = hdr->total = 168162306a36Sopenharmony_ci cpu_to_le32(new_root_size - offsetof(struct INDEX_ROOT, ihdr)); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci fnd->root_de = hdr_first_de(hdr); 168462306a36Sopenharmony_ci mi->dirty = true; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci /* Create alloc and bitmap attributes (if not). */ 168762306a36Sopenharmony_ci err = run_is_empty(&indx->alloc_run) ? 168862306a36Sopenharmony_ci indx_create_allocate(indx, ni, &new_vbn) : 168962306a36Sopenharmony_ci indx_add_allocate(indx, ni, &new_vbn); 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci /* Layout of record may be changed, so rescan root. */ 169262306a36Sopenharmony_ci root = indx_get_root(indx, ni, &attr, &mi); 169362306a36Sopenharmony_ci if (!root) { 169462306a36Sopenharmony_ci /* Bug? */ 169562306a36Sopenharmony_ci ntfs_set_state(sbi, NTFS_DIRTY_ERROR); 169662306a36Sopenharmony_ci err = -EINVAL; 169762306a36Sopenharmony_ci goto out_free_re; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci if (err) { 170162306a36Sopenharmony_ci /* Restore root. */ 170262306a36Sopenharmony_ci if (mi_resize_attr(mi, attr, -ds_root)) { 170362306a36Sopenharmony_ci memcpy(attr, a_root, asize); 170462306a36Sopenharmony_ci } else { 170562306a36Sopenharmony_ci /* Bug? */ 170662306a36Sopenharmony_ci ntfs_set_state(sbi, NTFS_DIRTY_ERROR); 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci goto out_free_re; 170962306a36Sopenharmony_ci } 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci e = (struct NTFS_DE *)(root + 1); 171262306a36Sopenharmony_ci *(__le64 *)(e + 1) = cpu_to_le64(new_vbn); 171362306a36Sopenharmony_ci mi->dirty = true; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci /* Now we can create/format the new buffer and copy the entries into. */ 171662306a36Sopenharmony_ci n = indx_new(indx, ni, new_vbn, sub_vbn); 171762306a36Sopenharmony_ci if (IS_ERR(n)) { 171862306a36Sopenharmony_ci err = PTR_ERR(n); 171962306a36Sopenharmony_ci goto out_free_re; 172062306a36Sopenharmony_ci } 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci hdr = &n->index->ihdr; 172362306a36Sopenharmony_ci hdr_used = le32_to_cpu(hdr->used); 172462306a36Sopenharmony_ci hdr_total = le32_to_cpu(hdr->total); 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci /* Copy root entries into new buffer. */ 172762306a36Sopenharmony_ci hdr_insert_head(hdr, re, to_move); 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci /* Update bitmap attribute. */ 173062306a36Sopenharmony_ci indx_mark_used(indx, ni, new_vbn >> indx->idx2vbn_bits); 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci /* Check if we can insert new entry new index buffer. */ 173362306a36Sopenharmony_ci if (hdr_used + new_de_size > hdr_total) { 173462306a36Sopenharmony_ci /* 173562306a36Sopenharmony_ci * This occurs if MFT record is the same or bigger than index 173662306a36Sopenharmony_ci * buffer. Move all root new index and have no space to add 173762306a36Sopenharmony_ci * new entry classic case when MFT record is 1K and index 173862306a36Sopenharmony_ci * buffer 4K the problem should not occurs. 173962306a36Sopenharmony_ci */ 174062306a36Sopenharmony_ci kfree(re); 174162306a36Sopenharmony_ci indx_write(indx, ni, n, 0); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci put_indx_node(n); 174462306a36Sopenharmony_ci fnd_clear(fnd); 174562306a36Sopenharmony_ci err = indx_insert_entry(indx, ni, new_de, ctx, fnd, undo); 174662306a36Sopenharmony_ci goto out_free_root; 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci /* 175062306a36Sopenharmony_ci * Now root is a parent for new index buffer. 175162306a36Sopenharmony_ci * Insert NewEntry a new buffer. 175262306a36Sopenharmony_ci */ 175362306a36Sopenharmony_ci e = hdr_insert_de(indx, hdr, new_de, NULL, ctx); 175462306a36Sopenharmony_ci if (!e) { 175562306a36Sopenharmony_ci err = -EINVAL; 175662306a36Sopenharmony_ci goto out_put_n; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci fnd_push(fnd, n, e); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci /* Just write updates index into disk. */ 176162306a36Sopenharmony_ci indx_write(indx, ni, n, 0); 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci n = NULL; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ciout_put_n: 176662306a36Sopenharmony_ci put_indx_node(n); 176762306a36Sopenharmony_ciout_free_re: 176862306a36Sopenharmony_ci kfree(re); 176962306a36Sopenharmony_ciout_free_root: 177062306a36Sopenharmony_ci kfree(a_root); 177162306a36Sopenharmony_ci return err; 177262306a36Sopenharmony_ci} 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci/* 177562306a36Sopenharmony_ci * indx_insert_into_buffer 177662306a36Sopenharmony_ci * 177762306a36Sopenharmony_ci * Attempt to insert an entry into an Index Allocation Buffer. 177862306a36Sopenharmony_ci * If necessary, it will split the buffer. 177962306a36Sopenharmony_ci */ 178062306a36Sopenharmony_cistatic int 178162306a36Sopenharmony_ciindx_insert_into_buffer(struct ntfs_index *indx, struct ntfs_inode *ni, 178262306a36Sopenharmony_ci struct INDEX_ROOT *root, const struct NTFS_DE *new_de, 178362306a36Sopenharmony_ci const void *ctx, int level, struct ntfs_fnd *fnd) 178462306a36Sopenharmony_ci{ 178562306a36Sopenharmony_ci int err; 178662306a36Sopenharmony_ci const struct NTFS_DE *sp; 178762306a36Sopenharmony_ci struct NTFS_DE *e, *de_t, *up_e; 178862306a36Sopenharmony_ci struct indx_node *n2; 178962306a36Sopenharmony_ci struct indx_node *n1 = fnd->nodes[level]; 179062306a36Sopenharmony_ci struct INDEX_HDR *hdr1 = &n1->index->ihdr; 179162306a36Sopenharmony_ci struct INDEX_HDR *hdr2; 179262306a36Sopenharmony_ci u32 to_copy, used, used1; 179362306a36Sopenharmony_ci CLST new_vbn; 179462306a36Sopenharmony_ci __le64 t_vbn, *sub_vbn; 179562306a36Sopenharmony_ci u16 sp_size; 179662306a36Sopenharmony_ci void *hdr1_saved = NULL; 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci /* Try the most easy case. */ 179962306a36Sopenharmony_ci e = fnd->level - 1 == level ? fnd->de[level] : NULL; 180062306a36Sopenharmony_ci e = hdr_insert_de(indx, hdr1, new_de, e, ctx); 180162306a36Sopenharmony_ci fnd->de[level] = e; 180262306a36Sopenharmony_ci if (e) { 180362306a36Sopenharmony_ci /* Just write updated index into disk. */ 180462306a36Sopenharmony_ci indx_write(indx, ni, n1, 0); 180562306a36Sopenharmony_ci return 0; 180662306a36Sopenharmony_ci } 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci /* 180962306a36Sopenharmony_ci * No space to insert into buffer. Split it. 181062306a36Sopenharmony_ci * To split we: 181162306a36Sopenharmony_ci * - Save split point ('cause index buffers will be changed) 181262306a36Sopenharmony_ci * - Allocate NewBuffer and copy all entries <= sp into new buffer 181362306a36Sopenharmony_ci * - Remove all entries (sp including) from TargetBuffer 181462306a36Sopenharmony_ci * - Insert NewEntry into left or right buffer (depending on sp <=> 181562306a36Sopenharmony_ci * NewEntry) 181662306a36Sopenharmony_ci * - Insert sp into parent buffer (or root) 181762306a36Sopenharmony_ci * - Make sp a parent for new buffer 181862306a36Sopenharmony_ci */ 181962306a36Sopenharmony_ci sp = hdr_find_split(hdr1); 182062306a36Sopenharmony_ci if (!sp) 182162306a36Sopenharmony_ci return -EINVAL; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci sp_size = le16_to_cpu(sp->size); 182462306a36Sopenharmony_ci up_e = kmalloc(sp_size + sizeof(u64), GFP_NOFS); 182562306a36Sopenharmony_ci if (!up_e) 182662306a36Sopenharmony_ci return -ENOMEM; 182762306a36Sopenharmony_ci memcpy(up_e, sp, sp_size); 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci used1 = le32_to_cpu(hdr1->used); 183062306a36Sopenharmony_ci hdr1_saved = kmemdup(hdr1, used1, GFP_NOFS); 183162306a36Sopenharmony_ci if (!hdr1_saved) { 183262306a36Sopenharmony_ci err = -ENOMEM; 183362306a36Sopenharmony_ci goto out; 183462306a36Sopenharmony_ci } 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if (!hdr1->flags) { 183762306a36Sopenharmony_ci up_e->flags |= NTFS_IE_HAS_SUBNODES; 183862306a36Sopenharmony_ci up_e->size = cpu_to_le16(sp_size + sizeof(u64)); 183962306a36Sopenharmony_ci sub_vbn = NULL; 184062306a36Sopenharmony_ci } else { 184162306a36Sopenharmony_ci t_vbn = de_get_vbn_le(up_e); 184262306a36Sopenharmony_ci sub_vbn = &t_vbn; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci /* Allocate on disk a new index allocation buffer. */ 184662306a36Sopenharmony_ci err = indx_add_allocate(indx, ni, &new_vbn); 184762306a36Sopenharmony_ci if (err) 184862306a36Sopenharmony_ci goto out; 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci /* Allocate and format memory a new index buffer. */ 185162306a36Sopenharmony_ci n2 = indx_new(indx, ni, new_vbn, sub_vbn); 185262306a36Sopenharmony_ci if (IS_ERR(n2)) { 185362306a36Sopenharmony_ci err = PTR_ERR(n2); 185462306a36Sopenharmony_ci goto out; 185562306a36Sopenharmony_ci } 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci hdr2 = &n2->index->ihdr; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci /* Make sp a parent for new buffer. */ 186062306a36Sopenharmony_ci de_set_vbn(up_e, new_vbn); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci /* Copy all the entries <= sp into the new buffer. */ 186362306a36Sopenharmony_ci de_t = hdr_first_de(hdr1); 186462306a36Sopenharmony_ci to_copy = PtrOffset(de_t, sp); 186562306a36Sopenharmony_ci hdr_insert_head(hdr2, de_t, to_copy); 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci /* Remove all entries (sp including) from hdr1. */ 186862306a36Sopenharmony_ci used = used1 - to_copy - sp_size; 186962306a36Sopenharmony_ci memmove(de_t, Add2Ptr(sp, sp_size), used - le32_to_cpu(hdr1->de_off)); 187062306a36Sopenharmony_ci hdr1->used = cpu_to_le32(used); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci /* 187362306a36Sopenharmony_ci * Insert new entry into left or right buffer 187462306a36Sopenharmony_ci * (depending on sp <=> new_de). 187562306a36Sopenharmony_ci */ 187662306a36Sopenharmony_ci hdr_insert_de(indx, 187762306a36Sopenharmony_ci (*indx->cmp)(new_de + 1, le16_to_cpu(new_de->key_size), 187862306a36Sopenharmony_ci up_e + 1, le16_to_cpu(up_e->key_size), 187962306a36Sopenharmony_ci ctx) < 0 ? 188062306a36Sopenharmony_ci hdr2 : 188162306a36Sopenharmony_ci hdr1, 188262306a36Sopenharmony_ci new_de, NULL, ctx); 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci indx_mark_used(indx, ni, new_vbn >> indx->idx2vbn_bits); 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci indx_write(indx, ni, n1, 0); 188762306a36Sopenharmony_ci indx_write(indx, ni, n2, 0); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci put_indx_node(n2); 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci /* 189262306a36Sopenharmony_ci * We've finished splitting everybody, so we are ready to 189362306a36Sopenharmony_ci * insert the promoted entry into the parent. 189462306a36Sopenharmony_ci */ 189562306a36Sopenharmony_ci if (!level) { 189662306a36Sopenharmony_ci /* Insert in root. */ 189762306a36Sopenharmony_ci err = indx_insert_into_root(indx, ni, up_e, NULL, ctx, fnd, 0); 189862306a36Sopenharmony_ci } else { 189962306a36Sopenharmony_ci /* 190062306a36Sopenharmony_ci * The target buffer's parent is another index buffer. 190162306a36Sopenharmony_ci * TODO: Remove recursion. 190262306a36Sopenharmony_ci */ 190362306a36Sopenharmony_ci err = indx_insert_into_buffer(indx, ni, root, up_e, ctx, 190462306a36Sopenharmony_ci level - 1, fnd); 190562306a36Sopenharmony_ci } 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci if (err) { 190862306a36Sopenharmony_ci /* 190962306a36Sopenharmony_ci * Undo critical operations. 191062306a36Sopenharmony_ci */ 191162306a36Sopenharmony_ci indx_mark_free(indx, ni, new_vbn >> indx->idx2vbn_bits); 191262306a36Sopenharmony_ci memcpy(hdr1, hdr1_saved, used1); 191362306a36Sopenharmony_ci indx_write(indx, ni, n1, 0); 191462306a36Sopenharmony_ci } 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ciout: 191762306a36Sopenharmony_ci kfree(up_e); 191862306a36Sopenharmony_ci kfree(hdr1_saved); 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci return err; 192162306a36Sopenharmony_ci} 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci/* 192462306a36Sopenharmony_ci * indx_insert_entry - Insert new entry into index. 192562306a36Sopenharmony_ci * 192662306a36Sopenharmony_ci * @undo - True if we undoing previous remove. 192762306a36Sopenharmony_ci */ 192862306a36Sopenharmony_ciint indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni, 192962306a36Sopenharmony_ci const struct NTFS_DE *new_de, const void *ctx, 193062306a36Sopenharmony_ci struct ntfs_fnd *fnd, bool undo) 193162306a36Sopenharmony_ci{ 193262306a36Sopenharmony_ci int err; 193362306a36Sopenharmony_ci int diff; 193462306a36Sopenharmony_ci struct NTFS_DE *e; 193562306a36Sopenharmony_ci struct ntfs_fnd *fnd_a = NULL; 193662306a36Sopenharmony_ci struct INDEX_ROOT *root; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci if (!fnd) { 193962306a36Sopenharmony_ci fnd_a = fnd_get(); 194062306a36Sopenharmony_ci if (!fnd_a) { 194162306a36Sopenharmony_ci err = -ENOMEM; 194262306a36Sopenharmony_ci goto out1; 194362306a36Sopenharmony_ci } 194462306a36Sopenharmony_ci fnd = fnd_a; 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci root = indx_get_root(indx, ni, NULL, NULL); 194862306a36Sopenharmony_ci if (!root) { 194962306a36Sopenharmony_ci err = -EINVAL; 195062306a36Sopenharmony_ci goto out; 195162306a36Sopenharmony_ci } 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci if (fnd_is_empty(fnd)) { 195462306a36Sopenharmony_ci /* 195562306a36Sopenharmony_ci * Find the spot the tree where we want to 195662306a36Sopenharmony_ci * insert the new entry. 195762306a36Sopenharmony_ci */ 195862306a36Sopenharmony_ci err = indx_find(indx, ni, root, new_de + 1, 195962306a36Sopenharmony_ci le16_to_cpu(new_de->key_size), ctx, &diff, &e, 196062306a36Sopenharmony_ci fnd); 196162306a36Sopenharmony_ci if (err) 196262306a36Sopenharmony_ci goto out; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci if (!diff) { 196562306a36Sopenharmony_ci err = -EEXIST; 196662306a36Sopenharmony_ci goto out; 196762306a36Sopenharmony_ci } 196862306a36Sopenharmony_ci } 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci if (!fnd->level) { 197162306a36Sopenharmony_ci /* 197262306a36Sopenharmony_ci * The root is also a leaf, so we'll insert the 197362306a36Sopenharmony_ci * new entry into it. 197462306a36Sopenharmony_ci */ 197562306a36Sopenharmony_ci err = indx_insert_into_root(indx, ni, new_de, fnd->root_de, ctx, 197662306a36Sopenharmony_ci fnd, undo); 197762306a36Sopenharmony_ci } else { 197862306a36Sopenharmony_ci /* 197962306a36Sopenharmony_ci * Found a leaf buffer, so we'll insert the new entry into it. 198062306a36Sopenharmony_ci */ 198162306a36Sopenharmony_ci err = indx_insert_into_buffer(indx, ni, root, new_de, ctx, 198262306a36Sopenharmony_ci fnd->level - 1, fnd); 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ciout: 198662306a36Sopenharmony_ci fnd_put(fnd_a); 198762306a36Sopenharmony_ciout1: 198862306a36Sopenharmony_ci return err; 198962306a36Sopenharmony_ci} 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci/* 199262306a36Sopenharmony_ci * indx_find_buffer - Locate a buffer from the tree. 199362306a36Sopenharmony_ci */ 199462306a36Sopenharmony_cistatic struct indx_node *indx_find_buffer(struct ntfs_index *indx, 199562306a36Sopenharmony_ci struct ntfs_inode *ni, 199662306a36Sopenharmony_ci const struct INDEX_ROOT *root, 199762306a36Sopenharmony_ci __le64 vbn, struct indx_node *n) 199862306a36Sopenharmony_ci{ 199962306a36Sopenharmony_ci int err; 200062306a36Sopenharmony_ci const struct NTFS_DE *e; 200162306a36Sopenharmony_ci struct indx_node *r; 200262306a36Sopenharmony_ci const struct INDEX_HDR *hdr = n ? &n->index->ihdr : &root->ihdr; 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci /* Step 1: Scan one level. */ 200562306a36Sopenharmony_ci for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) { 200662306a36Sopenharmony_ci if (!e) 200762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ci if (de_has_vcn(e) && vbn == de_get_vbn_le(e)) 201062306a36Sopenharmony_ci return n; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci if (de_is_last(e)) 201362306a36Sopenharmony_ci break; 201462306a36Sopenharmony_ci } 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci /* Step2: Do recursion. */ 201762306a36Sopenharmony_ci e = Add2Ptr(hdr, le32_to_cpu(hdr->de_off)); 201862306a36Sopenharmony_ci for (;;) { 201962306a36Sopenharmony_ci if (de_has_vcn_ex(e)) { 202062306a36Sopenharmony_ci err = indx_read(indx, ni, de_get_vbn(e), &n); 202162306a36Sopenharmony_ci if (err) 202262306a36Sopenharmony_ci return ERR_PTR(err); 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci r = indx_find_buffer(indx, ni, root, vbn, n); 202562306a36Sopenharmony_ci if (r) 202662306a36Sopenharmony_ci return r; 202762306a36Sopenharmony_ci } 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci if (de_is_last(e)) 203062306a36Sopenharmony_ci break; 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci e = Add2Ptr(e, le16_to_cpu(e->size)); 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci return NULL; 203662306a36Sopenharmony_ci} 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci/* 203962306a36Sopenharmony_ci * indx_shrink - Deallocate unused tail indexes. 204062306a36Sopenharmony_ci */ 204162306a36Sopenharmony_cistatic int indx_shrink(struct ntfs_index *indx, struct ntfs_inode *ni, 204262306a36Sopenharmony_ci size_t bit) 204362306a36Sopenharmony_ci{ 204462306a36Sopenharmony_ci int err = 0; 204562306a36Sopenharmony_ci u64 bpb, new_data; 204662306a36Sopenharmony_ci size_t nbits; 204762306a36Sopenharmony_ci struct ATTRIB *b; 204862306a36Sopenharmony_ci struct ATTR_LIST_ENTRY *le = NULL; 204962306a36Sopenharmony_ci const struct INDEX_NAMES *in = &s_index_names[indx->type]; 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len, 205262306a36Sopenharmony_ci NULL, NULL); 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci if (!b) 205562306a36Sopenharmony_ci return -ENOENT; 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci if (!b->non_res) { 205862306a36Sopenharmony_ci unsigned long pos; 205962306a36Sopenharmony_ci const unsigned long *bm = resident_data(b); 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci nbits = (size_t)le32_to_cpu(b->res.data_size) * 8; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci if (bit >= nbits) 206462306a36Sopenharmony_ci return 0; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci pos = find_next_bit_le(bm, nbits, bit); 206762306a36Sopenharmony_ci if (pos < nbits) 206862306a36Sopenharmony_ci return 0; 206962306a36Sopenharmony_ci } else { 207062306a36Sopenharmony_ci size_t used = MINUS_ONE_T; 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci nbits = le64_to_cpu(b->nres.data_size) * 8; 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci if (bit >= nbits) 207562306a36Sopenharmony_ci return 0; 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci err = scan_nres_bitmap(ni, b, indx, bit, &scan_for_used, &used); 207862306a36Sopenharmony_ci if (err) 207962306a36Sopenharmony_ci return err; 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci if (used != MINUS_ONE_T) 208262306a36Sopenharmony_ci return 0; 208362306a36Sopenharmony_ci } 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci new_data = (u64)bit << indx->index_bits; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len, 208862306a36Sopenharmony_ci &indx->alloc_run, new_data, &new_data, false, NULL); 208962306a36Sopenharmony_ci if (err) 209062306a36Sopenharmony_ci return err; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci if (in->name == I30_NAME) 209362306a36Sopenharmony_ci i_size_write(&ni->vfs_inode, new_data); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci bpb = bitmap_size(bit); 209662306a36Sopenharmony_ci if (bpb * 8 == nbits) 209762306a36Sopenharmony_ci return 0; 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len, 210062306a36Sopenharmony_ci &indx->bitmap_run, bpb, &bpb, false, NULL); 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci return err; 210362306a36Sopenharmony_ci} 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_cistatic int indx_free_children(struct ntfs_index *indx, struct ntfs_inode *ni, 210662306a36Sopenharmony_ci const struct NTFS_DE *e, bool trim) 210762306a36Sopenharmony_ci{ 210862306a36Sopenharmony_ci int err; 210962306a36Sopenharmony_ci struct indx_node *n = NULL; 211062306a36Sopenharmony_ci struct INDEX_HDR *hdr; 211162306a36Sopenharmony_ci CLST vbn = de_get_vbn(e); 211262306a36Sopenharmony_ci size_t i; 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci err = indx_read(indx, ni, vbn, &n); 211562306a36Sopenharmony_ci if (err) 211662306a36Sopenharmony_ci return err; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci hdr = &n->index->ihdr; 211962306a36Sopenharmony_ci /* First, recurse into the children, if any. */ 212062306a36Sopenharmony_ci if (hdr_has_subnode(hdr)) { 212162306a36Sopenharmony_ci for (e = hdr_first_de(hdr); e; e = hdr_next_de(hdr, e)) { 212262306a36Sopenharmony_ci indx_free_children(indx, ni, e, false); 212362306a36Sopenharmony_ci if (de_is_last(e)) 212462306a36Sopenharmony_ci break; 212562306a36Sopenharmony_ci } 212662306a36Sopenharmony_ci } 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci put_indx_node(n); 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci i = vbn >> indx->idx2vbn_bits; 213162306a36Sopenharmony_ci /* 213262306a36Sopenharmony_ci * We've gotten rid of the children; add this buffer to the free list. 213362306a36Sopenharmony_ci */ 213462306a36Sopenharmony_ci indx_mark_free(indx, ni, i); 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci if (!trim) 213762306a36Sopenharmony_ci return 0; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci /* 214062306a36Sopenharmony_ci * If there are no used indexes after current free index 214162306a36Sopenharmony_ci * then we can truncate allocation and bitmap. 214262306a36Sopenharmony_ci * Use bitmap to estimate the case. 214362306a36Sopenharmony_ci */ 214462306a36Sopenharmony_ci indx_shrink(indx, ni, i + 1); 214562306a36Sopenharmony_ci return 0; 214662306a36Sopenharmony_ci} 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci/* 214962306a36Sopenharmony_ci * indx_get_entry_to_replace 215062306a36Sopenharmony_ci * 215162306a36Sopenharmony_ci * Find a replacement entry for a deleted entry. 215262306a36Sopenharmony_ci * Always returns a node entry: 215362306a36Sopenharmony_ci * NTFS_IE_HAS_SUBNODES is set the flags and the size includes the sub_vcn. 215462306a36Sopenharmony_ci */ 215562306a36Sopenharmony_cistatic int indx_get_entry_to_replace(struct ntfs_index *indx, 215662306a36Sopenharmony_ci struct ntfs_inode *ni, 215762306a36Sopenharmony_ci const struct NTFS_DE *de_next, 215862306a36Sopenharmony_ci struct NTFS_DE **de_to_replace, 215962306a36Sopenharmony_ci struct ntfs_fnd *fnd) 216062306a36Sopenharmony_ci{ 216162306a36Sopenharmony_ci int err; 216262306a36Sopenharmony_ci int level = -1; 216362306a36Sopenharmony_ci CLST vbn; 216462306a36Sopenharmony_ci struct NTFS_DE *e, *te, *re; 216562306a36Sopenharmony_ci struct indx_node *n; 216662306a36Sopenharmony_ci struct INDEX_BUFFER *ib; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci *de_to_replace = NULL; 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci /* Find first leaf entry down from de_next. */ 217162306a36Sopenharmony_ci vbn = de_get_vbn(de_next); 217262306a36Sopenharmony_ci for (;;) { 217362306a36Sopenharmony_ci n = NULL; 217462306a36Sopenharmony_ci err = indx_read(indx, ni, vbn, &n); 217562306a36Sopenharmony_ci if (err) 217662306a36Sopenharmony_ci goto out; 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci e = hdr_first_de(&n->index->ihdr); 217962306a36Sopenharmony_ci fnd_push(fnd, n, e); 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci if (!de_is_last(e)) { 218262306a36Sopenharmony_ci /* 218362306a36Sopenharmony_ci * This buffer is non-empty, so its first entry 218462306a36Sopenharmony_ci * could be used as the replacement entry. 218562306a36Sopenharmony_ci */ 218662306a36Sopenharmony_ci level = fnd->level - 1; 218762306a36Sopenharmony_ci } 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci if (!de_has_vcn(e)) 219062306a36Sopenharmony_ci break; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci /* This buffer is a node. Continue to go down. */ 219362306a36Sopenharmony_ci vbn = de_get_vbn(e); 219462306a36Sopenharmony_ci } 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci if (level == -1) 219762306a36Sopenharmony_ci goto out; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci n = fnd->nodes[level]; 220062306a36Sopenharmony_ci te = hdr_first_de(&n->index->ihdr); 220162306a36Sopenharmony_ci /* Copy the candidate entry into the replacement entry buffer. */ 220262306a36Sopenharmony_ci re = kmalloc(le16_to_cpu(te->size) + sizeof(u64), GFP_NOFS); 220362306a36Sopenharmony_ci if (!re) { 220462306a36Sopenharmony_ci err = -ENOMEM; 220562306a36Sopenharmony_ci goto out; 220662306a36Sopenharmony_ci } 220762306a36Sopenharmony_ci 220862306a36Sopenharmony_ci *de_to_replace = re; 220962306a36Sopenharmony_ci memcpy(re, te, le16_to_cpu(te->size)); 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci if (!de_has_vcn(re)) { 221262306a36Sopenharmony_ci /* 221362306a36Sopenharmony_ci * The replacement entry we found doesn't have a sub_vcn. 221462306a36Sopenharmony_ci * increase its size to hold one. 221562306a36Sopenharmony_ci */ 221662306a36Sopenharmony_ci le16_add_cpu(&re->size, sizeof(u64)); 221762306a36Sopenharmony_ci re->flags |= NTFS_IE_HAS_SUBNODES; 221862306a36Sopenharmony_ci } else { 221962306a36Sopenharmony_ci /* 222062306a36Sopenharmony_ci * The replacement entry we found was a node entry, which 222162306a36Sopenharmony_ci * means that all its child buffers are empty. Return them 222262306a36Sopenharmony_ci * to the free pool. 222362306a36Sopenharmony_ci */ 222462306a36Sopenharmony_ci indx_free_children(indx, ni, te, true); 222562306a36Sopenharmony_ci } 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci /* 222862306a36Sopenharmony_ci * Expunge the replacement entry from its former location, 222962306a36Sopenharmony_ci * and then write that buffer. 223062306a36Sopenharmony_ci */ 223162306a36Sopenharmony_ci ib = n->index; 223262306a36Sopenharmony_ci e = hdr_delete_de(&ib->ihdr, te); 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_ci fnd->de[level] = e; 223562306a36Sopenharmony_ci indx_write(indx, ni, n, 0); 223662306a36Sopenharmony_ci 223762306a36Sopenharmony_ci if (ib_is_leaf(ib) && ib_is_empty(ib)) { 223862306a36Sopenharmony_ci /* An empty leaf. */ 223962306a36Sopenharmony_ci return 0; 224062306a36Sopenharmony_ci } 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ciout: 224362306a36Sopenharmony_ci fnd_clear(fnd); 224462306a36Sopenharmony_ci return err; 224562306a36Sopenharmony_ci} 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci/* 224862306a36Sopenharmony_ci * indx_delete_entry - Delete an entry from the index. 224962306a36Sopenharmony_ci */ 225062306a36Sopenharmony_ciint indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni, 225162306a36Sopenharmony_ci const void *key, u32 key_len, const void *ctx) 225262306a36Sopenharmony_ci{ 225362306a36Sopenharmony_ci int err, diff; 225462306a36Sopenharmony_ci struct INDEX_ROOT *root; 225562306a36Sopenharmony_ci struct INDEX_HDR *hdr; 225662306a36Sopenharmony_ci struct ntfs_fnd *fnd, *fnd2; 225762306a36Sopenharmony_ci struct INDEX_BUFFER *ib; 225862306a36Sopenharmony_ci struct NTFS_DE *e, *re, *next, *prev, *me; 225962306a36Sopenharmony_ci struct indx_node *n, *n2d = NULL; 226062306a36Sopenharmony_ci __le64 sub_vbn; 226162306a36Sopenharmony_ci int level, level2; 226262306a36Sopenharmony_ci struct ATTRIB *attr; 226362306a36Sopenharmony_ci struct mft_inode *mi; 226462306a36Sopenharmony_ci u32 e_size, root_size, new_root_size; 226562306a36Sopenharmony_ci size_t trim_bit; 226662306a36Sopenharmony_ci const struct INDEX_NAMES *in; 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci fnd = fnd_get(); 226962306a36Sopenharmony_ci if (!fnd) { 227062306a36Sopenharmony_ci err = -ENOMEM; 227162306a36Sopenharmony_ci goto out2; 227262306a36Sopenharmony_ci } 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci fnd2 = fnd_get(); 227562306a36Sopenharmony_ci if (!fnd2) { 227662306a36Sopenharmony_ci err = -ENOMEM; 227762306a36Sopenharmony_ci goto out1; 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci root = indx_get_root(indx, ni, &attr, &mi); 228162306a36Sopenharmony_ci if (!root) { 228262306a36Sopenharmony_ci err = -EINVAL; 228362306a36Sopenharmony_ci goto out; 228462306a36Sopenharmony_ci } 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci /* Locate the entry to remove. */ 228762306a36Sopenharmony_ci err = indx_find(indx, ni, root, key, key_len, ctx, &diff, &e, fnd); 228862306a36Sopenharmony_ci if (err) 228962306a36Sopenharmony_ci goto out; 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci if (!e || diff) { 229262306a36Sopenharmony_ci err = -ENOENT; 229362306a36Sopenharmony_ci goto out; 229462306a36Sopenharmony_ci } 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci level = fnd->level; 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci if (level) { 229962306a36Sopenharmony_ci n = fnd->nodes[level - 1]; 230062306a36Sopenharmony_ci e = fnd->de[level - 1]; 230162306a36Sopenharmony_ci ib = n->index; 230262306a36Sopenharmony_ci hdr = &ib->ihdr; 230362306a36Sopenharmony_ci } else { 230462306a36Sopenharmony_ci hdr = &root->ihdr; 230562306a36Sopenharmony_ci e = fnd->root_de; 230662306a36Sopenharmony_ci n = NULL; 230762306a36Sopenharmony_ci } 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci e_size = le16_to_cpu(e->size); 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci if (!de_has_vcn_ex(e)) { 231262306a36Sopenharmony_ci /* The entry to delete is a leaf, so we can just rip it out. */ 231362306a36Sopenharmony_ci hdr_delete_de(hdr, e); 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci if (!level) { 231662306a36Sopenharmony_ci hdr->total = hdr->used; 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci /* Shrink resident root attribute. */ 231962306a36Sopenharmony_ci mi_resize_attr(mi, attr, 0 - e_size); 232062306a36Sopenharmony_ci goto out; 232162306a36Sopenharmony_ci } 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci indx_write(indx, ni, n, 0); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci /* 232662306a36Sopenharmony_ci * Check to see if removing that entry made 232762306a36Sopenharmony_ci * the leaf empty. 232862306a36Sopenharmony_ci */ 232962306a36Sopenharmony_ci if (ib_is_leaf(ib) && ib_is_empty(ib)) { 233062306a36Sopenharmony_ci fnd_pop(fnd); 233162306a36Sopenharmony_ci fnd_push(fnd2, n, e); 233262306a36Sopenharmony_ci } 233362306a36Sopenharmony_ci } else { 233462306a36Sopenharmony_ci /* 233562306a36Sopenharmony_ci * The entry we wish to delete is a node buffer, so we 233662306a36Sopenharmony_ci * have to find a replacement for it. 233762306a36Sopenharmony_ci */ 233862306a36Sopenharmony_ci next = de_get_next(e); 233962306a36Sopenharmony_ci 234062306a36Sopenharmony_ci err = indx_get_entry_to_replace(indx, ni, next, &re, fnd2); 234162306a36Sopenharmony_ci if (err) 234262306a36Sopenharmony_ci goto out; 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci if (re) { 234562306a36Sopenharmony_ci de_set_vbn_le(re, de_get_vbn_le(e)); 234662306a36Sopenharmony_ci hdr_delete_de(hdr, e); 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_ci err = level ? indx_insert_into_buffer(indx, ni, root, 234962306a36Sopenharmony_ci re, ctx, 235062306a36Sopenharmony_ci fnd->level - 1, 235162306a36Sopenharmony_ci fnd) : 235262306a36Sopenharmony_ci indx_insert_into_root(indx, ni, re, e, 235362306a36Sopenharmony_ci ctx, fnd, 0); 235462306a36Sopenharmony_ci kfree(re); 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci if (err) 235762306a36Sopenharmony_ci goto out; 235862306a36Sopenharmony_ci } else { 235962306a36Sopenharmony_ci /* 236062306a36Sopenharmony_ci * There is no replacement for the current entry. 236162306a36Sopenharmony_ci * This means that the subtree rooted at its node 236262306a36Sopenharmony_ci * is empty, and can be deleted, which turn means 236362306a36Sopenharmony_ci * that the node can just inherit the deleted 236462306a36Sopenharmony_ci * entry sub_vcn. 236562306a36Sopenharmony_ci */ 236662306a36Sopenharmony_ci indx_free_children(indx, ni, next, true); 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci de_set_vbn_le(next, de_get_vbn_le(e)); 236962306a36Sopenharmony_ci hdr_delete_de(hdr, e); 237062306a36Sopenharmony_ci if (level) { 237162306a36Sopenharmony_ci indx_write(indx, ni, n, 0); 237262306a36Sopenharmony_ci } else { 237362306a36Sopenharmony_ci hdr->total = hdr->used; 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci /* Shrink resident root attribute. */ 237662306a36Sopenharmony_ci mi_resize_attr(mi, attr, 0 - e_size); 237762306a36Sopenharmony_ci } 237862306a36Sopenharmony_ci } 237962306a36Sopenharmony_ci } 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci /* Delete a branch of tree. */ 238262306a36Sopenharmony_ci if (!fnd2 || !fnd2->level) 238362306a36Sopenharmony_ci goto out; 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ci /* Reinit root 'cause it can be changed. */ 238662306a36Sopenharmony_ci root = indx_get_root(indx, ni, &attr, &mi); 238762306a36Sopenharmony_ci if (!root) { 238862306a36Sopenharmony_ci err = -EINVAL; 238962306a36Sopenharmony_ci goto out; 239062306a36Sopenharmony_ci } 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci n2d = NULL; 239362306a36Sopenharmony_ci sub_vbn = fnd2->nodes[0]->index->vbn; 239462306a36Sopenharmony_ci level2 = 0; 239562306a36Sopenharmony_ci level = fnd->level; 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci hdr = level ? &fnd->nodes[level - 1]->index->ihdr : &root->ihdr; 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci /* Scan current level. */ 240062306a36Sopenharmony_ci for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) { 240162306a36Sopenharmony_ci if (!e) { 240262306a36Sopenharmony_ci err = -EINVAL; 240362306a36Sopenharmony_ci goto out; 240462306a36Sopenharmony_ci } 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci if (de_has_vcn(e) && sub_vbn == de_get_vbn_le(e)) 240762306a36Sopenharmony_ci break; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (de_is_last(e)) { 241062306a36Sopenharmony_ci e = NULL; 241162306a36Sopenharmony_ci break; 241262306a36Sopenharmony_ci } 241362306a36Sopenharmony_ci } 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_ci if (!e) { 241662306a36Sopenharmony_ci /* Do slow search from root. */ 241762306a36Sopenharmony_ci struct indx_node *in; 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ci fnd_clear(fnd); 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci in = indx_find_buffer(indx, ni, root, sub_vbn, NULL); 242262306a36Sopenharmony_ci if (IS_ERR(in)) { 242362306a36Sopenharmony_ci err = PTR_ERR(in); 242462306a36Sopenharmony_ci goto out; 242562306a36Sopenharmony_ci } 242662306a36Sopenharmony_ci 242762306a36Sopenharmony_ci if (in) 242862306a36Sopenharmony_ci fnd_push(fnd, in, NULL); 242962306a36Sopenharmony_ci } 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci /* Merge fnd2 -> fnd. */ 243262306a36Sopenharmony_ci for (level = 0; level < fnd2->level; level++) { 243362306a36Sopenharmony_ci fnd_push(fnd, fnd2->nodes[level], fnd2->de[level]); 243462306a36Sopenharmony_ci fnd2->nodes[level] = NULL; 243562306a36Sopenharmony_ci } 243662306a36Sopenharmony_ci fnd2->level = 0; 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci hdr = NULL; 243962306a36Sopenharmony_ci for (level = fnd->level; level; level--) { 244062306a36Sopenharmony_ci struct indx_node *in = fnd->nodes[level - 1]; 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci ib = in->index; 244362306a36Sopenharmony_ci if (ib_is_empty(ib)) { 244462306a36Sopenharmony_ci sub_vbn = ib->vbn; 244562306a36Sopenharmony_ci } else { 244662306a36Sopenharmony_ci hdr = &ib->ihdr; 244762306a36Sopenharmony_ci n2d = in; 244862306a36Sopenharmony_ci level2 = level; 244962306a36Sopenharmony_ci break; 245062306a36Sopenharmony_ci } 245162306a36Sopenharmony_ci } 245262306a36Sopenharmony_ci 245362306a36Sopenharmony_ci if (!hdr) 245462306a36Sopenharmony_ci hdr = &root->ihdr; 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci e = hdr_first_de(hdr); 245762306a36Sopenharmony_ci if (!e) { 245862306a36Sopenharmony_ci err = -EINVAL; 245962306a36Sopenharmony_ci goto out; 246062306a36Sopenharmony_ci } 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci if (hdr != &root->ihdr || !de_is_last(e)) { 246362306a36Sopenharmony_ci prev = NULL; 246462306a36Sopenharmony_ci while (!de_is_last(e)) { 246562306a36Sopenharmony_ci if (de_has_vcn(e) && sub_vbn == de_get_vbn_le(e)) 246662306a36Sopenharmony_ci break; 246762306a36Sopenharmony_ci prev = e; 246862306a36Sopenharmony_ci e = hdr_next_de(hdr, e); 246962306a36Sopenharmony_ci if (!e) { 247062306a36Sopenharmony_ci err = -EINVAL; 247162306a36Sopenharmony_ci goto out; 247262306a36Sopenharmony_ci } 247362306a36Sopenharmony_ci } 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci if (sub_vbn != de_get_vbn_le(e)) { 247662306a36Sopenharmony_ci /* 247762306a36Sopenharmony_ci * Didn't find the parent entry, although this buffer 247862306a36Sopenharmony_ci * is the parent trail. Something is corrupt. 247962306a36Sopenharmony_ci */ 248062306a36Sopenharmony_ci err = -EINVAL; 248162306a36Sopenharmony_ci goto out; 248262306a36Sopenharmony_ci } 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci if (de_is_last(e)) { 248562306a36Sopenharmony_ci /* 248662306a36Sopenharmony_ci * Since we can't remove the end entry, we'll remove 248762306a36Sopenharmony_ci * its predecessor instead. This means we have to 248862306a36Sopenharmony_ci * transfer the predecessor's sub_vcn to the end entry. 248962306a36Sopenharmony_ci * Note: This index block is not empty, so the 249062306a36Sopenharmony_ci * predecessor must exist. 249162306a36Sopenharmony_ci */ 249262306a36Sopenharmony_ci if (!prev) { 249362306a36Sopenharmony_ci err = -EINVAL; 249462306a36Sopenharmony_ci goto out; 249562306a36Sopenharmony_ci } 249662306a36Sopenharmony_ci 249762306a36Sopenharmony_ci if (de_has_vcn(prev)) { 249862306a36Sopenharmony_ci de_set_vbn_le(e, de_get_vbn_le(prev)); 249962306a36Sopenharmony_ci } else if (de_has_vcn(e)) { 250062306a36Sopenharmony_ci le16_sub_cpu(&e->size, sizeof(u64)); 250162306a36Sopenharmony_ci e->flags &= ~NTFS_IE_HAS_SUBNODES; 250262306a36Sopenharmony_ci le32_sub_cpu(&hdr->used, sizeof(u64)); 250362306a36Sopenharmony_ci } 250462306a36Sopenharmony_ci e = prev; 250562306a36Sopenharmony_ci } 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci /* 250862306a36Sopenharmony_ci * Copy the current entry into a temporary buffer (stripping 250962306a36Sopenharmony_ci * off its down-pointer, if any) and delete it from the current 251062306a36Sopenharmony_ci * buffer or root, as appropriate. 251162306a36Sopenharmony_ci */ 251262306a36Sopenharmony_ci e_size = le16_to_cpu(e->size); 251362306a36Sopenharmony_ci me = kmemdup(e, e_size, GFP_NOFS); 251462306a36Sopenharmony_ci if (!me) { 251562306a36Sopenharmony_ci err = -ENOMEM; 251662306a36Sopenharmony_ci goto out; 251762306a36Sopenharmony_ci } 251862306a36Sopenharmony_ci 251962306a36Sopenharmony_ci if (de_has_vcn(me)) { 252062306a36Sopenharmony_ci me->flags &= ~NTFS_IE_HAS_SUBNODES; 252162306a36Sopenharmony_ci le16_sub_cpu(&me->size, sizeof(u64)); 252262306a36Sopenharmony_ci } 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci hdr_delete_de(hdr, e); 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci if (hdr == &root->ihdr) { 252762306a36Sopenharmony_ci level = 0; 252862306a36Sopenharmony_ci hdr->total = hdr->used; 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci /* Shrink resident root attribute. */ 253162306a36Sopenharmony_ci mi_resize_attr(mi, attr, 0 - e_size); 253262306a36Sopenharmony_ci } else { 253362306a36Sopenharmony_ci indx_write(indx, ni, n2d, 0); 253462306a36Sopenharmony_ci level = level2; 253562306a36Sopenharmony_ci } 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci /* Mark unused buffers as free. */ 253862306a36Sopenharmony_ci trim_bit = -1; 253962306a36Sopenharmony_ci for (; level < fnd->level; level++) { 254062306a36Sopenharmony_ci ib = fnd->nodes[level]->index; 254162306a36Sopenharmony_ci if (ib_is_empty(ib)) { 254262306a36Sopenharmony_ci size_t k = le64_to_cpu(ib->vbn) >> 254362306a36Sopenharmony_ci indx->idx2vbn_bits; 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci indx_mark_free(indx, ni, k); 254662306a36Sopenharmony_ci if (k < trim_bit) 254762306a36Sopenharmony_ci trim_bit = k; 254862306a36Sopenharmony_ci } 254962306a36Sopenharmony_ci } 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci fnd_clear(fnd); 255262306a36Sopenharmony_ci /*fnd->root_de = NULL;*/ 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci /* 255562306a36Sopenharmony_ci * Re-insert the entry into the tree. 255662306a36Sopenharmony_ci * Find the spot the tree where we want to insert the new entry. 255762306a36Sopenharmony_ci */ 255862306a36Sopenharmony_ci err = indx_insert_entry(indx, ni, me, ctx, fnd, 0); 255962306a36Sopenharmony_ci kfree(me); 256062306a36Sopenharmony_ci if (err) 256162306a36Sopenharmony_ci goto out; 256262306a36Sopenharmony_ci 256362306a36Sopenharmony_ci if (trim_bit != -1) 256462306a36Sopenharmony_ci indx_shrink(indx, ni, trim_bit); 256562306a36Sopenharmony_ci } else { 256662306a36Sopenharmony_ci /* 256762306a36Sopenharmony_ci * This tree needs to be collapsed down to an empty root. 256862306a36Sopenharmony_ci * Recreate the index root as an empty leaf and free all 256962306a36Sopenharmony_ci * the bits the index allocation bitmap. 257062306a36Sopenharmony_ci */ 257162306a36Sopenharmony_ci fnd_clear(fnd); 257262306a36Sopenharmony_ci fnd_clear(fnd2); 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci in = &s_index_names[indx->type]; 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len, 257762306a36Sopenharmony_ci &indx->alloc_run, 0, NULL, false, NULL); 257862306a36Sopenharmony_ci if (in->name == I30_NAME) 257962306a36Sopenharmony_ci i_size_write(&ni->vfs_inode, 0); 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci err = ni_remove_attr(ni, ATTR_ALLOC, in->name, in->name_len, 258262306a36Sopenharmony_ci false, NULL); 258362306a36Sopenharmony_ci run_close(&indx->alloc_run); 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len, 258662306a36Sopenharmony_ci &indx->bitmap_run, 0, NULL, false, NULL); 258762306a36Sopenharmony_ci err = ni_remove_attr(ni, ATTR_BITMAP, in->name, in->name_len, 258862306a36Sopenharmony_ci false, NULL); 258962306a36Sopenharmony_ci run_close(&indx->bitmap_run); 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci root = indx_get_root(indx, ni, &attr, &mi); 259262306a36Sopenharmony_ci if (!root) { 259362306a36Sopenharmony_ci err = -EINVAL; 259462306a36Sopenharmony_ci goto out; 259562306a36Sopenharmony_ci } 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci root_size = le32_to_cpu(attr->res.data_size); 259862306a36Sopenharmony_ci new_root_size = 259962306a36Sopenharmony_ci sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE); 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_ci if (new_root_size != root_size && 260262306a36Sopenharmony_ci !mi_resize_attr(mi, attr, new_root_size - root_size)) { 260362306a36Sopenharmony_ci err = -EINVAL; 260462306a36Sopenharmony_ci goto out; 260562306a36Sopenharmony_ci } 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ci /* Fill first entry. */ 260862306a36Sopenharmony_ci e = (struct NTFS_DE *)(root + 1); 260962306a36Sopenharmony_ci e->ref.low = 0; 261062306a36Sopenharmony_ci e->ref.high = 0; 261162306a36Sopenharmony_ci e->ref.seq = 0; 261262306a36Sopenharmony_ci e->size = cpu_to_le16(sizeof(struct NTFS_DE)); 261362306a36Sopenharmony_ci e->flags = NTFS_IE_LAST; // 0x02 261462306a36Sopenharmony_ci e->key_size = 0; 261562306a36Sopenharmony_ci e->res = 0; 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ci hdr = &root->ihdr; 261862306a36Sopenharmony_ci hdr->flags = 0; 261962306a36Sopenharmony_ci hdr->used = hdr->total = cpu_to_le32( 262062306a36Sopenharmony_ci new_root_size - offsetof(struct INDEX_ROOT, ihdr)); 262162306a36Sopenharmony_ci mi->dirty = true; 262262306a36Sopenharmony_ci } 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ciout: 262562306a36Sopenharmony_ci fnd_put(fnd2); 262662306a36Sopenharmony_ciout1: 262762306a36Sopenharmony_ci fnd_put(fnd); 262862306a36Sopenharmony_ciout2: 262962306a36Sopenharmony_ci return err; 263062306a36Sopenharmony_ci} 263162306a36Sopenharmony_ci 263262306a36Sopenharmony_ci/* 263362306a36Sopenharmony_ci * Update duplicated information in directory entry 263462306a36Sopenharmony_ci * 'dup' - info from MFT record 263562306a36Sopenharmony_ci */ 263662306a36Sopenharmony_ciint indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi, 263762306a36Sopenharmony_ci const struct ATTR_FILE_NAME *fname, 263862306a36Sopenharmony_ci const struct NTFS_DUP_INFO *dup, int sync) 263962306a36Sopenharmony_ci{ 264062306a36Sopenharmony_ci int err, diff; 264162306a36Sopenharmony_ci struct NTFS_DE *e = NULL; 264262306a36Sopenharmony_ci struct ATTR_FILE_NAME *e_fname; 264362306a36Sopenharmony_ci struct ntfs_fnd *fnd; 264462306a36Sopenharmony_ci struct INDEX_ROOT *root; 264562306a36Sopenharmony_ci struct mft_inode *mi; 264662306a36Sopenharmony_ci struct ntfs_index *indx = &ni->dir; 264762306a36Sopenharmony_ci 264862306a36Sopenharmony_ci fnd = fnd_get(); 264962306a36Sopenharmony_ci if (!fnd) 265062306a36Sopenharmony_ci return -ENOMEM; 265162306a36Sopenharmony_ci 265262306a36Sopenharmony_ci root = indx_get_root(indx, ni, NULL, &mi); 265362306a36Sopenharmony_ci if (!root) { 265462306a36Sopenharmony_ci err = -EINVAL; 265562306a36Sopenharmony_ci goto out; 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci /* Find entry in directory. */ 265962306a36Sopenharmony_ci err = indx_find(indx, ni, root, fname, fname_full_size(fname), sbi, 266062306a36Sopenharmony_ci &diff, &e, fnd); 266162306a36Sopenharmony_ci if (err) 266262306a36Sopenharmony_ci goto out; 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci if (!e) { 266562306a36Sopenharmony_ci err = -EINVAL; 266662306a36Sopenharmony_ci goto out; 266762306a36Sopenharmony_ci } 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci if (diff) { 267062306a36Sopenharmony_ci err = -EINVAL; 267162306a36Sopenharmony_ci goto out; 267262306a36Sopenharmony_ci } 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci e_fname = (struct ATTR_FILE_NAME *)(e + 1); 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci if (!memcmp(&e_fname->dup, dup, sizeof(*dup))) { 267762306a36Sopenharmony_ci /* 267862306a36Sopenharmony_ci * Nothing to update in index! Try to avoid this call. 267962306a36Sopenharmony_ci */ 268062306a36Sopenharmony_ci goto out; 268162306a36Sopenharmony_ci } 268262306a36Sopenharmony_ci 268362306a36Sopenharmony_ci memcpy(&e_fname->dup, dup, sizeof(*dup)); 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_ci if (fnd->level) { 268662306a36Sopenharmony_ci /* Directory entry in index. */ 268762306a36Sopenharmony_ci err = indx_write(indx, ni, fnd->nodes[fnd->level - 1], sync); 268862306a36Sopenharmony_ci } else { 268962306a36Sopenharmony_ci /* Directory entry in directory MFT record. */ 269062306a36Sopenharmony_ci mi->dirty = true; 269162306a36Sopenharmony_ci if (sync) 269262306a36Sopenharmony_ci err = mi_write(mi, 1); 269362306a36Sopenharmony_ci else 269462306a36Sopenharmony_ci mark_inode_dirty(&ni->vfs_inode); 269562306a36Sopenharmony_ci } 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ciout: 269862306a36Sopenharmony_ci fnd_put(fnd); 269962306a36Sopenharmony_ci return err; 270062306a36Sopenharmony_ci} 2701