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