162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * linux/fs/ext4/xattr.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Fix by Harrison Xing <harrison@mountainviewdata.com>.
862306a36Sopenharmony_ci * Ext4 code with a lot of help from Eric Jarman <ejarman@acm.org>.
962306a36Sopenharmony_ci * Extended attributes for symlinks and special files added per
1062306a36Sopenharmony_ci *  suggestion of Luka Renko <luka.renko@hermes.si>.
1162306a36Sopenharmony_ci * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
1262306a36Sopenharmony_ci *  Red Hat Inc.
1362306a36Sopenharmony_ci * ea-in-inode support by Alex Tomas <alex@clusterfs.com> aka bzzz
1462306a36Sopenharmony_ci *  and Andreas Gruenbacher <agruen@suse.de>.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Extended attributes are stored directly in inodes (on file systems with
1962306a36Sopenharmony_ci * inodes bigger than 128 bytes) and on additional disk blocks. The i_file_acl
2062306a36Sopenharmony_ci * field contains the block number if an inode uses an additional block. All
2162306a36Sopenharmony_ci * attributes must fit in the inode and one additional block. Blocks that
2262306a36Sopenharmony_ci * contain the identical set of attributes may be shared among several inodes.
2362306a36Sopenharmony_ci * Identical blocks are detected by keeping a cache of blocks that have
2462306a36Sopenharmony_ci * recently been accessed.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * The attributes in inodes and on blocks have a different header; the entries
2762306a36Sopenharmony_ci * are stored in the same format:
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci *   +------------------+
3062306a36Sopenharmony_ci *   | header           |
3162306a36Sopenharmony_ci *   | entry 1          | |
3262306a36Sopenharmony_ci *   | entry 2          | | growing downwards
3362306a36Sopenharmony_ci *   | entry 3          | v
3462306a36Sopenharmony_ci *   | four null bytes  |
3562306a36Sopenharmony_ci *   | . . .            |
3662306a36Sopenharmony_ci *   | value 1          | ^
3762306a36Sopenharmony_ci *   | value 3          | | growing upwards
3862306a36Sopenharmony_ci *   | value 2          | |
3962306a36Sopenharmony_ci *   +------------------+
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * The header is followed by multiple entry descriptors. In disk blocks, the
4262306a36Sopenharmony_ci * entry descriptors are kept sorted. In inodes, they are unsorted. The
4362306a36Sopenharmony_ci * attribute values are aligned to the end of the block in no specific order.
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * Locking strategy
4662306a36Sopenharmony_ci * ----------------
4762306a36Sopenharmony_ci * EXT4_I(inode)->i_file_acl is protected by EXT4_I(inode)->xattr_sem.
4862306a36Sopenharmony_ci * EA blocks are only changed if they are exclusive to an inode, so
4962306a36Sopenharmony_ci * holding xattr_sem also means that nothing but the EA block's reference
5062306a36Sopenharmony_ci * count can change. Multiple writers to the same block are synchronized
5162306a36Sopenharmony_ci * by the buffer lock.
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#include <linux/init.h>
5562306a36Sopenharmony_ci#include <linux/fs.h>
5662306a36Sopenharmony_ci#include <linux/slab.h>
5762306a36Sopenharmony_ci#include <linux/mbcache.h>
5862306a36Sopenharmony_ci#include <linux/quotaops.h>
5962306a36Sopenharmony_ci#include <linux/iversion.h>
6062306a36Sopenharmony_ci#include "ext4_jbd2.h"
6162306a36Sopenharmony_ci#include "ext4.h"
6262306a36Sopenharmony_ci#include "xattr.h"
6362306a36Sopenharmony_ci#include "acl.h"
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#ifdef EXT4_XATTR_DEBUG
6662306a36Sopenharmony_ci# define ea_idebug(inode, fmt, ...)					\
6762306a36Sopenharmony_ci	printk(KERN_DEBUG "inode %s:%lu: " fmt "\n",			\
6862306a36Sopenharmony_ci	       inode->i_sb->s_id, inode->i_ino, ##__VA_ARGS__)
6962306a36Sopenharmony_ci# define ea_bdebug(bh, fmt, ...)					\
7062306a36Sopenharmony_ci	printk(KERN_DEBUG "block %pg:%lu: " fmt "\n",			\
7162306a36Sopenharmony_ci	       bh->b_bdev, (unsigned long)bh->b_blocknr, ##__VA_ARGS__)
7262306a36Sopenharmony_ci#else
7362306a36Sopenharmony_ci# define ea_idebug(inode, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
7462306a36Sopenharmony_ci# define ea_bdebug(bh, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
7562306a36Sopenharmony_ci#endif
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic void ext4_xattr_block_cache_insert(struct mb_cache *,
7862306a36Sopenharmony_ci					  struct buffer_head *);
7962306a36Sopenharmony_cistatic struct buffer_head *
8062306a36Sopenharmony_ciext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *,
8162306a36Sopenharmony_ci			    struct mb_cache_entry **);
8262306a36Sopenharmony_cistatic __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
8362306a36Sopenharmony_ci				    size_t value_count);
8462306a36Sopenharmony_cistatic __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value,
8562306a36Sopenharmony_ci				    size_t value_count);
8662306a36Sopenharmony_cistatic void ext4_xattr_rehash(struct ext4_xattr_header *);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic const struct xattr_handler * const ext4_xattr_handler_map[] = {
8962306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_USER]		     = &ext4_xattr_user_handler,
9062306a36Sopenharmony_ci#ifdef CONFIG_EXT4_FS_POSIX_ACL
9162306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &nop_posix_acl_access,
9262306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_TRUSTED]	     = &ext4_xattr_trusted_handler,
9562306a36Sopenharmony_ci#ifdef CONFIG_EXT4_FS_SECURITY
9662306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_SECURITY]	     = &ext4_xattr_security_handler,
9762306a36Sopenharmony_ci#endif
9862306a36Sopenharmony_ci	[EXT4_XATTR_INDEX_HURD]		     = &ext4_xattr_hurd_handler,
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciconst struct xattr_handler *ext4_xattr_handlers[] = {
10262306a36Sopenharmony_ci	&ext4_xattr_user_handler,
10362306a36Sopenharmony_ci	&ext4_xattr_trusted_handler,
10462306a36Sopenharmony_ci#ifdef CONFIG_EXT4_FS_SECURITY
10562306a36Sopenharmony_ci	&ext4_xattr_security_handler,
10662306a36Sopenharmony_ci#endif
10762306a36Sopenharmony_ci	&ext4_xattr_hurd_handler,
10862306a36Sopenharmony_ci	NULL
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#define EA_BLOCK_CACHE(inode)	(((struct ext4_sb_info *) \
11262306a36Sopenharmony_ci				inode->i_sb->s_fs_info)->s_ea_block_cache)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#define EA_INODE_CACHE(inode)	(((struct ext4_sb_info *) \
11562306a36Sopenharmony_ci				inode->i_sb->s_fs_info)->s_ea_inode_cache)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int
11862306a36Sopenharmony_ciext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
11962306a36Sopenharmony_ci			struct inode *inode);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci#ifdef CONFIG_LOCKDEP
12262306a36Sopenharmony_civoid ext4_xattr_inode_set_class(struct inode *ea_inode)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	struct ext4_inode_info *ei = EXT4_I(ea_inode);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	lockdep_set_subclass(&ea_inode->i_rwsem, 1);
12762306a36Sopenharmony_ci	(void) ei;	/* shut up clang warning if !CONFIG_LOCKDEP */
12862306a36Sopenharmony_ci	lockdep_set_subclass(&ei->i_data_sem, I_DATA_SEM_EA);
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci#endif
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic __le32 ext4_xattr_block_csum(struct inode *inode,
13362306a36Sopenharmony_ci				    sector_t block_nr,
13462306a36Sopenharmony_ci				    struct ext4_xattr_header *hdr)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
13762306a36Sopenharmony_ci	__u32 csum;
13862306a36Sopenharmony_ci	__le64 dsk_block_nr = cpu_to_le64(block_nr);
13962306a36Sopenharmony_ci	__u32 dummy_csum = 0;
14062306a36Sopenharmony_ci	int offset = offsetof(struct ext4_xattr_header, h_checksum);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr,
14362306a36Sopenharmony_ci			   sizeof(dsk_block_nr));
14462306a36Sopenharmony_ci	csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset);
14562306a36Sopenharmony_ci	csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
14662306a36Sopenharmony_ci	offset += sizeof(dummy_csum);
14762306a36Sopenharmony_ci	csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset,
14862306a36Sopenharmony_ci			   EXT4_BLOCK_SIZE(inode->i_sb) - offset);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	return cpu_to_le32(csum);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic int ext4_xattr_block_csum_verify(struct inode *inode,
15462306a36Sopenharmony_ci					struct buffer_head *bh)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	struct ext4_xattr_header *hdr = BHDR(bh);
15762306a36Sopenharmony_ci	int ret = 1;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (ext4_has_metadata_csum(inode->i_sb)) {
16062306a36Sopenharmony_ci		lock_buffer(bh);
16162306a36Sopenharmony_ci		ret = (hdr->h_checksum == ext4_xattr_block_csum(inode,
16262306a36Sopenharmony_ci							bh->b_blocknr, hdr));
16362306a36Sopenharmony_ci		unlock_buffer(bh);
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci	return ret;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic void ext4_xattr_block_csum_set(struct inode *inode,
16962306a36Sopenharmony_ci				      struct buffer_head *bh)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	if (ext4_has_metadata_csum(inode->i_sb))
17262306a36Sopenharmony_ci		BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode,
17362306a36Sopenharmony_ci						bh->b_blocknr, BHDR(bh));
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline const char *ext4_xattr_prefix(int name_index,
17762306a36Sopenharmony_ci					    struct dentry *dentry)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	const struct xattr_handler *handler = NULL;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
18262306a36Sopenharmony_ci		handler = ext4_xattr_handler_map[name_index];
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	if (!xattr_handler_can_list(handler, dentry))
18562306a36Sopenharmony_ci		return NULL;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return xattr_prefix(handler);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int
19162306a36Sopenharmony_cicheck_xattrs(struct inode *inode, struct buffer_head *bh,
19262306a36Sopenharmony_ci	     struct ext4_xattr_entry *entry, void *end, void *value_start,
19362306a36Sopenharmony_ci	     const char *function, unsigned int line)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct ext4_xattr_entry *e = entry;
19662306a36Sopenharmony_ci	int err = -EFSCORRUPTED;
19762306a36Sopenharmony_ci	char *err_str;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if (bh) {
20062306a36Sopenharmony_ci		if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
20162306a36Sopenharmony_ci		    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
20262306a36Sopenharmony_ci			err_str = "invalid header";
20362306a36Sopenharmony_ci			goto errout;
20462306a36Sopenharmony_ci		}
20562306a36Sopenharmony_ci		if (buffer_verified(bh))
20662306a36Sopenharmony_ci			return 0;
20762306a36Sopenharmony_ci		if (!ext4_xattr_block_csum_verify(inode, bh)) {
20862306a36Sopenharmony_ci			err = -EFSBADCRC;
20962306a36Sopenharmony_ci			err_str = "invalid checksum";
21062306a36Sopenharmony_ci			goto errout;
21162306a36Sopenharmony_ci		}
21262306a36Sopenharmony_ci	} else {
21362306a36Sopenharmony_ci		struct ext4_xattr_ibody_header *header = value_start;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		header -= 1;
21662306a36Sopenharmony_ci		if (end - (void *)header < sizeof(*header) + sizeof(u32)) {
21762306a36Sopenharmony_ci			err_str = "in-inode xattr block too small";
21862306a36Sopenharmony_ci			goto errout;
21962306a36Sopenharmony_ci		}
22062306a36Sopenharmony_ci		if (header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
22162306a36Sopenharmony_ci			err_str = "bad magic number in in-inode xattr";
22262306a36Sopenharmony_ci			goto errout;
22362306a36Sopenharmony_ci		}
22462306a36Sopenharmony_ci	}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* Find the end of the names list */
22762306a36Sopenharmony_ci	while (!IS_LAST_ENTRY(e)) {
22862306a36Sopenharmony_ci		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
22962306a36Sopenharmony_ci		if ((void *)next >= end) {
23062306a36Sopenharmony_ci			err_str = "e_name out of bounds";
23162306a36Sopenharmony_ci			goto errout;
23262306a36Sopenharmony_ci		}
23362306a36Sopenharmony_ci		if (strnlen(e->e_name, e->e_name_len) != e->e_name_len) {
23462306a36Sopenharmony_ci			err_str = "bad e_name length";
23562306a36Sopenharmony_ci			goto errout;
23662306a36Sopenharmony_ci		}
23762306a36Sopenharmony_ci		e = next;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/* Check the values */
24162306a36Sopenharmony_ci	while (!IS_LAST_ENTRY(entry)) {
24262306a36Sopenharmony_ci		u32 size = le32_to_cpu(entry->e_value_size);
24362306a36Sopenharmony_ci		unsigned long ea_ino = le32_to_cpu(entry->e_value_inum);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		if (!ext4_has_feature_ea_inode(inode->i_sb) && ea_ino) {
24662306a36Sopenharmony_ci			err_str = "ea_inode specified without ea_inode feature enabled";
24762306a36Sopenharmony_ci			goto errout;
24862306a36Sopenharmony_ci		}
24962306a36Sopenharmony_ci		if (ea_ino && ((ea_ino == EXT4_ROOT_INO) ||
25062306a36Sopenharmony_ci			       !ext4_valid_inum(inode->i_sb, ea_ino))) {
25162306a36Sopenharmony_ci			err_str = "invalid ea_ino";
25262306a36Sopenharmony_ci			goto errout;
25362306a36Sopenharmony_ci		}
25462306a36Sopenharmony_ci		if (size > EXT4_XATTR_SIZE_MAX) {
25562306a36Sopenharmony_ci			err_str = "e_value size too large";
25662306a36Sopenharmony_ci			goto errout;
25762306a36Sopenharmony_ci		}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci		if (size != 0 && entry->e_value_inum == 0) {
26062306a36Sopenharmony_ci			u16 offs = le16_to_cpu(entry->e_value_offs);
26162306a36Sopenharmony_ci			void *value;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci			/*
26462306a36Sopenharmony_ci			 * The value cannot overlap the names, and the value
26562306a36Sopenharmony_ci			 * with padding cannot extend beyond 'end'.  Check both
26662306a36Sopenharmony_ci			 * the padded and unpadded sizes, since the size may
26762306a36Sopenharmony_ci			 * overflow to 0 when adding padding.
26862306a36Sopenharmony_ci			 */
26962306a36Sopenharmony_ci			if (offs > end - value_start) {
27062306a36Sopenharmony_ci				err_str = "e_value out of bounds";
27162306a36Sopenharmony_ci				goto errout;
27262306a36Sopenharmony_ci			}
27362306a36Sopenharmony_ci			value = value_start + offs;
27462306a36Sopenharmony_ci			if (value < (void *)e + sizeof(u32) ||
27562306a36Sopenharmony_ci			    size > end - value ||
27662306a36Sopenharmony_ci			    EXT4_XATTR_SIZE(size) > end - value) {
27762306a36Sopenharmony_ci				err_str = "overlapping e_value ";
27862306a36Sopenharmony_ci				goto errout;
27962306a36Sopenharmony_ci			}
28062306a36Sopenharmony_ci		}
28162306a36Sopenharmony_ci		entry = EXT4_XATTR_NEXT(entry);
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci	if (bh)
28462306a36Sopenharmony_ci		set_buffer_verified(bh);
28562306a36Sopenharmony_ci	return 0;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cierrout:
28862306a36Sopenharmony_ci	if (bh)
28962306a36Sopenharmony_ci		__ext4_error_inode(inode, function, line, 0, -err,
29062306a36Sopenharmony_ci				   "corrupted xattr block %llu: %s",
29162306a36Sopenharmony_ci				   (unsigned long long) bh->b_blocknr,
29262306a36Sopenharmony_ci				   err_str);
29362306a36Sopenharmony_ci	else
29462306a36Sopenharmony_ci		__ext4_error_inode(inode, function, line, 0, -err,
29562306a36Sopenharmony_ci				   "corrupted in-inode xattr: %s", err_str);
29662306a36Sopenharmony_ci	return err;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic inline int
30062306a36Sopenharmony_ci__ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
30162306a36Sopenharmony_ci			 const char *function, unsigned int line)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	return check_xattrs(inode, bh, BFIRST(bh), bh->b_data + bh->b_size,
30462306a36Sopenharmony_ci			    bh->b_data, function, line);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci#define ext4_xattr_check_block(inode, bh) \
30862306a36Sopenharmony_ci	__ext4_xattr_check_block((inode), (bh),  __func__, __LINE__)
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic inline int
31262306a36Sopenharmony_ci__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
31362306a36Sopenharmony_ci			 void *end, const char *function, unsigned int line)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	return check_xattrs(inode, NULL, IFIRST(header), end, IFIRST(header),
31662306a36Sopenharmony_ci			    function, line);
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci#define xattr_check_inode(inode, header, end) \
32062306a36Sopenharmony_ci	__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic int
32362306a36Sopenharmony_cixattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
32462306a36Sopenharmony_ci		 void *end, int name_index, const char *name, int sorted)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct ext4_xattr_entry *entry, *next;
32762306a36Sopenharmony_ci	size_t name_len;
32862306a36Sopenharmony_ci	int cmp = 1;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (name == NULL)
33162306a36Sopenharmony_ci		return -EINVAL;
33262306a36Sopenharmony_ci	name_len = strlen(name);
33362306a36Sopenharmony_ci	for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) {
33462306a36Sopenharmony_ci		next = EXT4_XATTR_NEXT(entry);
33562306a36Sopenharmony_ci		if ((void *) next >= end) {
33662306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "corrupted xattr entries");
33762306a36Sopenharmony_ci			return -EFSCORRUPTED;
33862306a36Sopenharmony_ci		}
33962306a36Sopenharmony_ci		cmp = name_index - entry->e_name_index;
34062306a36Sopenharmony_ci		if (!cmp)
34162306a36Sopenharmony_ci			cmp = name_len - entry->e_name_len;
34262306a36Sopenharmony_ci		if (!cmp)
34362306a36Sopenharmony_ci			cmp = memcmp(name, entry->e_name, name_len);
34462306a36Sopenharmony_ci		if (cmp <= 0 && (sorted || cmp == 0))
34562306a36Sopenharmony_ci			break;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	*pentry = entry;
34862306a36Sopenharmony_ci	return cmp ? -ENODATA : 0;
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic u32
35262306a36Sopenharmony_ciext4_xattr_inode_hash(struct ext4_sb_info *sbi, const void *buffer, size_t size)
35362306a36Sopenharmony_ci{
35462306a36Sopenharmony_ci	return ext4_chksum(sbi, sbi->s_csum_seed, buffer, size);
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic u64 ext4_xattr_inode_get_ref(struct inode *ea_inode)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	return ((u64) inode_get_ctime(ea_inode).tv_sec << 32) |
36062306a36Sopenharmony_ci		(u32) inode_peek_iversion_raw(ea_inode);
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic void ext4_xattr_inode_set_ref(struct inode *ea_inode, u64 ref_count)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	inode_set_ctime(ea_inode, (u32)(ref_count >> 32), 0);
36662306a36Sopenharmony_ci	inode_set_iversion_raw(ea_inode, ref_count & 0xffffffff);
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic u32 ext4_xattr_inode_get_hash(struct inode *ea_inode)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	return (u32)ea_inode->i_atime.tv_sec;
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cistatic void ext4_xattr_inode_set_hash(struct inode *ea_inode, u32 hash)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	ea_inode->i_atime.tv_sec = hash;
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci/*
38062306a36Sopenharmony_ci * Read the EA value from an inode.
38162306a36Sopenharmony_ci */
38262306a36Sopenharmony_cistatic int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	int blocksize = 1 << ea_inode->i_blkbits;
38562306a36Sopenharmony_ci	int bh_count = (size + blocksize - 1) >> ea_inode->i_blkbits;
38662306a36Sopenharmony_ci	int tail_size = (size % blocksize) ?: blocksize;
38762306a36Sopenharmony_ci	struct buffer_head *bhs_inline[8];
38862306a36Sopenharmony_ci	struct buffer_head **bhs = bhs_inline;
38962306a36Sopenharmony_ci	int i, ret;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	if (bh_count > ARRAY_SIZE(bhs_inline)) {
39262306a36Sopenharmony_ci		bhs = kmalloc_array(bh_count, sizeof(*bhs), GFP_NOFS);
39362306a36Sopenharmony_ci		if (!bhs)
39462306a36Sopenharmony_ci			return -ENOMEM;
39562306a36Sopenharmony_ci	}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	ret = ext4_bread_batch(ea_inode, 0 /* block */, bh_count,
39862306a36Sopenharmony_ci			       true /* wait */, bhs);
39962306a36Sopenharmony_ci	if (ret)
40062306a36Sopenharmony_ci		goto free_bhs;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	for (i = 0; i < bh_count; i++) {
40362306a36Sopenharmony_ci		/* There shouldn't be any holes in ea_inode. */
40462306a36Sopenharmony_ci		if (!bhs[i]) {
40562306a36Sopenharmony_ci			ret = -EFSCORRUPTED;
40662306a36Sopenharmony_ci			goto put_bhs;
40762306a36Sopenharmony_ci		}
40862306a36Sopenharmony_ci		memcpy((char *)buf + blocksize * i, bhs[i]->b_data,
40962306a36Sopenharmony_ci		       i < bh_count - 1 ? blocksize : tail_size);
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci	ret = 0;
41262306a36Sopenharmony_ciput_bhs:
41362306a36Sopenharmony_ci	for (i = 0; i < bh_count; i++)
41462306a36Sopenharmony_ci		brelse(bhs[i]);
41562306a36Sopenharmony_cifree_bhs:
41662306a36Sopenharmony_ci	if (bhs != bhs_inline)
41762306a36Sopenharmony_ci		kfree(bhs);
41862306a36Sopenharmony_ci	return ret;
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci#define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode)->i_mtime.tv_sec)
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
42462306a36Sopenharmony_ci				 u32 ea_inode_hash, struct inode **ea_inode)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	struct inode *inode;
42762306a36Sopenharmony_ci	int err;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/*
43062306a36Sopenharmony_ci	 * We have to check for this corruption early as otherwise
43162306a36Sopenharmony_ci	 * iget_locked() could wait indefinitely for the state of our
43262306a36Sopenharmony_ci	 * parent inode.
43362306a36Sopenharmony_ci	 */
43462306a36Sopenharmony_ci	if (parent->i_ino == ea_ino) {
43562306a36Sopenharmony_ci		ext4_error(parent->i_sb,
43662306a36Sopenharmony_ci			   "Parent and EA inode have the same ino %lu", ea_ino);
43762306a36Sopenharmony_ci		return -EFSCORRUPTED;
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_EA_INODE);
44162306a36Sopenharmony_ci	if (IS_ERR(inode)) {
44262306a36Sopenharmony_ci		err = PTR_ERR(inode);
44362306a36Sopenharmony_ci		ext4_error(parent->i_sb,
44462306a36Sopenharmony_ci			   "error while reading EA inode %lu err=%d", ea_ino,
44562306a36Sopenharmony_ci			   err);
44662306a36Sopenharmony_ci		return err;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci	ext4_xattr_inode_set_class(inode);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	/*
45162306a36Sopenharmony_ci	 * Check whether this is an old Lustre-style xattr inode. Lustre
45262306a36Sopenharmony_ci	 * implementation does not have hash validation, rather it has a
45362306a36Sopenharmony_ci	 * backpointer from ea_inode to the parent inode.
45462306a36Sopenharmony_ci	 */
45562306a36Sopenharmony_ci	if (ea_inode_hash != ext4_xattr_inode_get_hash(inode) &&
45662306a36Sopenharmony_ci	    EXT4_XATTR_INODE_GET_PARENT(inode) == parent->i_ino &&
45762306a36Sopenharmony_ci	    inode->i_generation == parent->i_generation) {
45862306a36Sopenharmony_ci		ext4_set_inode_state(inode, EXT4_STATE_LUSTRE_EA_INODE);
45962306a36Sopenharmony_ci		ext4_xattr_inode_set_ref(inode, 1);
46062306a36Sopenharmony_ci	} else {
46162306a36Sopenharmony_ci		inode_lock(inode);
46262306a36Sopenharmony_ci		inode->i_flags |= S_NOQUOTA;
46362306a36Sopenharmony_ci		inode_unlock(inode);
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	*ea_inode = inode;
46762306a36Sopenharmony_ci	return 0;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci/* Remove entry from mbcache when EA inode is getting evicted */
47162306a36Sopenharmony_civoid ext4_evict_ea_inode(struct inode *inode)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct mb_cache_entry *oe;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	if (!EA_INODE_CACHE(inode))
47662306a36Sopenharmony_ci		return;
47762306a36Sopenharmony_ci	/* Wait for entry to get unused so that we can remove it */
47862306a36Sopenharmony_ci	while ((oe = mb_cache_entry_delete_or_get(EA_INODE_CACHE(inode),
47962306a36Sopenharmony_ci			ext4_xattr_inode_get_hash(inode), inode->i_ino))) {
48062306a36Sopenharmony_ci		mb_cache_entry_wait_unused(oe);
48162306a36Sopenharmony_ci		mb_cache_entry_put(EA_INODE_CACHE(inode), oe);
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int
48662306a36Sopenharmony_ciext4_xattr_inode_verify_hashes(struct inode *ea_inode,
48762306a36Sopenharmony_ci			       struct ext4_xattr_entry *entry, void *buffer,
48862306a36Sopenharmony_ci			       size_t size)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	u32 hash;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	/* Verify stored hash matches calculated hash. */
49362306a36Sopenharmony_ci	hash = ext4_xattr_inode_hash(EXT4_SB(ea_inode->i_sb), buffer, size);
49462306a36Sopenharmony_ci	if (hash != ext4_xattr_inode_get_hash(ea_inode))
49562306a36Sopenharmony_ci		return -EFSCORRUPTED;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (entry) {
49862306a36Sopenharmony_ci		__le32 e_hash, tmp_data;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci		/* Verify entry hash. */
50162306a36Sopenharmony_ci		tmp_data = cpu_to_le32(hash);
50262306a36Sopenharmony_ci		e_hash = ext4_xattr_hash_entry(entry->e_name, entry->e_name_len,
50362306a36Sopenharmony_ci					       &tmp_data, 1);
50462306a36Sopenharmony_ci		/* All good? */
50562306a36Sopenharmony_ci		if (e_hash == entry->e_hash)
50662306a36Sopenharmony_ci			return 0;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci		/*
50962306a36Sopenharmony_ci		 * Not good. Maybe the entry hash was calculated
51062306a36Sopenharmony_ci		 * using the buggy signed char version?
51162306a36Sopenharmony_ci		 */
51262306a36Sopenharmony_ci		e_hash = ext4_xattr_hash_entry_signed(entry->e_name, entry->e_name_len,
51362306a36Sopenharmony_ci							&tmp_data, 1);
51462306a36Sopenharmony_ci		/* Still no match - bad */
51562306a36Sopenharmony_ci		if (e_hash != entry->e_hash)
51662306a36Sopenharmony_ci			return -EFSCORRUPTED;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci		/* Let people know about old hash */
51962306a36Sopenharmony_ci		pr_warn_once("ext4: filesystem with signed xattr name hash");
52062306a36Sopenharmony_ci	}
52162306a36Sopenharmony_ci	return 0;
52262306a36Sopenharmony_ci}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci/*
52562306a36Sopenharmony_ci * Read xattr value from the EA inode.
52662306a36Sopenharmony_ci */
52762306a36Sopenharmony_cistatic int
52862306a36Sopenharmony_ciext4_xattr_inode_get(struct inode *inode, struct ext4_xattr_entry *entry,
52962306a36Sopenharmony_ci		     void *buffer, size_t size)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	struct mb_cache *ea_inode_cache = EA_INODE_CACHE(inode);
53262306a36Sopenharmony_ci	struct inode *ea_inode;
53362306a36Sopenharmony_ci	int err;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	err = ext4_xattr_inode_iget(inode, le32_to_cpu(entry->e_value_inum),
53662306a36Sopenharmony_ci				    le32_to_cpu(entry->e_hash), &ea_inode);
53762306a36Sopenharmony_ci	if (err) {
53862306a36Sopenharmony_ci		ea_inode = NULL;
53962306a36Sopenharmony_ci		goto out;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (i_size_read(ea_inode) != size) {
54362306a36Sopenharmony_ci		ext4_warning_inode(ea_inode,
54462306a36Sopenharmony_ci				   "ea_inode file size=%llu entry size=%zu",
54562306a36Sopenharmony_ci				   i_size_read(ea_inode), size);
54662306a36Sopenharmony_ci		err = -EFSCORRUPTED;
54762306a36Sopenharmony_ci		goto out;
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	err = ext4_xattr_inode_read(ea_inode, buffer, size);
55162306a36Sopenharmony_ci	if (err)
55262306a36Sopenharmony_ci		goto out;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	if (!ext4_test_inode_state(ea_inode, EXT4_STATE_LUSTRE_EA_INODE)) {
55562306a36Sopenharmony_ci		err = ext4_xattr_inode_verify_hashes(ea_inode, entry, buffer,
55662306a36Sopenharmony_ci						     size);
55762306a36Sopenharmony_ci		if (err) {
55862306a36Sopenharmony_ci			ext4_warning_inode(ea_inode,
55962306a36Sopenharmony_ci					   "EA inode hash validation failed");
56062306a36Sopenharmony_ci			goto out;
56162306a36Sopenharmony_ci		}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci		if (ea_inode_cache)
56462306a36Sopenharmony_ci			mb_cache_entry_create(ea_inode_cache, GFP_NOFS,
56562306a36Sopenharmony_ci					ext4_xattr_inode_get_hash(ea_inode),
56662306a36Sopenharmony_ci					ea_inode->i_ino, true /* reusable */);
56762306a36Sopenharmony_ci	}
56862306a36Sopenharmony_ciout:
56962306a36Sopenharmony_ci	iput(ea_inode);
57062306a36Sopenharmony_ci	return err;
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic int
57462306a36Sopenharmony_ciext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
57562306a36Sopenharmony_ci		     void *buffer, size_t buffer_size)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
57862306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
57962306a36Sopenharmony_ci	size_t size;
58062306a36Sopenharmony_ci	void *end;
58162306a36Sopenharmony_ci	int error;
58262306a36Sopenharmony_ci	struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
58562306a36Sopenharmony_ci		  name_index, name, buffer, (long)buffer_size);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (!EXT4_I(inode)->i_file_acl)
58862306a36Sopenharmony_ci		return -ENODATA;
58962306a36Sopenharmony_ci	ea_idebug(inode, "reading block %llu",
59062306a36Sopenharmony_ci		  (unsigned long long)EXT4_I(inode)->i_file_acl);
59162306a36Sopenharmony_ci	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
59262306a36Sopenharmony_ci	if (IS_ERR(bh))
59362306a36Sopenharmony_ci		return PTR_ERR(bh);
59462306a36Sopenharmony_ci	ea_bdebug(bh, "b_count=%d, refcount=%d",
59562306a36Sopenharmony_ci		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
59662306a36Sopenharmony_ci	error = ext4_xattr_check_block(inode, bh);
59762306a36Sopenharmony_ci	if (error)
59862306a36Sopenharmony_ci		goto cleanup;
59962306a36Sopenharmony_ci	ext4_xattr_block_cache_insert(ea_block_cache, bh);
60062306a36Sopenharmony_ci	entry = BFIRST(bh);
60162306a36Sopenharmony_ci	end = bh->b_data + bh->b_size;
60262306a36Sopenharmony_ci	error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
60362306a36Sopenharmony_ci	if (error)
60462306a36Sopenharmony_ci		goto cleanup;
60562306a36Sopenharmony_ci	size = le32_to_cpu(entry->e_value_size);
60662306a36Sopenharmony_ci	error = -ERANGE;
60762306a36Sopenharmony_ci	if (unlikely(size > EXT4_XATTR_SIZE_MAX))
60862306a36Sopenharmony_ci		goto cleanup;
60962306a36Sopenharmony_ci	if (buffer) {
61062306a36Sopenharmony_ci		if (size > buffer_size)
61162306a36Sopenharmony_ci			goto cleanup;
61262306a36Sopenharmony_ci		if (entry->e_value_inum) {
61362306a36Sopenharmony_ci			error = ext4_xattr_inode_get(inode, entry, buffer,
61462306a36Sopenharmony_ci						     size);
61562306a36Sopenharmony_ci			if (error)
61662306a36Sopenharmony_ci				goto cleanup;
61762306a36Sopenharmony_ci		} else {
61862306a36Sopenharmony_ci			u16 offset = le16_to_cpu(entry->e_value_offs);
61962306a36Sopenharmony_ci			void *p = bh->b_data + offset;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci			if (unlikely(p + size > end))
62262306a36Sopenharmony_ci				goto cleanup;
62362306a36Sopenharmony_ci			memcpy(buffer, p, size);
62462306a36Sopenharmony_ci		}
62562306a36Sopenharmony_ci	}
62662306a36Sopenharmony_ci	error = size;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cicleanup:
62962306a36Sopenharmony_ci	brelse(bh);
63062306a36Sopenharmony_ci	return error;
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ciint
63462306a36Sopenharmony_ciext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
63562306a36Sopenharmony_ci		     void *buffer, size_t buffer_size)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
63862306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
63962306a36Sopenharmony_ci	struct ext4_inode *raw_inode;
64062306a36Sopenharmony_ci	struct ext4_iloc iloc;
64162306a36Sopenharmony_ci	size_t size;
64262306a36Sopenharmony_ci	void *end;
64362306a36Sopenharmony_ci	int error;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
64662306a36Sopenharmony_ci		return -ENODATA;
64762306a36Sopenharmony_ci	error = ext4_get_inode_loc(inode, &iloc);
64862306a36Sopenharmony_ci	if (error)
64962306a36Sopenharmony_ci		return error;
65062306a36Sopenharmony_ci	raw_inode = ext4_raw_inode(&iloc);
65162306a36Sopenharmony_ci	header = IHDR(inode, raw_inode);
65262306a36Sopenharmony_ci	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
65362306a36Sopenharmony_ci	error = xattr_check_inode(inode, header, end);
65462306a36Sopenharmony_ci	if (error)
65562306a36Sopenharmony_ci		goto cleanup;
65662306a36Sopenharmony_ci	entry = IFIRST(header);
65762306a36Sopenharmony_ci	error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
65862306a36Sopenharmony_ci	if (error)
65962306a36Sopenharmony_ci		goto cleanup;
66062306a36Sopenharmony_ci	size = le32_to_cpu(entry->e_value_size);
66162306a36Sopenharmony_ci	error = -ERANGE;
66262306a36Sopenharmony_ci	if (unlikely(size > EXT4_XATTR_SIZE_MAX))
66362306a36Sopenharmony_ci		goto cleanup;
66462306a36Sopenharmony_ci	if (buffer) {
66562306a36Sopenharmony_ci		if (size > buffer_size)
66662306a36Sopenharmony_ci			goto cleanup;
66762306a36Sopenharmony_ci		if (entry->e_value_inum) {
66862306a36Sopenharmony_ci			error = ext4_xattr_inode_get(inode, entry, buffer,
66962306a36Sopenharmony_ci						     size);
67062306a36Sopenharmony_ci			if (error)
67162306a36Sopenharmony_ci				goto cleanup;
67262306a36Sopenharmony_ci		} else {
67362306a36Sopenharmony_ci			u16 offset = le16_to_cpu(entry->e_value_offs);
67462306a36Sopenharmony_ci			void *p = (void *)IFIRST(header) + offset;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci			if (unlikely(p + size > end))
67762306a36Sopenharmony_ci				goto cleanup;
67862306a36Sopenharmony_ci			memcpy(buffer, p, size);
67962306a36Sopenharmony_ci		}
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci	error = size;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_cicleanup:
68462306a36Sopenharmony_ci	brelse(iloc.bh);
68562306a36Sopenharmony_ci	return error;
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci/*
68962306a36Sopenharmony_ci * ext4_xattr_get()
69062306a36Sopenharmony_ci *
69162306a36Sopenharmony_ci * Copy an extended attribute into the buffer
69262306a36Sopenharmony_ci * provided, or compute the buffer size required.
69362306a36Sopenharmony_ci * Buffer is NULL to compute the size of the buffer required.
69462306a36Sopenharmony_ci *
69562306a36Sopenharmony_ci * Returns a negative error number on failure, or the number of bytes
69662306a36Sopenharmony_ci * used / required on success.
69762306a36Sopenharmony_ci */
69862306a36Sopenharmony_ciint
69962306a36Sopenharmony_ciext4_xattr_get(struct inode *inode, int name_index, const char *name,
70062306a36Sopenharmony_ci	       void *buffer, size_t buffer_size)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	int error;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	if (unlikely(ext4_forced_shutdown(inode->i_sb)))
70562306a36Sopenharmony_ci		return -EIO;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	if (strlen(name) > 255)
70862306a36Sopenharmony_ci		return -ERANGE;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	down_read(&EXT4_I(inode)->xattr_sem);
71162306a36Sopenharmony_ci	error = ext4_xattr_ibody_get(inode, name_index, name, buffer,
71262306a36Sopenharmony_ci				     buffer_size);
71362306a36Sopenharmony_ci	if (error == -ENODATA)
71462306a36Sopenharmony_ci		error = ext4_xattr_block_get(inode, name_index, name, buffer,
71562306a36Sopenharmony_ci					     buffer_size);
71662306a36Sopenharmony_ci	up_read(&EXT4_I(inode)->xattr_sem);
71762306a36Sopenharmony_ci	return error;
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic int
72162306a36Sopenharmony_ciext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
72262306a36Sopenharmony_ci			char *buffer, size_t buffer_size)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	size_t rest = buffer_size;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
72762306a36Sopenharmony_ci		const char *prefix;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		prefix = ext4_xattr_prefix(entry->e_name_index, dentry);
73062306a36Sopenharmony_ci		if (prefix) {
73162306a36Sopenharmony_ci			size_t prefix_len = strlen(prefix);
73262306a36Sopenharmony_ci			size_t size = prefix_len + entry->e_name_len + 1;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci			if (buffer) {
73562306a36Sopenharmony_ci				if (size > rest)
73662306a36Sopenharmony_ci					return -ERANGE;
73762306a36Sopenharmony_ci				memcpy(buffer, prefix, prefix_len);
73862306a36Sopenharmony_ci				buffer += prefix_len;
73962306a36Sopenharmony_ci				memcpy(buffer, entry->e_name, entry->e_name_len);
74062306a36Sopenharmony_ci				buffer += entry->e_name_len;
74162306a36Sopenharmony_ci				*buffer++ = 0;
74262306a36Sopenharmony_ci			}
74362306a36Sopenharmony_ci			rest -= size;
74462306a36Sopenharmony_ci		}
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci	return buffer_size - rest;  /* total size */
74762306a36Sopenharmony_ci}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_cistatic int
75062306a36Sopenharmony_ciext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
75162306a36Sopenharmony_ci{
75262306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
75362306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
75462306a36Sopenharmony_ci	int error;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
75762306a36Sopenharmony_ci		  buffer, (long)buffer_size);
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	if (!EXT4_I(inode)->i_file_acl)
76062306a36Sopenharmony_ci		return 0;
76162306a36Sopenharmony_ci	ea_idebug(inode, "reading block %llu",
76262306a36Sopenharmony_ci		  (unsigned long long)EXT4_I(inode)->i_file_acl);
76362306a36Sopenharmony_ci	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
76462306a36Sopenharmony_ci	if (IS_ERR(bh))
76562306a36Sopenharmony_ci		return PTR_ERR(bh);
76662306a36Sopenharmony_ci	ea_bdebug(bh, "b_count=%d, refcount=%d",
76762306a36Sopenharmony_ci		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
76862306a36Sopenharmony_ci	error = ext4_xattr_check_block(inode, bh);
76962306a36Sopenharmony_ci	if (error)
77062306a36Sopenharmony_ci		goto cleanup;
77162306a36Sopenharmony_ci	ext4_xattr_block_cache_insert(EA_BLOCK_CACHE(inode), bh);
77262306a36Sopenharmony_ci	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer,
77362306a36Sopenharmony_ci					buffer_size);
77462306a36Sopenharmony_cicleanup:
77562306a36Sopenharmony_ci	brelse(bh);
77662306a36Sopenharmony_ci	return error;
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_cistatic int
78062306a36Sopenharmony_ciext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
78362306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
78462306a36Sopenharmony_ci	struct ext4_inode *raw_inode;
78562306a36Sopenharmony_ci	struct ext4_iloc iloc;
78662306a36Sopenharmony_ci	void *end;
78762306a36Sopenharmony_ci	int error;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
79062306a36Sopenharmony_ci		return 0;
79162306a36Sopenharmony_ci	error = ext4_get_inode_loc(inode, &iloc);
79262306a36Sopenharmony_ci	if (error)
79362306a36Sopenharmony_ci		return error;
79462306a36Sopenharmony_ci	raw_inode = ext4_raw_inode(&iloc);
79562306a36Sopenharmony_ci	header = IHDR(inode, raw_inode);
79662306a36Sopenharmony_ci	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
79762306a36Sopenharmony_ci	error = xattr_check_inode(inode, header, end);
79862306a36Sopenharmony_ci	if (error)
79962306a36Sopenharmony_ci		goto cleanup;
80062306a36Sopenharmony_ci	error = ext4_xattr_list_entries(dentry, IFIRST(header),
80162306a36Sopenharmony_ci					buffer, buffer_size);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cicleanup:
80462306a36Sopenharmony_ci	brelse(iloc.bh);
80562306a36Sopenharmony_ci	return error;
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci/*
80962306a36Sopenharmony_ci * Inode operation listxattr()
81062306a36Sopenharmony_ci *
81162306a36Sopenharmony_ci * d_inode(dentry)->i_rwsem: don't care
81262306a36Sopenharmony_ci *
81362306a36Sopenharmony_ci * Copy a list of attribute names into the buffer
81462306a36Sopenharmony_ci * provided, or compute the buffer size required.
81562306a36Sopenharmony_ci * Buffer is NULL to compute the size of the buffer required.
81662306a36Sopenharmony_ci *
81762306a36Sopenharmony_ci * Returns a negative error number on failure, or the number of bytes
81862306a36Sopenharmony_ci * used / required on success.
81962306a36Sopenharmony_ci */
82062306a36Sopenharmony_cissize_t
82162306a36Sopenharmony_ciext4_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	int ret, ret2;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	down_read(&EXT4_I(d_inode(dentry))->xattr_sem);
82662306a36Sopenharmony_ci	ret = ret2 = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
82762306a36Sopenharmony_ci	if (ret < 0)
82862306a36Sopenharmony_ci		goto errout;
82962306a36Sopenharmony_ci	if (buffer) {
83062306a36Sopenharmony_ci		buffer += ret;
83162306a36Sopenharmony_ci		buffer_size -= ret;
83262306a36Sopenharmony_ci	}
83362306a36Sopenharmony_ci	ret = ext4_xattr_block_list(dentry, buffer, buffer_size);
83462306a36Sopenharmony_ci	if (ret < 0)
83562306a36Sopenharmony_ci		goto errout;
83662306a36Sopenharmony_ci	ret += ret2;
83762306a36Sopenharmony_cierrout:
83862306a36Sopenharmony_ci	up_read(&EXT4_I(d_inode(dentry))->xattr_sem);
83962306a36Sopenharmony_ci	return ret;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci/*
84362306a36Sopenharmony_ci * If the EXT4_FEATURE_COMPAT_EXT_ATTR feature of this file system is
84462306a36Sopenharmony_ci * not set, set it.
84562306a36Sopenharmony_ci */
84662306a36Sopenharmony_cistatic void ext4_xattr_update_super_block(handle_t *handle,
84762306a36Sopenharmony_ci					  struct super_block *sb)
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	if (ext4_has_feature_xattr(sb))
85062306a36Sopenharmony_ci		return;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
85362306a36Sopenharmony_ci	if (ext4_journal_get_write_access(handle, sb, EXT4_SB(sb)->s_sbh,
85462306a36Sopenharmony_ci					  EXT4_JTR_NONE) == 0) {
85562306a36Sopenharmony_ci		lock_buffer(EXT4_SB(sb)->s_sbh);
85662306a36Sopenharmony_ci		ext4_set_feature_xattr(sb);
85762306a36Sopenharmony_ci		ext4_superblock_csum_set(sb);
85862306a36Sopenharmony_ci		unlock_buffer(EXT4_SB(sb)->s_sbh);
85962306a36Sopenharmony_ci		ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ciint ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	struct ext4_iloc iloc = { .bh = NULL };
86662306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
86762306a36Sopenharmony_ci	struct ext4_inode *raw_inode;
86862306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
86962306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
87062306a36Sopenharmony_ci	qsize_t ea_inode_refs = 0;
87162306a36Sopenharmony_ci	void *end;
87262306a36Sopenharmony_ci	int ret;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	lockdep_assert_held_read(&EXT4_I(inode)->xattr_sem);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
87762306a36Sopenharmony_ci		ret = ext4_get_inode_loc(inode, &iloc);
87862306a36Sopenharmony_ci		if (ret)
87962306a36Sopenharmony_ci			goto out;
88062306a36Sopenharmony_ci		raw_inode = ext4_raw_inode(&iloc);
88162306a36Sopenharmony_ci		header = IHDR(inode, raw_inode);
88262306a36Sopenharmony_ci		end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
88362306a36Sopenharmony_ci		ret = xattr_check_inode(inode, header, end);
88462306a36Sopenharmony_ci		if (ret)
88562306a36Sopenharmony_ci			goto out;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci		for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
88862306a36Sopenharmony_ci		     entry = EXT4_XATTR_NEXT(entry))
88962306a36Sopenharmony_ci			if (entry->e_value_inum)
89062306a36Sopenharmony_ci				ea_inode_refs++;
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	if (EXT4_I(inode)->i_file_acl) {
89462306a36Sopenharmony_ci		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
89562306a36Sopenharmony_ci		if (IS_ERR(bh)) {
89662306a36Sopenharmony_ci			ret = PTR_ERR(bh);
89762306a36Sopenharmony_ci			bh = NULL;
89862306a36Sopenharmony_ci			goto out;
89962306a36Sopenharmony_ci		}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci		ret = ext4_xattr_check_block(inode, bh);
90262306a36Sopenharmony_ci		if (ret)
90362306a36Sopenharmony_ci			goto out;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci		for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry);
90662306a36Sopenharmony_ci		     entry = EXT4_XATTR_NEXT(entry))
90762306a36Sopenharmony_ci			if (entry->e_value_inum)
90862306a36Sopenharmony_ci				ea_inode_refs++;
90962306a36Sopenharmony_ci	}
91062306a36Sopenharmony_ci	*usage = ea_inode_refs + 1;
91162306a36Sopenharmony_ci	ret = 0;
91262306a36Sopenharmony_ciout:
91362306a36Sopenharmony_ci	brelse(iloc.bh);
91462306a36Sopenharmony_ci	brelse(bh);
91562306a36Sopenharmony_ci	return ret;
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_cistatic inline size_t round_up_cluster(struct inode *inode, size_t length)
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci	struct super_block *sb = inode->i_sb;
92162306a36Sopenharmony_ci	size_t cluster_size = 1 << (EXT4_SB(sb)->s_cluster_bits +
92262306a36Sopenharmony_ci				    inode->i_blkbits);
92362306a36Sopenharmony_ci	size_t mask = ~(cluster_size - 1);
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	return (length + cluster_size - 1) & mask;
92662306a36Sopenharmony_ci}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_cistatic int ext4_xattr_inode_alloc_quota(struct inode *inode, size_t len)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	int err;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	err = dquot_alloc_inode(inode);
93362306a36Sopenharmony_ci	if (err)
93462306a36Sopenharmony_ci		return err;
93562306a36Sopenharmony_ci	err = dquot_alloc_space_nodirty(inode, round_up_cluster(inode, len));
93662306a36Sopenharmony_ci	if (err)
93762306a36Sopenharmony_ci		dquot_free_inode(inode);
93862306a36Sopenharmony_ci	return err;
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic void ext4_xattr_inode_free_quota(struct inode *parent,
94262306a36Sopenharmony_ci					struct inode *ea_inode,
94362306a36Sopenharmony_ci					size_t len)
94462306a36Sopenharmony_ci{
94562306a36Sopenharmony_ci	if (ea_inode &&
94662306a36Sopenharmony_ci	    ext4_test_inode_state(ea_inode, EXT4_STATE_LUSTRE_EA_INODE))
94762306a36Sopenharmony_ci		return;
94862306a36Sopenharmony_ci	dquot_free_space_nodirty(parent, round_up_cluster(parent, len));
94962306a36Sopenharmony_ci	dquot_free_inode(parent);
95062306a36Sopenharmony_ci}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ciint __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
95362306a36Sopenharmony_ci			     struct buffer_head *block_bh, size_t value_len,
95462306a36Sopenharmony_ci			     bool is_create)
95562306a36Sopenharmony_ci{
95662306a36Sopenharmony_ci	int credits;
95762306a36Sopenharmony_ci	int blocks;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	/*
96062306a36Sopenharmony_ci	 * 1) Owner inode update
96162306a36Sopenharmony_ci	 * 2) Ref count update on old xattr block
96262306a36Sopenharmony_ci	 * 3) new xattr block
96362306a36Sopenharmony_ci	 * 4) block bitmap update for new xattr block
96462306a36Sopenharmony_ci	 * 5) group descriptor for new xattr block
96562306a36Sopenharmony_ci	 * 6) block bitmap update for old xattr block
96662306a36Sopenharmony_ci	 * 7) group descriptor for old block
96762306a36Sopenharmony_ci	 *
96862306a36Sopenharmony_ci	 * 6 & 7 can happen if we have two racing threads T_a and T_b
96962306a36Sopenharmony_ci	 * which are each trying to set an xattr on inodes I_a and I_b
97062306a36Sopenharmony_ci	 * which were both initially sharing an xattr block.
97162306a36Sopenharmony_ci	 */
97262306a36Sopenharmony_ci	credits = 7;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	/* Quota updates. */
97562306a36Sopenharmony_ci	credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(sb);
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	/*
97862306a36Sopenharmony_ci	 * In case of inline data, we may push out the data to a block,
97962306a36Sopenharmony_ci	 * so we need to reserve credits for this eventuality
98062306a36Sopenharmony_ci	 */
98162306a36Sopenharmony_ci	if (inode && ext4_has_inline_data(inode))
98262306a36Sopenharmony_ci		credits += ext4_writepage_trans_blocks(inode) + 1;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	/* We are done if ea_inode feature is not enabled. */
98562306a36Sopenharmony_ci	if (!ext4_has_feature_ea_inode(sb))
98662306a36Sopenharmony_ci		return credits;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	/* New ea_inode, inode map, block bitmap, group descriptor. */
98962306a36Sopenharmony_ci	credits += 4;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	/* Data blocks. */
99262306a36Sopenharmony_ci	blocks = (value_len + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	/* Indirection block or one level of extent tree. */
99562306a36Sopenharmony_ci	blocks += 1;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	/* Block bitmap and group descriptor updates for each block. */
99862306a36Sopenharmony_ci	credits += blocks * 2;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	/* Blocks themselves. */
100162306a36Sopenharmony_ci	credits += blocks;
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	if (!is_create) {
100462306a36Sopenharmony_ci		/* Dereference ea_inode holding old xattr value.
100562306a36Sopenharmony_ci		 * Old ea_inode, inode map, block bitmap, group descriptor.
100662306a36Sopenharmony_ci		 */
100762306a36Sopenharmony_ci		credits += 4;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci		/* Data blocks for old ea_inode. */
101062306a36Sopenharmony_ci		blocks = XATTR_SIZE_MAX >> sb->s_blocksize_bits;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci		/* Indirection block or one level of extent tree for old
101362306a36Sopenharmony_ci		 * ea_inode.
101462306a36Sopenharmony_ci		 */
101562306a36Sopenharmony_ci		blocks += 1;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci		/* Block bitmap and group descriptor updates for each block. */
101862306a36Sopenharmony_ci		credits += blocks * 2;
101962306a36Sopenharmony_ci	}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	/* We may need to clone the existing xattr block in which case we need
102262306a36Sopenharmony_ci	 * to increment ref counts for existing ea_inodes referenced by it.
102362306a36Sopenharmony_ci	 */
102462306a36Sopenharmony_ci	if (block_bh) {
102562306a36Sopenharmony_ci		struct ext4_xattr_entry *entry = BFIRST(block_bh);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci		for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry))
102862306a36Sopenharmony_ci			if (entry->e_value_inum)
102962306a36Sopenharmony_ci				/* Ref count update on ea_inode. */
103062306a36Sopenharmony_ci				credits += 1;
103162306a36Sopenharmony_ci	}
103262306a36Sopenharmony_ci	return credits;
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_cistatic int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
103662306a36Sopenharmony_ci				       int ref_change)
103762306a36Sopenharmony_ci{
103862306a36Sopenharmony_ci	struct ext4_iloc iloc;
103962306a36Sopenharmony_ci	s64 ref_count;
104062306a36Sopenharmony_ci	int ret;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	inode_lock(ea_inode);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	ret = ext4_reserve_inode_write(handle, ea_inode, &iloc);
104562306a36Sopenharmony_ci	if (ret)
104662306a36Sopenharmony_ci		goto out;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	ref_count = ext4_xattr_inode_get_ref(ea_inode);
104962306a36Sopenharmony_ci	ref_count += ref_change;
105062306a36Sopenharmony_ci	ext4_xattr_inode_set_ref(ea_inode, ref_count);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	if (ref_change > 0) {
105362306a36Sopenharmony_ci		WARN_ONCE(ref_count <= 0, "EA inode %lu ref_count=%lld",
105462306a36Sopenharmony_ci			  ea_inode->i_ino, ref_count);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci		if (ref_count == 1) {
105762306a36Sopenharmony_ci			WARN_ONCE(ea_inode->i_nlink, "EA inode %lu i_nlink=%u",
105862306a36Sopenharmony_ci				  ea_inode->i_ino, ea_inode->i_nlink);
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci			set_nlink(ea_inode, 1);
106162306a36Sopenharmony_ci			ext4_orphan_del(handle, ea_inode);
106262306a36Sopenharmony_ci		}
106362306a36Sopenharmony_ci	} else {
106462306a36Sopenharmony_ci		WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld",
106562306a36Sopenharmony_ci			  ea_inode->i_ino, ref_count);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci		if (ref_count == 0) {
106862306a36Sopenharmony_ci			WARN_ONCE(ea_inode->i_nlink != 1,
106962306a36Sopenharmony_ci				  "EA inode %lu i_nlink=%u",
107062306a36Sopenharmony_ci				  ea_inode->i_ino, ea_inode->i_nlink);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci			clear_nlink(ea_inode);
107362306a36Sopenharmony_ci			ext4_orphan_add(handle, ea_inode);
107462306a36Sopenharmony_ci		}
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	ret = ext4_mark_iloc_dirty(handle, ea_inode, &iloc);
107862306a36Sopenharmony_ci	if (ret)
107962306a36Sopenharmony_ci		ext4_warning_inode(ea_inode,
108062306a36Sopenharmony_ci				   "ext4_mark_iloc_dirty() failed ret=%d", ret);
108162306a36Sopenharmony_ciout:
108262306a36Sopenharmony_ci	inode_unlock(ea_inode);
108362306a36Sopenharmony_ci	return ret;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_cistatic int ext4_xattr_inode_inc_ref(handle_t *handle, struct inode *ea_inode)
108762306a36Sopenharmony_ci{
108862306a36Sopenharmony_ci	return ext4_xattr_inode_update_ref(handle, ea_inode, 1);
108962306a36Sopenharmony_ci}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_cistatic int ext4_xattr_inode_dec_ref(handle_t *handle, struct inode *ea_inode)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	return ext4_xattr_inode_update_ref(handle, ea_inode, -1);
109462306a36Sopenharmony_ci}
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_cistatic int ext4_xattr_inode_inc_ref_all(handle_t *handle, struct inode *parent,
109762306a36Sopenharmony_ci					struct ext4_xattr_entry *first)
109862306a36Sopenharmony_ci{
109962306a36Sopenharmony_ci	struct inode *ea_inode;
110062306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
110162306a36Sopenharmony_ci	struct ext4_xattr_entry *failed_entry;
110262306a36Sopenharmony_ci	unsigned int ea_ino;
110362306a36Sopenharmony_ci	int err, saved_err;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	for (entry = first; !IS_LAST_ENTRY(entry);
110662306a36Sopenharmony_ci	     entry = EXT4_XATTR_NEXT(entry)) {
110762306a36Sopenharmony_ci		if (!entry->e_value_inum)
110862306a36Sopenharmony_ci			continue;
110962306a36Sopenharmony_ci		ea_ino = le32_to_cpu(entry->e_value_inum);
111062306a36Sopenharmony_ci		err = ext4_xattr_inode_iget(parent, ea_ino,
111162306a36Sopenharmony_ci					    le32_to_cpu(entry->e_hash),
111262306a36Sopenharmony_ci					    &ea_inode);
111362306a36Sopenharmony_ci		if (err)
111462306a36Sopenharmony_ci			goto cleanup;
111562306a36Sopenharmony_ci		err = ext4_xattr_inode_inc_ref(handle, ea_inode);
111662306a36Sopenharmony_ci		if (err) {
111762306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "inc ref error %d", err);
111862306a36Sopenharmony_ci			iput(ea_inode);
111962306a36Sopenharmony_ci			goto cleanup;
112062306a36Sopenharmony_ci		}
112162306a36Sopenharmony_ci		iput(ea_inode);
112262306a36Sopenharmony_ci	}
112362306a36Sopenharmony_ci	return 0;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_cicleanup:
112662306a36Sopenharmony_ci	saved_err = err;
112762306a36Sopenharmony_ci	failed_entry = entry;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	for (entry = first; entry != failed_entry;
113062306a36Sopenharmony_ci	     entry = EXT4_XATTR_NEXT(entry)) {
113162306a36Sopenharmony_ci		if (!entry->e_value_inum)
113262306a36Sopenharmony_ci			continue;
113362306a36Sopenharmony_ci		ea_ino = le32_to_cpu(entry->e_value_inum);
113462306a36Sopenharmony_ci		err = ext4_xattr_inode_iget(parent, ea_ino,
113562306a36Sopenharmony_ci					    le32_to_cpu(entry->e_hash),
113662306a36Sopenharmony_ci					    &ea_inode);
113762306a36Sopenharmony_ci		if (err) {
113862306a36Sopenharmony_ci			ext4_warning(parent->i_sb,
113962306a36Sopenharmony_ci				     "cleanup ea_ino %u iget error %d", ea_ino,
114062306a36Sopenharmony_ci				     err);
114162306a36Sopenharmony_ci			continue;
114262306a36Sopenharmony_ci		}
114362306a36Sopenharmony_ci		err = ext4_xattr_inode_dec_ref(handle, ea_inode);
114462306a36Sopenharmony_ci		if (err)
114562306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "cleanup dec ref error %d",
114662306a36Sopenharmony_ci					   err);
114762306a36Sopenharmony_ci		iput(ea_inode);
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci	return saved_err;
115062306a36Sopenharmony_ci}
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_cistatic int ext4_xattr_restart_fn(handle_t *handle, struct inode *inode,
115362306a36Sopenharmony_ci			struct buffer_head *bh, bool block_csum, bool dirty)
115462306a36Sopenharmony_ci{
115562306a36Sopenharmony_ci	int error;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	if (bh && dirty) {
115862306a36Sopenharmony_ci		if (block_csum)
115962306a36Sopenharmony_ci			ext4_xattr_block_csum_set(inode, bh);
116062306a36Sopenharmony_ci		error = ext4_handle_dirty_metadata(handle, NULL, bh);
116162306a36Sopenharmony_ci		if (error) {
116262306a36Sopenharmony_ci			ext4_warning(inode->i_sb, "Handle metadata (error %d)",
116362306a36Sopenharmony_ci				     error);
116462306a36Sopenharmony_ci			return error;
116562306a36Sopenharmony_ci		}
116662306a36Sopenharmony_ci	}
116762306a36Sopenharmony_ci	return 0;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_cistatic void
117162306a36Sopenharmony_ciext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
117262306a36Sopenharmony_ci			     struct buffer_head *bh,
117362306a36Sopenharmony_ci			     struct ext4_xattr_entry *first, bool block_csum,
117462306a36Sopenharmony_ci			     struct ext4_xattr_inode_array **ea_inode_array,
117562306a36Sopenharmony_ci			     int extra_credits, bool skip_quota)
117662306a36Sopenharmony_ci{
117762306a36Sopenharmony_ci	struct inode *ea_inode;
117862306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
117962306a36Sopenharmony_ci	bool dirty = false;
118062306a36Sopenharmony_ci	unsigned int ea_ino;
118162306a36Sopenharmony_ci	int err;
118262306a36Sopenharmony_ci	int credits;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	/* One credit for dec ref on ea_inode, one for orphan list addition, */
118562306a36Sopenharmony_ci	credits = 2 + extra_credits;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	for (entry = first; !IS_LAST_ENTRY(entry);
118862306a36Sopenharmony_ci	     entry = EXT4_XATTR_NEXT(entry)) {
118962306a36Sopenharmony_ci		if (!entry->e_value_inum)
119062306a36Sopenharmony_ci			continue;
119162306a36Sopenharmony_ci		ea_ino = le32_to_cpu(entry->e_value_inum);
119262306a36Sopenharmony_ci		err = ext4_xattr_inode_iget(parent, ea_ino,
119362306a36Sopenharmony_ci					    le32_to_cpu(entry->e_hash),
119462306a36Sopenharmony_ci					    &ea_inode);
119562306a36Sopenharmony_ci		if (err)
119662306a36Sopenharmony_ci			continue;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		err = ext4_expand_inode_array(ea_inode_array, ea_inode);
119962306a36Sopenharmony_ci		if (err) {
120062306a36Sopenharmony_ci			ext4_warning_inode(ea_inode,
120162306a36Sopenharmony_ci					   "Expand inode array err=%d", err);
120262306a36Sopenharmony_ci			iput(ea_inode);
120362306a36Sopenharmony_ci			continue;
120462306a36Sopenharmony_ci		}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci		err = ext4_journal_ensure_credits_fn(handle, credits, credits,
120762306a36Sopenharmony_ci			ext4_free_metadata_revoke_credits(parent->i_sb, 1),
120862306a36Sopenharmony_ci			ext4_xattr_restart_fn(handle, parent, bh, block_csum,
120962306a36Sopenharmony_ci					      dirty));
121062306a36Sopenharmony_ci		if (err < 0) {
121162306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "Ensure credits err=%d",
121262306a36Sopenharmony_ci					   err);
121362306a36Sopenharmony_ci			continue;
121462306a36Sopenharmony_ci		}
121562306a36Sopenharmony_ci		if (err > 0) {
121662306a36Sopenharmony_ci			err = ext4_journal_get_write_access(handle,
121762306a36Sopenharmony_ci					parent->i_sb, bh, EXT4_JTR_NONE);
121862306a36Sopenharmony_ci			if (err) {
121962306a36Sopenharmony_ci				ext4_warning_inode(ea_inode,
122062306a36Sopenharmony_ci						"Re-get write access err=%d",
122162306a36Sopenharmony_ci						err);
122262306a36Sopenharmony_ci				continue;
122362306a36Sopenharmony_ci			}
122462306a36Sopenharmony_ci		}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci		err = ext4_xattr_inode_dec_ref(handle, ea_inode);
122762306a36Sopenharmony_ci		if (err) {
122862306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "ea_inode dec ref err=%d",
122962306a36Sopenharmony_ci					   err);
123062306a36Sopenharmony_ci			continue;
123162306a36Sopenharmony_ci		}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci		if (!skip_quota)
123462306a36Sopenharmony_ci			ext4_xattr_inode_free_quota(parent, ea_inode,
123562306a36Sopenharmony_ci					      le32_to_cpu(entry->e_value_size));
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci		/*
123862306a36Sopenharmony_ci		 * Forget about ea_inode within the same transaction that
123962306a36Sopenharmony_ci		 * decrements the ref count. This avoids duplicate decrements in
124062306a36Sopenharmony_ci		 * case the rest of the work spills over to subsequent
124162306a36Sopenharmony_ci		 * transactions.
124262306a36Sopenharmony_ci		 */
124362306a36Sopenharmony_ci		entry->e_value_inum = 0;
124462306a36Sopenharmony_ci		entry->e_value_size = 0;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci		dirty = true;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	if (dirty) {
125062306a36Sopenharmony_ci		/*
125162306a36Sopenharmony_ci		 * Note that we are deliberately skipping csum calculation for
125262306a36Sopenharmony_ci		 * the final update because we do not expect any journal
125362306a36Sopenharmony_ci		 * restarts until xattr block is freed.
125462306a36Sopenharmony_ci		 */
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci		err = ext4_handle_dirty_metadata(handle, NULL, bh);
125762306a36Sopenharmony_ci		if (err)
125862306a36Sopenharmony_ci			ext4_warning_inode(parent,
125962306a36Sopenharmony_ci					   "handle dirty metadata err=%d", err);
126062306a36Sopenharmony_ci	}
126162306a36Sopenharmony_ci}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci/*
126462306a36Sopenharmony_ci * Release the xattr block BH: If the reference count is > 1, decrement it;
126562306a36Sopenharmony_ci * otherwise free the block.
126662306a36Sopenharmony_ci */
126762306a36Sopenharmony_cistatic void
126862306a36Sopenharmony_ciext4_xattr_release_block(handle_t *handle, struct inode *inode,
126962306a36Sopenharmony_ci			 struct buffer_head *bh,
127062306a36Sopenharmony_ci			 struct ext4_xattr_inode_array **ea_inode_array,
127162306a36Sopenharmony_ci			 int extra_credits)
127262306a36Sopenharmony_ci{
127362306a36Sopenharmony_ci	struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
127462306a36Sopenharmony_ci	u32 hash, ref;
127562306a36Sopenharmony_ci	int error = 0;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	BUFFER_TRACE(bh, "get_write_access");
127862306a36Sopenharmony_ci	error = ext4_journal_get_write_access(handle, inode->i_sb, bh,
127962306a36Sopenharmony_ci					      EXT4_JTR_NONE);
128062306a36Sopenharmony_ci	if (error)
128162306a36Sopenharmony_ci		goto out;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ciretry_ref:
128462306a36Sopenharmony_ci	lock_buffer(bh);
128562306a36Sopenharmony_ci	hash = le32_to_cpu(BHDR(bh)->h_hash);
128662306a36Sopenharmony_ci	ref = le32_to_cpu(BHDR(bh)->h_refcount);
128762306a36Sopenharmony_ci	if (ref == 1) {
128862306a36Sopenharmony_ci		ea_bdebug(bh, "refcount now=0; freeing");
128962306a36Sopenharmony_ci		/*
129062306a36Sopenharmony_ci		 * This must happen under buffer lock for
129162306a36Sopenharmony_ci		 * ext4_xattr_block_set() to reliably detect freed block
129262306a36Sopenharmony_ci		 */
129362306a36Sopenharmony_ci		if (ea_block_cache) {
129462306a36Sopenharmony_ci			struct mb_cache_entry *oe;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci			oe = mb_cache_entry_delete_or_get(ea_block_cache, hash,
129762306a36Sopenharmony_ci							  bh->b_blocknr);
129862306a36Sopenharmony_ci			if (oe) {
129962306a36Sopenharmony_ci				unlock_buffer(bh);
130062306a36Sopenharmony_ci				mb_cache_entry_wait_unused(oe);
130162306a36Sopenharmony_ci				mb_cache_entry_put(ea_block_cache, oe);
130262306a36Sopenharmony_ci				goto retry_ref;
130362306a36Sopenharmony_ci			}
130462306a36Sopenharmony_ci		}
130562306a36Sopenharmony_ci		get_bh(bh);
130662306a36Sopenharmony_ci		unlock_buffer(bh);
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci		if (ext4_has_feature_ea_inode(inode->i_sb))
130962306a36Sopenharmony_ci			ext4_xattr_inode_dec_ref_all(handle, inode, bh,
131062306a36Sopenharmony_ci						     BFIRST(bh),
131162306a36Sopenharmony_ci						     true /* block_csum */,
131262306a36Sopenharmony_ci						     ea_inode_array,
131362306a36Sopenharmony_ci						     extra_credits,
131462306a36Sopenharmony_ci						     true /* skip_quota */);
131562306a36Sopenharmony_ci		ext4_free_blocks(handle, inode, bh, 0, 1,
131662306a36Sopenharmony_ci				 EXT4_FREE_BLOCKS_METADATA |
131762306a36Sopenharmony_ci				 EXT4_FREE_BLOCKS_FORGET);
131862306a36Sopenharmony_ci	} else {
131962306a36Sopenharmony_ci		ref--;
132062306a36Sopenharmony_ci		BHDR(bh)->h_refcount = cpu_to_le32(ref);
132162306a36Sopenharmony_ci		if (ref == EXT4_XATTR_REFCOUNT_MAX - 1) {
132262306a36Sopenharmony_ci			struct mb_cache_entry *ce;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci			if (ea_block_cache) {
132562306a36Sopenharmony_ci				ce = mb_cache_entry_get(ea_block_cache, hash,
132662306a36Sopenharmony_ci							bh->b_blocknr);
132762306a36Sopenharmony_ci				if (ce) {
132862306a36Sopenharmony_ci					set_bit(MBE_REUSABLE_B, &ce->e_flags);
132962306a36Sopenharmony_ci					mb_cache_entry_put(ea_block_cache, ce);
133062306a36Sopenharmony_ci				}
133162306a36Sopenharmony_ci			}
133262306a36Sopenharmony_ci		}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci		ext4_xattr_block_csum_set(inode, bh);
133562306a36Sopenharmony_ci		/*
133662306a36Sopenharmony_ci		 * Beware of this ugliness: Releasing of xattr block references
133762306a36Sopenharmony_ci		 * from different inodes can race and so we have to protect
133862306a36Sopenharmony_ci		 * from a race where someone else frees the block (and releases
133962306a36Sopenharmony_ci		 * its journal_head) before we are done dirtying the buffer. In
134062306a36Sopenharmony_ci		 * nojournal mode this race is harmless and we actually cannot
134162306a36Sopenharmony_ci		 * call ext4_handle_dirty_metadata() with locked buffer as
134262306a36Sopenharmony_ci		 * that function can call sync_dirty_buffer() so for that case
134362306a36Sopenharmony_ci		 * we handle the dirtying after unlocking the buffer.
134462306a36Sopenharmony_ci		 */
134562306a36Sopenharmony_ci		if (ext4_handle_valid(handle))
134662306a36Sopenharmony_ci			error = ext4_handle_dirty_metadata(handle, inode, bh);
134762306a36Sopenharmony_ci		unlock_buffer(bh);
134862306a36Sopenharmony_ci		if (!ext4_handle_valid(handle))
134962306a36Sopenharmony_ci			error = ext4_handle_dirty_metadata(handle, inode, bh);
135062306a36Sopenharmony_ci		if (IS_SYNC(inode))
135162306a36Sopenharmony_ci			ext4_handle_sync(handle);
135262306a36Sopenharmony_ci		dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
135362306a36Sopenharmony_ci		ea_bdebug(bh, "refcount now=%d; releasing",
135462306a36Sopenharmony_ci			  le32_to_cpu(BHDR(bh)->h_refcount));
135562306a36Sopenharmony_ci	}
135662306a36Sopenharmony_ciout:
135762306a36Sopenharmony_ci	ext4_std_error(inode->i_sb, error);
135862306a36Sopenharmony_ci	return;
135962306a36Sopenharmony_ci}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci/*
136262306a36Sopenharmony_ci * Find the available free space for EAs. This also returns the total number of
136362306a36Sopenharmony_ci * bytes used by EA entries.
136462306a36Sopenharmony_ci */
136562306a36Sopenharmony_cistatic size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
136662306a36Sopenharmony_ci				    size_t *min_offs, void *base, int *total)
136762306a36Sopenharmony_ci{
136862306a36Sopenharmony_ci	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
136962306a36Sopenharmony_ci		if (!last->e_value_inum && last->e_value_size) {
137062306a36Sopenharmony_ci			size_t offs = le16_to_cpu(last->e_value_offs);
137162306a36Sopenharmony_ci			if (offs < *min_offs)
137262306a36Sopenharmony_ci				*min_offs = offs;
137362306a36Sopenharmony_ci		}
137462306a36Sopenharmony_ci		if (total)
137562306a36Sopenharmony_ci			*total += EXT4_XATTR_LEN(last->e_name_len);
137662306a36Sopenharmony_ci	}
137762306a36Sopenharmony_ci	return (*min_offs - ((void *)last - base) - sizeof(__u32));
137862306a36Sopenharmony_ci}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci/*
138162306a36Sopenharmony_ci * Write the value of the EA in an inode.
138262306a36Sopenharmony_ci */
138362306a36Sopenharmony_cistatic int ext4_xattr_inode_write(handle_t *handle, struct inode *ea_inode,
138462306a36Sopenharmony_ci				  const void *buf, int bufsize)
138562306a36Sopenharmony_ci{
138662306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
138762306a36Sopenharmony_ci	unsigned long block = 0;
138862306a36Sopenharmony_ci	int blocksize = ea_inode->i_sb->s_blocksize;
138962306a36Sopenharmony_ci	int max_blocks = (bufsize + blocksize - 1) >> ea_inode->i_blkbits;
139062306a36Sopenharmony_ci	int csize, wsize = 0;
139162306a36Sopenharmony_ci	int ret = 0, ret2 = 0;
139262306a36Sopenharmony_ci	int retries = 0;
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ciretry:
139562306a36Sopenharmony_ci	while (ret >= 0 && ret < max_blocks) {
139662306a36Sopenharmony_ci		struct ext4_map_blocks map;
139762306a36Sopenharmony_ci		map.m_lblk = block += ret;
139862306a36Sopenharmony_ci		map.m_len = max_blocks -= ret;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci		ret = ext4_map_blocks(handle, ea_inode, &map,
140162306a36Sopenharmony_ci				      EXT4_GET_BLOCKS_CREATE);
140262306a36Sopenharmony_ci		if (ret <= 0) {
140362306a36Sopenharmony_ci			ext4_mark_inode_dirty(handle, ea_inode);
140462306a36Sopenharmony_ci			if (ret == -ENOSPC &&
140562306a36Sopenharmony_ci			    ext4_should_retry_alloc(ea_inode->i_sb, &retries)) {
140662306a36Sopenharmony_ci				ret = 0;
140762306a36Sopenharmony_ci				goto retry;
140862306a36Sopenharmony_ci			}
140962306a36Sopenharmony_ci			break;
141062306a36Sopenharmony_ci		}
141162306a36Sopenharmony_ci	}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	if (ret < 0)
141462306a36Sopenharmony_ci		return ret;
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	block = 0;
141762306a36Sopenharmony_ci	while (wsize < bufsize) {
141862306a36Sopenharmony_ci		brelse(bh);
141962306a36Sopenharmony_ci		csize = (bufsize - wsize) > blocksize ? blocksize :
142062306a36Sopenharmony_ci								bufsize - wsize;
142162306a36Sopenharmony_ci		bh = ext4_getblk(handle, ea_inode, block, 0);
142262306a36Sopenharmony_ci		if (IS_ERR(bh))
142362306a36Sopenharmony_ci			return PTR_ERR(bh);
142462306a36Sopenharmony_ci		if (!bh) {
142562306a36Sopenharmony_ci			WARN_ON_ONCE(1);
142662306a36Sopenharmony_ci			EXT4_ERROR_INODE(ea_inode,
142762306a36Sopenharmony_ci					 "ext4_getblk() return bh = NULL");
142862306a36Sopenharmony_ci			return -EFSCORRUPTED;
142962306a36Sopenharmony_ci		}
143062306a36Sopenharmony_ci		ret = ext4_journal_get_write_access(handle, ea_inode->i_sb, bh,
143162306a36Sopenharmony_ci						   EXT4_JTR_NONE);
143262306a36Sopenharmony_ci		if (ret)
143362306a36Sopenharmony_ci			goto out;
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci		memcpy(bh->b_data, buf, csize);
143662306a36Sopenharmony_ci		set_buffer_uptodate(bh);
143762306a36Sopenharmony_ci		ext4_handle_dirty_metadata(handle, ea_inode, bh);
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci		buf += csize;
144062306a36Sopenharmony_ci		wsize += csize;
144162306a36Sopenharmony_ci		block += 1;
144262306a36Sopenharmony_ci	}
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	inode_lock(ea_inode);
144562306a36Sopenharmony_ci	i_size_write(ea_inode, wsize);
144662306a36Sopenharmony_ci	ext4_update_i_disksize(ea_inode, wsize);
144762306a36Sopenharmony_ci	inode_unlock(ea_inode);
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	ret2 = ext4_mark_inode_dirty(handle, ea_inode);
145062306a36Sopenharmony_ci	if (unlikely(ret2 && !ret))
145162306a36Sopenharmony_ci		ret = ret2;
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ciout:
145462306a36Sopenharmony_ci	brelse(bh);
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	return ret;
145762306a36Sopenharmony_ci}
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci/*
146062306a36Sopenharmony_ci * Create an inode to store the value of a large EA.
146162306a36Sopenharmony_ci */
146262306a36Sopenharmony_cistatic struct inode *ext4_xattr_inode_create(handle_t *handle,
146362306a36Sopenharmony_ci					     struct inode *inode, u32 hash)
146462306a36Sopenharmony_ci{
146562306a36Sopenharmony_ci	struct inode *ea_inode = NULL;
146662306a36Sopenharmony_ci	uid_t owner[2] = { i_uid_read(inode), i_gid_read(inode) };
146762306a36Sopenharmony_ci	int err;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	if (inode->i_sb->s_root == NULL) {
147062306a36Sopenharmony_ci		ext4_warning(inode->i_sb,
147162306a36Sopenharmony_ci			     "refuse to create EA inode when umounting");
147262306a36Sopenharmony_ci		WARN_ON(1);
147362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
147462306a36Sopenharmony_ci	}
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	/*
147762306a36Sopenharmony_ci	 * Let the next inode be the goal, so we try and allocate the EA inode
147862306a36Sopenharmony_ci	 * in the same group, or nearby one.
147962306a36Sopenharmony_ci	 */
148062306a36Sopenharmony_ci	ea_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
148162306a36Sopenharmony_ci				  S_IFREG | 0600, NULL, inode->i_ino + 1, owner,
148262306a36Sopenharmony_ci				  EXT4_EA_INODE_FL);
148362306a36Sopenharmony_ci	if (!IS_ERR(ea_inode)) {
148462306a36Sopenharmony_ci		ea_inode->i_op = &ext4_file_inode_operations;
148562306a36Sopenharmony_ci		ea_inode->i_fop = &ext4_file_operations;
148662306a36Sopenharmony_ci		ext4_set_aops(ea_inode);
148762306a36Sopenharmony_ci		ext4_xattr_inode_set_class(ea_inode);
148862306a36Sopenharmony_ci		unlock_new_inode(ea_inode);
148962306a36Sopenharmony_ci		ext4_xattr_inode_set_ref(ea_inode, 1);
149062306a36Sopenharmony_ci		ext4_xattr_inode_set_hash(ea_inode, hash);
149162306a36Sopenharmony_ci		err = ext4_mark_inode_dirty(handle, ea_inode);
149262306a36Sopenharmony_ci		if (!err)
149362306a36Sopenharmony_ci			err = ext4_inode_attach_jinode(ea_inode);
149462306a36Sopenharmony_ci		if (err) {
149562306a36Sopenharmony_ci			if (ext4_xattr_inode_dec_ref(handle, ea_inode))
149662306a36Sopenharmony_ci				ext4_warning_inode(ea_inode,
149762306a36Sopenharmony_ci					"cleanup dec ref error %d", err);
149862306a36Sopenharmony_ci			iput(ea_inode);
149962306a36Sopenharmony_ci			return ERR_PTR(err);
150062306a36Sopenharmony_ci		}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci		/*
150362306a36Sopenharmony_ci		 * Xattr inodes are shared therefore quota charging is performed
150462306a36Sopenharmony_ci		 * at a higher level.
150562306a36Sopenharmony_ci		 */
150662306a36Sopenharmony_ci		dquot_free_inode(ea_inode);
150762306a36Sopenharmony_ci		dquot_drop(ea_inode);
150862306a36Sopenharmony_ci		inode_lock(ea_inode);
150962306a36Sopenharmony_ci		ea_inode->i_flags |= S_NOQUOTA;
151062306a36Sopenharmony_ci		inode_unlock(ea_inode);
151162306a36Sopenharmony_ci	}
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	return ea_inode;
151462306a36Sopenharmony_ci}
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_cistatic struct inode *
151762306a36Sopenharmony_ciext4_xattr_inode_cache_find(struct inode *inode, const void *value,
151862306a36Sopenharmony_ci			    size_t value_len, u32 hash)
151962306a36Sopenharmony_ci{
152062306a36Sopenharmony_ci	struct inode *ea_inode;
152162306a36Sopenharmony_ci	struct mb_cache_entry *ce;
152262306a36Sopenharmony_ci	struct mb_cache *ea_inode_cache = EA_INODE_CACHE(inode);
152362306a36Sopenharmony_ci	void *ea_data;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	if (!ea_inode_cache)
152662306a36Sopenharmony_ci		return NULL;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	ce = mb_cache_entry_find_first(ea_inode_cache, hash);
152962306a36Sopenharmony_ci	if (!ce)
153062306a36Sopenharmony_ci		return NULL;
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	WARN_ON_ONCE(ext4_handle_valid(journal_current_handle()) &&
153362306a36Sopenharmony_ci		     !(current->flags & PF_MEMALLOC_NOFS));
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	ea_data = kvmalloc(value_len, GFP_KERNEL);
153662306a36Sopenharmony_ci	if (!ea_data) {
153762306a36Sopenharmony_ci		mb_cache_entry_put(ea_inode_cache, ce);
153862306a36Sopenharmony_ci		return NULL;
153962306a36Sopenharmony_ci	}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	while (ce) {
154262306a36Sopenharmony_ci		ea_inode = ext4_iget(inode->i_sb, ce->e_value,
154362306a36Sopenharmony_ci				     EXT4_IGET_EA_INODE);
154462306a36Sopenharmony_ci		if (IS_ERR(ea_inode))
154562306a36Sopenharmony_ci			goto next_entry;
154662306a36Sopenharmony_ci		ext4_xattr_inode_set_class(ea_inode);
154762306a36Sopenharmony_ci		if (i_size_read(ea_inode) == value_len &&
154862306a36Sopenharmony_ci		    !ext4_xattr_inode_read(ea_inode, ea_data, value_len) &&
154962306a36Sopenharmony_ci		    !ext4_xattr_inode_verify_hashes(ea_inode, NULL, ea_data,
155062306a36Sopenharmony_ci						    value_len) &&
155162306a36Sopenharmony_ci		    !memcmp(value, ea_data, value_len)) {
155262306a36Sopenharmony_ci			mb_cache_entry_touch(ea_inode_cache, ce);
155362306a36Sopenharmony_ci			mb_cache_entry_put(ea_inode_cache, ce);
155462306a36Sopenharmony_ci			kvfree(ea_data);
155562306a36Sopenharmony_ci			return ea_inode;
155662306a36Sopenharmony_ci		}
155762306a36Sopenharmony_ci		iput(ea_inode);
155862306a36Sopenharmony_ci	next_entry:
155962306a36Sopenharmony_ci		ce = mb_cache_entry_find_next(ea_inode_cache, ce);
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci	kvfree(ea_data);
156262306a36Sopenharmony_ci	return NULL;
156362306a36Sopenharmony_ci}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci/*
156662306a36Sopenharmony_ci * Add value of the EA in an inode.
156762306a36Sopenharmony_ci */
156862306a36Sopenharmony_cistatic int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode,
156962306a36Sopenharmony_ci					  const void *value, size_t value_len,
157062306a36Sopenharmony_ci					  struct inode **ret_inode)
157162306a36Sopenharmony_ci{
157262306a36Sopenharmony_ci	struct inode *ea_inode;
157362306a36Sopenharmony_ci	u32 hash;
157462306a36Sopenharmony_ci	int err;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	hash = ext4_xattr_inode_hash(EXT4_SB(inode->i_sb), value, value_len);
157762306a36Sopenharmony_ci	ea_inode = ext4_xattr_inode_cache_find(inode, value, value_len, hash);
157862306a36Sopenharmony_ci	if (ea_inode) {
157962306a36Sopenharmony_ci		err = ext4_xattr_inode_inc_ref(handle, ea_inode);
158062306a36Sopenharmony_ci		if (err) {
158162306a36Sopenharmony_ci			iput(ea_inode);
158262306a36Sopenharmony_ci			return err;
158362306a36Sopenharmony_ci		}
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci		*ret_inode = ea_inode;
158662306a36Sopenharmony_ci		return 0;
158762306a36Sopenharmony_ci	}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	/* Create an inode for the EA value */
159062306a36Sopenharmony_ci	ea_inode = ext4_xattr_inode_create(handle, inode, hash);
159162306a36Sopenharmony_ci	if (IS_ERR(ea_inode))
159262306a36Sopenharmony_ci		return PTR_ERR(ea_inode);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	err = ext4_xattr_inode_write(handle, ea_inode, value, value_len);
159562306a36Sopenharmony_ci	if (err) {
159662306a36Sopenharmony_ci		if (ext4_xattr_inode_dec_ref(handle, ea_inode))
159762306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "cleanup dec ref error %d", err);
159862306a36Sopenharmony_ci		iput(ea_inode);
159962306a36Sopenharmony_ci		return err;
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	if (EA_INODE_CACHE(inode))
160362306a36Sopenharmony_ci		mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash,
160462306a36Sopenharmony_ci				      ea_inode->i_ino, true /* reusable */);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	*ret_inode = ea_inode;
160762306a36Sopenharmony_ci	return 0;
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci/*
161162306a36Sopenharmony_ci * Reserve min(block_size/8, 1024) bytes for xattr entries/names if ea_inode
161262306a36Sopenharmony_ci * feature is enabled.
161362306a36Sopenharmony_ci */
161462306a36Sopenharmony_ci#define EXT4_XATTR_BLOCK_RESERVE(inode)	min(i_blocksize(inode)/8, 1024U)
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_cistatic int ext4_xattr_set_entry(struct ext4_xattr_info *i,
161762306a36Sopenharmony_ci				struct ext4_xattr_search *s,
161862306a36Sopenharmony_ci				handle_t *handle, struct inode *inode,
161962306a36Sopenharmony_ci				bool is_block)
162062306a36Sopenharmony_ci{
162162306a36Sopenharmony_ci	struct ext4_xattr_entry *last, *next;
162262306a36Sopenharmony_ci	struct ext4_xattr_entry *here = s->here;
162362306a36Sopenharmony_ci	size_t min_offs = s->end - s->base, name_len = strlen(i->name);
162462306a36Sopenharmony_ci	int in_inode = i->in_inode;
162562306a36Sopenharmony_ci	struct inode *old_ea_inode = NULL;
162662306a36Sopenharmony_ci	struct inode *new_ea_inode = NULL;
162762306a36Sopenharmony_ci	size_t old_size, new_size;
162862306a36Sopenharmony_ci	int ret;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	/* Space used by old and new values. */
163162306a36Sopenharmony_ci	old_size = (!s->not_found && !here->e_value_inum) ?
163262306a36Sopenharmony_ci			EXT4_XATTR_SIZE(le32_to_cpu(here->e_value_size)) : 0;
163362306a36Sopenharmony_ci	new_size = (i->value && !in_inode) ? EXT4_XATTR_SIZE(i->value_len) : 0;
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	/*
163662306a36Sopenharmony_ci	 * Optimization for the simple case when old and new values have the
163762306a36Sopenharmony_ci	 * same padded sizes. Not applicable if external inodes are involved.
163862306a36Sopenharmony_ci	 */
163962306a36Sopenharmony_ci	if (new_size && new_size == old_size) {
164062306a36Sopenharmony_ci		size_t offs = le16_to_cpu(here->e_value_offs);
164162306a36Sopenharmony_ci		void *val = s->base + offs;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci		here->e_value_size = cpu_to_le32(i->value_len);
164462306a36Sopenharmony_ci		if (i->value == EXT4_ZERO_XATTR_VALUE) {
164562306a36Sopenharmony_ci			memset(val, 0, new_size);
164662306a36Sopenharmony_ci		} else {
164762306a36Sopenharmony_ci			memcpy(val, i->value, i->value_len);
164862306a36Sopenharmony_ci			/* Clear padding bytes. */
164962306a36Sopenharmony_ci			memset(val + i->value_len, 0, new_size - i->value_len);
165062306a36Sopenharmony_ci		}
165162306a36Sopenharmony_ci		goto update_hash;
165262306a36Sopenharmony_ci	}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	/* Compute min_offs and last. */
165562306a36Sopenharmony_ci	last = s->first;
165662306a36Sopenharmony_ci	for (; !IS_LAST_ENTRY(last); last = next) {
165762306a36Sopenharmony_ci		next = EXT4_XATTR_NEXT(last);
165862306a36Sopenharmony_ci		if ((void *)next >= s->end) {
165962306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "corrupted xattr entries");
166062306a36Sopenharmony_ci			ret = -EFSCORRUPTED;
166162306a36Sopenharmony_ci			goto out;
166262306a36Sopenharmony_ci		}
166362306a36Sopenharmony_ci		if (!last->e_value_inum && last->e_value_size) {
166462306a36Sopenharmony_ci			size_t offs = le16_to_cpu(last->e_value_offs);
166562306a36Sopenharmony_ci			if (offs < min_offs)
166662306a36Sopenharmony_ci				min_offs = offs;
166762306a36Sopenharmony_ci		}
166862306a36Sopenharmony_ci	}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/* Check whether we have enough space. */
167162306a36Sopenharmony_ci	if (i->value) {
167262306a36Sopenharmony_ci		size_t free;
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci		free = min_offs - ((void *)last - s->base) - sizeof(__u32);
167562306a36Sopenharmony_ci		if (!s->not_found)
167662306a36Sopenharmony_ci			free += EXT4_XATTR_LEN(name_len) + old_size;
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci		if (free < EXT4_XATTR_LEN(name_len) + new_size) {
167962306a36Sopenharmony_ci			ret = -ENOSPC;
168062306a36Sopenharmony_ci			goto out;
168162306a36Sopenharmony_ci		}
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci		/*
168462306a36Sopenharmony_ci		 * If storing the value in an external inode is an option,
168562306a36Sopenharmony_ci		 * reserve space for xattr entries/names in the external
168662306a36Sopenharmony_ci		 * attribute block so that a long value does not occupy the
168762306a36Sopenharmony_ci		 * whole space and prevent further entries being added.
168862306a36Sopenharmony_ci		 */
168962306a36Sopenharmony_ci		if (ext4_has_feature_ea_inode(inode->i_sb) &&
169062306a36Sopenharmony_ci		    new_size && is_block &&
169162306a36Sopenharmony_ci		    (min_offs + old_size - new_size) <
169262306a36Sopenharmony_ci					EXT4_XATTR_BLOCK_RESERVE(inode)) {
169362306a36Sopenharmony_ci			ret = -ENOSPC;
169462306a36Sopenharmony_ci			goto out;
169562306a36Sopenharmony_ci		}
169662306a36Sopenharmony_ci	}
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	/*
169962306a36Sopenharmony_ci	 * Getting access to old and new ea inodes is subject to failures.
170062306a36Sopenharmony_ci	 * Finish that work before doing any modifications to the xattr data.
170162306a36Sopenharmony_ci	 */
170262306a36Sopenharmony_ci	if (!s->not_found && here->e_value_inum) {
170362306a36Sopenharmony_ci		ret = ext4_xattr_inode_iget(inode,
170462306a36Sopenharmony_ci					    le32_to_cpu(here->e_value_inum),
170562306a36Sopenharmony_ci					    le32_to_cpu(here->e_hash),
170662306a36Sopenharmony_ci					    &old_ea_inode);
170762306a36Sopenharmony_ci		if (ret) {
170862306a36Sopenharmony_ci			old_ea_inode = NULL;
170962306a36Sopenharmony_ci			goto out;
171062306a36Sopenharmony_ci		}
171162306a36Sopenharmony_ci	}
171262306a36Sopenharmony_ci	if (i->value && in_inode) {
171362306a36Sopenharmony_ci		WARN_ON_ONCE(!i->value_len);
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci		ret = ext4_xattr_inode_alloc_quota(inode, i->value_len);
171662306a36Sopenharmony_ci		if (ret)
171762306a36Sopenharmony_ci			goto out;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci		ret = ext4_xattr_inode_lookup_create(handle, inode, i->value,
172062306a36Sopenharmony_ci						     i->value_len,
172162306a36Sopenharmony_ci						     &new_ea_inode);
172262306a36Sopenharmony_ci		if (ret) {
172362306a36Sopenharmony_ci			new_ea_inode = NULL;
172462306a36Sopenharmony_ci			ext4_xattr_inode_free_quota(inode, NULL, i->value_len);
172562306a36Sopenharmony_ci			goto out;
172662306a36Sopenharmony_ci		}
172762306a36Sopenharmony_ci	}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	if (old_ea_inode) {
173062306a36Sopenharmony_ci		/* We are ready to release ref count on the old_ea_inode. */
173162306a36Sopenharmony_ci		ret = ext4_xattr_inode_dec_ref(handle, old_ea_inode);
173262306a36Sopenharmony_ci		if (ret) {
173362306a36Sopenharmony_ci			/* Release newly required ref count on new_ea_inode. */
173462306a36Sopenharmony_ci			if (new_ea_inode) {
173562306a36Sopenharmony_ci				int err;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci				err = ext4_xattr_inode_dec_ref(handle,
173862306a36Sopenharmony_ci							       new_ea_inode);
173962306a36Sopenharmony_ci				if (err)
174062306a36Sopenharmony_ci					ext4_warning_inode(new_ea_inode,
174162306a36Sopenharmony_ci						  "dec ref new_ea_inode err=%d",
174262306a36Sopenharmony_ci						  err);
174362306a36Sopenharmony_ci				ext4_xattr_inode_free_quota(inode, new_ea_inode,
174462306a36Sopenharmony_ci							    i->value_len);
174562306a36Sopenharmony_ci			}
174662306a36Sopenharmony_ci			goto out;
174762306a36Sopenharmony_ci		}
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci		ext4_xattr_inode_free_quota(inode, old_ea_inode,
175062306a36Sopenharmony_ci					    le32_to_cpu(here->e_value_size));
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	/* No failures allowed past this point. */
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	if (!s->not_found && here->e_value_size && !here->e_value_inum) {
175662306a36Sopenharmony_ci		/* Remove the old value. */
175762306a36Sopenharmony_ci		void *first_val = s->base + min_offs;
175862306a36Sopenharmony_ci		size_t offs = le16_to_cpu(here->e_value_offs);
175962306a36Sopenharmony_ci		void *val = s->base + offs;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci		memmove(first_val + old_size, first_val, val - first_val);
176262306a36Sopenharmony_ci		memset(first_val, 0, old_size);
176362306a36Sopenharmony_ci		min_offs += old_size;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci		/* Adjust all value offsets. */
176662306a36Sopenharmony_ci		last = s->first;
176762306a36Sopenharmony_ci		while (!IS_LAST_ENTRY(last)) {
176862306a36Sopenharmony_ci			size_t o = le16_to_cpu(last->e_value_offs);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci			if (!last->e_value_inum &&
177162306a36Sopenharmony_ci			    last->e_value_size && o < offs)
177262306a36Sopenharmony_ci				last->e_value_offs = cpu_to_le16(o + old_size);
177362306a36Sopenharmony_ci			last = EXT4_XATTR_NEXT(last);
177462306a36Sopenharmony_ci		}
177562306a36Sopenharmony_ci	}
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	if (!i->value) {
177862306a36Sopenharmony_ci		/* Remove old name. */
177962306a36Sopenharmony_ci		size_t size = EXT4_XATTR_LEN(name_len);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci		last = ENTRY((void *)last - size);
178262306a36Sopenharmony_ci		memmove(here, (void *)here + size,
178362306a36Sopenharmony_ci			(void *)last - (void *)here + sizeof(__u32));
178462306a36Sopenharmony_ci		memset(last, 0, size);
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci		/*
178762306a36Sopenharmony_ci		 * Update i_inline_off - moved ibody region might contain
178862306a36Sopenharmony_ci		 * system.data attribute.  Handling a failure here won't
178962306a36Sopenharmony_ci		 * cause other complications for setting an xattr.
179062306a36Sopenharmony_ci		 */
179162306a36Sopenharmony_ci		if (!is_block && ext4_has_inline_data(inode)) {
179262306a36Sopenharmony_ci			ret = ext4_find_inline_data_nolock(inode);
179362306a36Sopenharmony_ci			if (ret) {
179462306a36Sopenharmony_ci				ext4_warning_inode(inode,
179562306a36Sopenharmony_ci					"unable to update i_inline_off");
179662306a36Sopenharmony_ci				goto out;
179762306a36Sopenharmony_ci			}
179862306a36Sopenharmony_ci		}
179962306a36Sopenharmony_ci	} else if (s->not_found) {
180062306a36Sopenharmony_ci		/* Insert new name. */
180162306a36Sopenharmony_ci		size_t size = EXT4_XATTR_LEN(name_len);
180262306a36Sopenharmony_ci		size_t rest = (void *)last - (void *)here + sizeof(__u32);
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci		memmove((void *)here + size, here, rest);
180562306a36Sopenharmony_ci		memset(here, 0, size);
180662306a36Sopenharmony_ci		here->e_name_index = i->name_index;
180762306a36Sopenharmony_ci		here->e_name_len = name_len;
180862306a36Sopenharmony_ci		memcpy(here->e_name, i->name, name_len);
180962306a36Sopenharmony_ci	} else {
181062306a36Sopenharmony_ci		/* This is an update, reset value info. */
181162306a36Sopenharmony_ci		here->e_value_inum = 0;
181262306a36Sopenharmony_ci		here->e_value_offs = 0;
181362306a36Sopenharmony_ci		here->e_value_size = 0;
181462306a36Sopenharmony_ci	}
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	if (i->value) {
181762306a36Sopenharmony_ci		/* Insert new value. */
181862306a36Sopenharmony_ci		if (in_inode) {
181962306a36Sopenharmony_ci			here->e_value_inum = cpu_to_le32(new_ea_inode->i_ino);
182062306a36Sopenharmony_ci		} else if (i->value_len) {
182162306a36Sopenharmony_ci			void *val = s->base + min_offs - new_size;
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci			here->e_value_offs = cpu_to_le16(min_offs - new_size);
182462306a36Sopenharmony_ci			if (i->value == EXT4_ZERO_XATTR_VALUE) {
182562306a36Sopenharmony_ci				memset(val, 0, new_size);
182662306a36Sopenharmony_ci			} else {
182762306a36Sopenharmony_ci				memcpy(val, i->value, i->value_len);
182862306a36Sopenharmony_ci				/* Clear padding bytes. */
182962306a36Sopenharmony_ci				memset(val + i->value_len, 0,
183062306a36Sopenharmony_ci				       new_size - i->value_len);
183162306a36Sopenharmony_ci			}
183262306a36Sopenharmony_ci		}
183362306a36Sopenharmony_ci		here->e_value_size = cpu_to_le32(i->value_len);
183462306a36Sopenharmony_ci	}
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ciupdate_hash:
183762306a36Sopenharmony_ci	if (i->value) {
183862306a36Sopenharmony_ci		__le32 hash = 0;
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci		/* Entry hash calculation. */
184162306a36Sopenharmony_ci		if (in_inode) {
184262306a36Sopenharmony_ci			__le32 crc32c_hash;
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci			/*
184562306a36Sopenharmony_ci			 * Feed crc32c hash instead of the raw value for entry
184662306a36Sopenharmony_ci			 * hash calculation. This is to avoid walking
184762306a36Sopenharmony_ci			 * potentially long value buffer again.
184862306a36Sopenharmony_ci			 */
184962306a36Sopenharmony_ci			crc32c_hash = cpu_to_le32(
185062306a36Sopenharmony_ci				       ext4_xattr_inode_get_hash(new_ea_inode));
185162306a36Sopenharmony_ci			hash = ext4_xattr_hash_entry(here->e_name,
185262306a36Sopenharmony_ci						     here->e_name_len,
185362306a36Sopenharmony_ci						     &crc32c_hash, 1);
185462306a36Sopenharmony_ci		} else if (is_block) {
185562306a36Sopenharmony_ci			__le32 *value = s->base + le16_to_cpu(
185662306a36Sopenharmony_ci							here->e_value_offs);
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci			hash = ext4_xattr_hash_entry(here->e_name,
185962306a36Sopenharmony_ci						     here->e_name_len, value,
186062306a36Sopenharmony_ci						     new_size >> 2);
186162306a36Sopenharmony_ci		}
186262306a36Sopenharmony_ci		here->e_hash = hash;
186362306a36Sopenharmony_ci	}
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	if (is_block)
186662306a36Sopenharmony_ci		ext4_xattr_rehash((struct ext4_xattr_header *)s->base);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	ret = 0;
186962306a36Sopenharmony_ciout:
187062306a36Sopenharmony_ci	iput(old_ea_inode);
187162306a36Sopenharmony_ci	iput(new_ea_inode);
187262306a36Sopenharmony_ci	return ret;
187362306a36Sopenharmony_ci}
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_cistruct ext4_xattr_block_find {
187662306a36Sopenharmony_ci	struct ext4_xattr_search s;
187762306a36Sopenharmony_ci	struct buffer_head *bh;
187862306a36Sopenharmony_ci};
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_cistatic int
188162306a36Sopenharmony_ciext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
188262306a36Sopenharmony_ci		      struct ext4_xattr_block_find *bs)
188362306a36Sopenharmony_ci{
188462306a36Sopenharmony_ci	struct super_block *sb = inode->i_sb;
188562306a36Sopenharmony_ci	int error;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
188862306a36Sopenharmony_ci		  i->name_index, i->name, i->value, (long)i->value_len);
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	if (EXT4_I(inode)->i_file_acl) {
189162306a36Sopenharmony_ci		/* The inode already has an extended attribute block. */
189262306a36Sopenharmony_ci		bs->bh = ext4_sb_bread(sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
189362306a36Sopenharmony_ci		if (IS_ERR(bs->bh)) {
189462306a36Sopenharmony_ci			error = PTR_ERR(bs->bh);
189562306a36Sopenharmony_ci			bs->bh = NULL;
189662306a36Sopenharmony_ci			return error;
189762306a36Sopenharmony_ci		}
189862306a36Sopenharmony_ci		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
189962306a36Sopenharmony_ci			atomic_read(&(bs->bh->b_count)),
190062306a36Sopenharmony_ci			le32_to_cpu(BHDR(bs->bh)->h_refcount));
190162306a36Sopenharmony_ci		error = ext4_xattr_check_block(inode, bs->bh);
190262306a36Sopenharmony_ci		if (error)
190362306a36Sopenharmony_ci			return error;
190462306a36Sopenharmony_ci		/* Find the named attribute. */
190562306a36Sopenharmony_ci		bs->s.base = BHDR(bs->bh);
190662306a36Sopenharmony_ci		bs->s.first = BFIRST(bs->bh);
190762306a36Sopenharmony_ci		bs->s.end = bs->bh->b_data + bs->bh->b_size;
190862306a36Sopenharmony_ci		bs->s.here = bs->s.first;
190962306a36Sopenharmony_ci		error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
191062306a36Sopenharmony_ci					 i->name_index, i->name, 1);
191162306a36Sopenharmony_ci		if (error && error != -ENODATA)
191262306a36Sopenharmony_ci			return error;
191362306a36Sopenharmony_ci		bs->s.not_found = error;
191462306a36Sopenharmony_ci	}
191562306a36Sopenharmony_ci	return 0;
191662306a36Sopenharmony_ci}
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_cistatic int
191962306a36Sopenharmony_ciext4_xattr_block_set(handle_t *handle, struct inode *inode,
192062306a36Sopenharmony_ci		     struct ext4_xattr_info *i,
192162306a36Sopenharmony_ci		     struct ext4_xattr_block_find *bs)
192262306a36Sopenharmony_ci{
192362306a36Sopenharmony_ci	struct super_block *sb = inode->i_sb;
192462306a36Sopenharmony_ci	struct buffer_head *new_bh = NULL;
192562306a36Sopenharmony_ci	struct ext4_xattr_search s_copy = bs->s;
192662306a36Sopenharmony_ci	struct ext4_xattr_search *s = &s_copy;
192762306a36Sopenharmony_ci	struct mb_cache_entry *ce = NULL;
192862306a36Sopenharmony_ci	int error = 0;
192962306a36Sopenharmony_ci	struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
193062306a36Sopenharmony_ci	struct inode *ea_inode = NULL, *tmp_inode;
193162306a36Sopenharmony_ci	size_t old_ea_inode_quota = 0;
193262306a36Sopenharmony_ci	unsigned int ea_ino;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci#define header(x) ((struct ext4_xattr_header *)(x))
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	if (s->base) {
193862306a36Sopenharmony_ci		int offset = (char *)s->here - bs->bh->b_data;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci		BUFFER_TRACE(bs->bh, "get_write_access");
194162306a36Sopenharmony_ci		error = ext4_journal_get_write_access(handle, sb, bs->bh,
194262306a36Sopenharmony_ci						      EXT4_JTR_NONE);
194362306a36Sopenharmony_ci		if (error)
194462306a36Sopenharmony_ci			goto cleanup;
194562306a36Sopenharmony_ci		lock_buffer(bs->bh);
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci		if (header(s->base)->h_refcount == cpu_to_le32(1)) {
194862306a36Sopenharmony_ci			__u32 hash = le32_to_cpu(BHDR(bs->bh)->h_hash);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci			/*
195162306a36Sopenharmony_ci			 * This must happen under buffer lock for
195262306a36Sopenharmony_ci			 * ext4_xattr_block_set() to reliably detect modified
195362306a36Sopenharmony_ci			 * block
195462306a36Sopenharmony_ci			 */
195562306a36Sopenharmony_ci			if (ea_block_cache) {
195662306a36Sopenharmony_ci				struct mb_cache_entry *oe;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci				oe = mb_cache_entry_delete_or_get(ea_block_cache,
195962306a36Sopenharmony_ci					hash, bs->bh->b_blocknr);
196062306a36Sopenharmony_ci				if (oe) {
196162306a36Sopenharmony_ci					/*
196262306a36Sopenharmony_ci					 * Xattr block is getting reused. Leave
196362306a36Sopenharmony_ci					 * it alone.
196462306a36Sopenharmony_ci					 */
196562306a36Sopenharmony_ci					mb_cache_entry_put(ea_block_cache, oe);
196662306a36Sopenharmony_ci					goto clone_block;
196762306a36Sopenharmony_ci				}
196862306a36Sopenharmony_ci			}
196962306a36Sopenharmony_ci			ea_bdebug(bs->bh, "modifying in-place");
197062306a36Sopenharmony_ci			error = ext4_xattr_set_entry(i, s, handle, inode,
197162306a36Sopenharmony_ci						     true /* is_block */);
197262306a36Sopenharmony_ci			ext4_xattr_block_csum_set(inode, bs->bh);
197362306a36Sopenharmony_ci			unlock_buffer(bs->bh);
197462306a36Sopenharmony_ci			if (error == -EFSCORRUPTED)
197562306a36Sopenharmony_ci				goto bad_block;
197662306a36Sopenharmony_ci			if (!error)
197762306a36Sopenharmony_ci				error = ext4_handle_dirty_metadata(handle,
197862306a36Sopenharmony_ci								   inode,
197962306a36Sopenharmony_ci								   bs->bh);
198062306a36Sopenharmony_ci			if (error)
198162306a36Sopenharmony_ci				goto cleanup;
198262306a36Sopenharmony_ci			goto inserted;
198362306a36Sopenharmony_ci		}
198462306a36Sopenharmony_ciclone_block:
198562306a36Sopenharmony_ci		unlock_buffer(bs->bh);
198662306a36Sopenharmony_ci		ea_bdebug(bs->bh, "cloning");
198762306a36Sopenharmony_ci		s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
198862306a36Sopenharmony_ci		error = -ENOMEM;
198962306a36Sopenharmony_ci		if (s->base == NULL)
199062306a36Sopenharmony_ci			goto cleanup;
199162306a36Sopenharmony_ci		s->first = ENTRY(header(s->base)+1);
199262306a36Sopenharmony_ci		header(s->base)->h_refcount = cpu_to_le32(1);
199362306a36Sopenharmony_ci		s->here = ENTRY(s->base + offset);
199462306a36Sopenharmony_ci		s->end = s->base + bs->bh->b_size;
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci		/*
199762306a36Sopenharmony_ci		 * If existing entry points to an xattr inode, we need
199862306a36Sopenharmony_ci		 * to prevent ext4_xattr_set_entry() from decrementing
199962306a36Sopenharmony_ci		 * ref count on it because the reference belongs to the
200062306a36Sopenharmony_ci		 * original block. In this case, make the entry look
200162306a36Sopenharmony_ci		 * like it has an empty value.
200262306a36Sopenharmony_ci		 */
200362306a36Sopenharmony_ci		if (!s->not_found && s->here->e_value_inum) {
200462306a36Sopenharmony_ci			ea_ino = le32_to_cpu(s->here->e_value_inum);
200562306a36Sopenharmony_ci			error = ext4_xattr_inode_iget(inode, ea_ino,
200662306a36Sopenharmony_ci				      le32_to_cpu(s->here->e_hash),
200762306a36Sopenharmony_ci				      &tmp_inode);
200862306a36Sopenharmony_ci			if (error)
200962306a36Sopenharmony_ci				goto cleanup;
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci			if (!ext4_test_inode_state(tmp_inode,
201262306a36Sopenharmony_ci					EXT4_STATE_LUSTRE_EA_INODE)) {
201362306a36Sopenharmony_ci				/*
201462306a36Sopenharmony_ci				 * Defer quota free call for previous
201562306a36Sopenharmony_ci				 * inode until success is guaranteed.
201662306a36Sopenharmony_ci				 */
201762306a36Sopenharmony_ci				old_ea_inode_quota = le32_to_cpu(
201862306a36Sopenharmony_ci						s->here->e_value_size);
201962306a36Sopenharmony_ci			}
202062306a36Sopenharmony_ci			iput(tmp_inode);
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci			s->here->e_value_inum = 0;
202362306a36Sopenharmony_ci			s->here->e_value_size = 0;
202462306a36Sopenharmony_ci		}
202562306a36Sopenharmony_ci	} else {
202662306a36Sopenharmony_ci		/* Allocate a buffer where we construct the new block. */
202762306a36Sopenharmony_ci		s->base = kzalloc(sb->s_blocksize, GFP_NOFS);
202862306a36Sopenharmony_ci		error = -ENOMEM;
202962306a36Sopenharmony_ci		if (s->base == NULL)
203062306a36Sopenharmony_ci			goto cleanup;
203162306a36Sopenharmony_ci		header(s->base)->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
203262306a36Sopenharmony_ci		header(s->base)->h_blocks = cpu_to_le32(1);
203362306a36Sopenharmony_ci		header(s->base)->h_refcount = cpu_to_le32(1);
203462306a36Sopenharmony_ci		s->first = ENTRY(header(s->base)+1);
203562306a36Sopenharmony_ci		s->here = ENTRY(header(s->base)+1);
203662306a36Sopenharmony_ci		s->end = s->base + sb->s_blocksize;
203762306a36Sopenharmony_ci	}
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	error = ext4_xattr_set_entry(i, s, handle, inode, true /* is_block */);
204062306a36Sopenharmony_ci	if (error == -EFSCORRUPTED)
204162306a36Sopenharmony_ci		goto bad_block;
204262306a36Sopenharmony_ci	if (error)
204362306a36Sopenharmony_ci		goto cleanup;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	if (i->value && s->here->e_value_inum) {
204662306a36Sopenharmony_ci		/*
204762306a36Sopenharmony_ci		 * A ref count on ea_inode has been taken as part of the call to
204862306a36Sopenharmony_ci		 * ext4_xattr_set_entry() above. We would like to drop this
204962306a36Sopenharmony_ci		 * extra ref but we have to wait until the xattr block is
205062306a36Sopenharmony_ci		 * initialized and has its own ref count on the ea_inode.
205162306a36Sopenharmony_ci		 */
205262306a36Sopenharmony_ci		ea_ino = le32_to_cpu(s->here->e_value_inum);
205362306a36Sopenharmony_ci		error = ext4_xattr_inode_iget(inode, ea_ino,
205462306a36Sopenharmony_ci					      le32_to_cpu(s->here->e_hash),
205562306a36Sopenharmony_ci					      &ea_inode);
205662306a36Sopenharmony_ci		if (error) {
205762306a36Sopenharmony_ci			ea_inode = NULL;
205862306a36Sopenharmony_ci			goto cleanup;
205962306a36Sopenharmony_ci		}
206062306a36Sopenharmony_ci	}
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ciinserted:
206362306a36Sopenharmony_ci	if (!IS_LAST_ENTRY(s->first)) {
206462306a36Sopenharmony_ci		new_bh = ext4_xattr_block_cache_find(inode, header(s->base),
206562306a36Sopenharmony_ci						     &ce);
206662306a36Sopenharmony_ci		if (new_bh) {
206762306a36Sopenharmony_ci			/* We found an identical block in the cache. */
206862306a36Sopenharmony_ci			if (new_bh == bs->bh)
206962306a36Sopenharmony_ci				ea_bdebug(new_bh, "keeping");
207062306a36Sopenharmony_ci			else {
207162306a36Sopenharmony_ci				u32 ref;
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci#ifdef EXT4_XATTR_DEBUG
207462306a36Sopenharmony_ci				WARN_ON_ONCE(dquot_initialize_needed(inode));
207562306a36Sopenharmony_ci#endif
207662306a36Sopenharmony_ci				/* The old block is released after updating
207762306a36Sopenharmony_ci				   the inode. */
207862306a36Sopenharmony_ci				error = dquot_alloc_block(inode,
207962306a36Sopenharmony_ci						EXT4_C2B(EXT4_SB(sb), 1));
208062306a36Sopenharmony_ci				if (error)
208162306a36Sopenharmony_ci					goto cleanup;
208262306a36Sopenharmony_ci				BUFFER_TRACE(new_bh, "get_write_access");
208362306a36Sopenharmony_ci				error = ext4_journal_get_write_access(
208462306a36Sopenharmony_ci						handle, sb, new_bh,
208562306a36Sopenharmony_ci						EXT4_JTR_NONE);
208662306a36Sopenharmony_ci				if (error)
208762306a36Sopenharmony_ci					goto cleanup_dquot;
208862306a36Sopenharmony_ci				lock_buffer(new_bh);
208962306a36Sopenharmony_ci				/*
209062306a36Sopenharmony_ci				 * We have to be careful about races with
209162306a36Sopenharmony_ci				 * adding references to xattr block. Once we
209262306a36Sopenharmony_ci				 * hold buffer lock xattr block's state is
209362306a36Sopenharmony_ci				 * stable so we can check the additional
209462306a36Sopenharmony_ci				 * reference fits.
209562306a36Sopenharmony_ci				 */
209662306a36Sopenharmony_ci				ref = le32_to_cpu(BHDR(new_bh)->h_refcount) + 1;
209762306a36Sopenharmony_ci				if (ref > EXT4_XATTR_REFCOUNT_MAX) {
209862306a36Sopenharmony_ci					/*
209962306a36Sopenharmony_ci					 * Undo everything and check mbcache
210062306a36Sopenharmony_ci					 * again.
210162306a36Sopenharmony_ci					 */
210262306a36Sopenharmony_ci					unlock_buffer(new_bh);
210362306a36Sopenharmony_ci					dquot_free_block(inode,
210462306a36Sopenharmony_ci							 EXT4_C2B(EXT4_SB(sb),
210562306a36Sopenharmony_ci								  1));
210662306a36Sopenharmony_ci					brelse(new_bh);
210762306a36Sopenharmony_ci					mb_cache_entry_put(ea_block_cache, ce);
210862306a36Sopenharmony_ci					ce = NULL;
210962306a36Sopenharmony_ci					new_bh = NULL;
211062306a36Sopenharmony_ci					goto inserted;
211162306a36Sopenharmony_ci				}
211262306a36Sopenharmony_ci				BHDR(new_bh)->h_refcount = cpu_to_le32(ref);
211362306a36Sopenharmony_ci				if (ref == EXT4_XATTR_REFCOUNT_MAX)
211462306a36Sopenharmony_ci					clear_bit(MBE_REUSABLE_B, &ce->e_flags);
211562306a36Sopenharmony_ci				ea_bdebug(new_bh, "reusing; refcount now=%d",
211662306a36Sopenharmony_ci					  ref);
211762306a36Sopenharmony_ci				ext4_xattr_block_csum_set(inode, new_bh);
211862306a36Sopenharmony_ci				unlock_buffer(new_bh);
211962306a36Sopenharmony_ci				error = ext4_handle_dirty_metadata(handle,
212062306a36Sopenharmony_ci								   inode,
212162306a36Sopenharmony_ci								   new_bh);
212262306a36Sopenharmony_ci				if (error)
212362306a36Sopenharmony_ci					goto cleanup_dquot;
212462306a36Sopenharmony_ci			}
212562306a36Sopenharmony_ci			mb_cache_entry_touch(ea_block_cache, ce);
212662306a36Sopenharmony_ci			mb_cache_entry_put(ea_block_cache, ce);
212762306a36Sopenharmony_ci			ce = NULL;
212862306a36Sopenharmony_ci		} else if (bs->bh && s->base == bs->bh->b_data) {
212962306a36Sopenharmony_ci			/* We were modifying this block in-place. */
213062306a36Sopenharmony_ci			ea_bdebug(bs->bh, "keeping this block");
213162306a36Sopenharmony_ci			ext4_xattr_block_cache_insert(ea_block_cache, bs->bh);
213262306a36Sopenharmony_ci			new_bh = bs->bh;
213362306a36Sopenharmony_ci			get_bh(new_bh);
213462306a36Sopenharmony_ci		} else {
213562306a36Sopenharmony_ci			/* We need to allocate a new block */
213662306a36Sopenharmony_ci			ext4_fsblk_t goal, block;
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci#ifdef EXT4_XATTR_DEBUG
213962306a36Sopenharmony_ci			WARN_ON_ONCE(dquot_initialize_needed(inode));
214062306a36Sopenharmony_ci#endif
214162306a36Sopenharmony_ci			goal = ext4_group_first_block_no(sb,
214262306a36Sopenharmony_ci						EXT4_I(inode)->i_block_group);
214362306a36Sopenharmony_ci			block = ext4_new_meta_blocks(handle, inode, goal, 0,
214462306a36Sopenharmony_ci						     NULL, &error);
214562306a36Sopenharmony_ci			if (error)
214662306a36Sopenharmony_ci				goto cleanup;
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci			ea_idebug(inode, "creating block %llu",
214962306a36Sopenharmony_ci				  (unsigned long long)block);
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci			new_bh = sb_getblk(sb, block);
215262306a36Sopenharmony_ci			if (unlikely(!new_bh)) {
215362306a36Sopenharmony_ci				error = -ENOMEM;
215462306a36Sopenharmony_cigetblk_failed:
215562306a36Sopenharmony_ci				ext4_free_blocks(handle, inode, NULL, block, 1,
215662306a36Sopenharmony_ci						 EXT4_FREE_BLOCKS_METADATA);
215762306a36Sopenharmony_ci				goto cleanup;
215862306a36Sopenharmony_ci			}
215962306a36Sopenharmony_ci			error = ext4_xattr_inode_inc_ref_all(handle, inode,
216062306a36Sopenharmony_ci						      ENTRY(header(s->base)+1));
216162306a36Sopenharmony_ci			if (error)
216262306a36Sopenharmony_ci				goto getblk_failed;
216362306a36Sopenharmony_ci			if (ea_inode) {
216462306a36Sopenharmony_ci				/* Drop the extra ref on ea_inode. */
216562306a36Sopenharmony_ci				error = ext4_xattr_inode_dec_ref(handle,
216662306a36Sopenharmony_ci								 ea_inode);
216762306a36Sopenharmony_ci				if (error)
216862306a36Sopenharmony_ci					ext4_warning_inode(ea_inode,
216962306a36Sopenharmony_ci							   "dec ref error=%d",
217062306a36Sopenharmony_ci							   error);
217162306a36Sopenharmony_ci				iput(ea_inode);
217262306a36Sopenharmony_ci				ea_inode = NULL;
217362306a36Sopenharmony_ci			}
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci			lock_buffer(new_bh);
217662306a36Sopenharmony_ci			error = ext4_journal_get_create_access(handle, sb,
217762306a36Sopenharmony_ci							new_bh, EXT4_JTR_NONE);
217862306a36Sopenharmony_ci			if (error) {
217962306a36Sopenharmony_ci				unlock_buffer(new_bh);
218062306a36Sopenharmony_ci				error = -EIO;
218162306a36Sopenharmony_ci				goto getblk_failed;
218262306a36Sopenharmony_ci			}
218362306a36Sopenharmony_ci			memcpy(new_bh->b_data, s->base, new_bh->b_size);
218462306a36Sopenharmony_ci			ext4_xattr_block_csum_set(inode, new_bh);
218562306a36Sopenharmony_ci			set_buffer_uptodate(new_bh);
218662306a36Sopenharmony_ci			unlock_buffer(new_bh);
218762306a36Sopenharmony_ci			ext4_xattr_block_cache_insert(ea_block_cache, new_bh);
218862306a36Sopenharmony_ci			error = ext4_handle_dirty_metadata(handle, inode,
218962306a36Sopenharmony_ci							   new_bh);
219062306a36Sopenharmony_ci			if (error)
219162306a36Sopenharmony_ci				goto cleanup;
219262306a36Sopenharmony_ci		}
219362306a36Sopenharmony_ci	}
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	if (old_ea_inode_quota)
219662306a36Sopenharmony_ci		ext4_xattr_inode_free_quota(inode, NULL, old_ea_inode_quota);
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	/* Update the inode. */
219962306a36Sopenharmony_ci	EXT4_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_ci	/* Drop the previous xattr block. */
220262306a36Sopenharmony_ci	if (bs->bh && bs->bh != new_bh) {
220362306a36Sopenharmony_ci		struct ext4_xattr_inode_array *ea_inode_array = NULL;
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci		ext4_xattr_release_block(handle, inode, bs->bh,
220662306a36Sopenharmony_ci					 &ea_inode_array,
220762306a36Sopenharmony_ci					 0 /* extra_credits */);
220862306a36Sopenharmony_ci		ext4_xattr_inode_array_free(ea_inode_array);
220962306a36Sopenharmony_ci	}
221062306a36Sopenharmony_ci	error = 0;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_cicleanup:
221362306a36Sopenharmony_ci	if (ea_inode) {
221462306a36Sopenharmony_ci		int error2;
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci		error2 = ext4_xattr_inode_dec_ref(handle, ea_inode);
221762306a36Sopenharmony_ci		if (error2)
221862306a36Sopenharmony_ci			ext4_warning_inode(ea_inode, "dec ref error=%d",
221962306a36Sopenharmony_ci					   error2);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci		/* If there was an error, revert the quota charge. */
222262306a36Sopenharmony_ci		if (error)
222362306a36Sopenharmony_ci			ext4_xattr_inode_free_quota(inode, ea_inode,
222462306a36Sopenharmony_ci						    i_size_read(ea_inode));
222562306a36Sopenharmony_ci		iput(ea_inode);
222662306a36Sopenharmony_ci	}
222762306a36Sopenharmony_ci	if (ce)
222862306a36Sopenharmony_ci		mb_cache_entry_put(ea_block_cache, ce);
222962306a36Sopenharmony_ci	brelse(new_bh);
223062306a36Sopenharmony_ci	if (!(bs->bh && s->base == bs->bh->b_data))
223162306a36Sopenharmony_ci		kfree(s->base);
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	return error;
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_cicleanup_dquot:
223662306a36Sopenharmony_ci	dquot_free_block(inode, EXT4_C2B(EXT4_SB(sb), 1));
223762306a36Sopenharmony_ci	goto cleanup;
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_cibad_block:
224062306a36Sopenharmony_ci	EXT4_ERROR_INODE(inode, "bad block %llu",
224162306a36Sopenharmony_ci			 EXT4_I(inode)->i_file_acl);
224262306a36Sopenharmony_ci	goto cleanup;
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci#undef header
224562306a36Sopenharmony_ci}
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ciint ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
224862306a36Sopenharmony_ci			  struct ext4_xattr_ibody_find *is)
224962306a36Sopenharmony_ci{
225062306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
225162306a36Sopenharmony_ci	struct ext4_inode *raw_inode;
225262306a36Sopenharmony_ci	int error;
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci	if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
225562306a36Sopenharmony_ci		return 0;
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	raw_inode = ext4_raw_inode(&is->iloc);
225862306a36Sopenharmony_ci	header = IHDR(inode, raw_inode);
225962306a36Sopenharmony_ci	is->s.base = is->s.first = IFIRST(header);
226062306a36Sopenharmony_ci	is->s.here = is->s.first;
226162306a36Sopenharmony_ci	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
226262306a36Sopenharmony_ci	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
226362306a36Sopenharmony_ci		error = xattr_check_inode(inode, header, is->s.end);
226462306a36Sopenharmony_ci		if (error)
226562306a36Sopenharmony_ci			return error;
226662306a36Sopenharmony_ci		/* Find the named attribute. */
226762306a36Sopenharmony_ci		error = xattr_find_entry(inode, &is->s.here, is->s.end,
226862306a36Sopenharmony_ci					 i->name_index, i->name, 0);
226962306a36Sopenharmony_ci		if (error && error != -ENODATA)
227062306a36Sopenharmony_ci			return error;
227162306a36Sopenharmony_ci		is->s.not_found = error;
227262306a36Sopenharmony_ci	}
227362306a36Sopenharmony_ci	return 0;
227462306a36Sopenharmony_ci}
227562306a36Sopenharmony_ci
227662306a36Sopenharmony_ciint ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
227762306a36Sopenharmony_ci				struct ext4_xattr_info *i,
227862306a36Sopenharmony_ci				struct ext4_xattr_ibody_find *is)
227962306a36Sopenharmony_ci{
228062306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
228162306a36Sopenharmony_ci	struct ext4_xattr_search *s = &is->s;
228262306a36Sopenharmony_ci	int error;
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci	if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
228562306a36Sopenharmony_ci		return -ENOSPC;
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
228862306a36Sopenharmony_ci	if (error)
228962306a36Sopenharmony_ci		return error;
229062306a36Sopenharmony_ci	header = IHDR(inode, ext4_raw_inode(&is->iloc));
229162306a36Sopenharmony_ci	if (!IS_LAST_ENTRY(s->first)) {
229262306a36Sopenharmony_ci		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
229362306a36Sopenharmony_ci		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
229462306a36Sopenharmony_ci	} else {
229562306a36Sopenharmony_ci		header->h_magic = cpu_to_le32(0);
229662306a36Sopenharmony_ci		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
229762306a36Sopenharmony_ci	}
229862306a36Sopenharmony_ci	return 0;
229962306a36Sopenharmony_ci}
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_cistatic int ext4_xattr_value_same(struct ext4_xattr_search *s,
230262306a36Sopenharmony_ci				 struct ext4_xattr_info *i)
230362306a36Sopenharmony_ci{
230462306a36Sopenharmony_ci	void *value;
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	/* When e_value_inum is set the value is stored externally. */
230762306a36Sopenharmony_ci	if (s->here->e_value_inum)
230862306a36Sopenharmony_ci		return 0;
230962306a36Sopenharmony_ci	if (le32_to_cpu(s->here->e_value_size) != i->value_len)
231062306a36Sopenharmony_ci		return 0;
231162306a36Sopenharmony_ci	value = ((void *)s->base) + le16_to_cpu(s->here->e_value_offs);
231262306a36Sopenharmony_ci	return !memcmp(value, i->value, i->value_len);
231362306a36Sopenharmony_ci}
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_cistatic struct buffer_head *ext4_xattr_get_block(struct inode *inode)
231662306a36Sopenharmony_ci{
231762306a36Sopenharmony_ci	struct buffer_head *bh;
231862306a36Sopenharmony_ci	int error;
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	if (!EXT4_I(inode)->i_file_acl)
232162306a36Sopenharmony_ci		return NULL;
232262306a36Sopenharmony_ci	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
232362306a36Sopenharmony_ci	if (IS_ERR(bh))
232462306a36Sopenharmony_ci		return bh;
232562306a36Sopenharmony_ci	error = ext4_xattr_check_block(inode, bh);
232662306a36Sopenharmony_ci	if (error) {
232762306a36Sopenharmony_ci		brelse(bh);
232862306a36Sopenharmony_ci		return ERR_PTR(error);
232962306a36Sopenharmony_ci	}
233062306a36Sopenharmony_ci	return bh;
233162306a36Sopenharmony_ci}
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci/*
233462306a36Sopenharmony_ci * ext4_xattr_set_handle()
233562306a36Sopenharmony_ci *
233662306a36Sopenharmony_ci * Create, replace or remove an extended attribute for this inode.  Value
233762306a36Sopenharmony_ci * is NULL to remove an existing extended attribute, and non-NULL to
233862306a36Sopenharmony_ci * either replace an existing extended attribute, or create a new extended
233962306a36Sopenharmony_ci * attribute. The flags XATTR_REPLACE and XATTR_CREATE
234062306a36Sopenharmony_ci * specify that an extended attribute must exist and must not exist
234162306a36Sopenharmony_ci * previous to the call, respectively.
234262306a36Sopenharmony_ci *
234362306a36Sopenharmony_ci * Returns 0, or a negative error number on failure.
234462306a36Sopenharmony_ci */
234562306a36Sopenharmony_ciint
234662306a36Sopenharmony_ciext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
234762306a36Sopenharmony_ci		      const char *name, const void *value, size_t value_len,
234862306a36Sopenharmony_ci		      int flags)
234962306a36Sopenharmony_ci{
235062306a36Sopenharmony_ci	struct ext4_xattr_info i = {
235162306a36Sopenharmony_ci		.name_index = name_index,
235262306a36Sopenharmony_ci		.name = name,
235362306a36Sopenharmony_ci		.value = value,
235462306a36Sopenharmony_ci		.value_len = value_len,
235562306a36Sopenharmony_ci		.in_inode = 0,
235662306a36Sopenharmony_ci	};
235762306a36Sopenharmony_ci	struct ext4_xattr_ibody_find is = {
235862306a36Sopenharmony_ci		.s = { .not_found = -ENODATA, },
235962306a36Sopenharmony_ci	};
236062306a36Sopenharmony_ci	struct ext4_xattr_block_find bs = {
236162306a36Sopenharmony_ci		.s = { .not_found = -ENODATA, },
236262306a36Sopenharmony_ci	};
236362306a36Sopenharmony_ci	int no_expand;
236462306a36Sopenharmony_ci	int error;
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	if (!name)
236762306a36Sopenharmony_ci		return -EINVAL;
236862306a36Sopenharmony_ci	if (strlen(name) > 255)
236962306a36Sopenharmony_ci		return -ERANGE;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	ext4_write_lock_xattr(inode, &no_expand);
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_ci	/* Check journal credits under write lock. */
237462306a36Sopenharmony_ci	if (ext4_handle_valid(handle)) {
237562306a36Sopenharmony_ci		struct buffer_head *bh;
237662306a36Sopenharmony_ci		int credits;
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci		bh = ext4_xattr_get_block(inode);
237962306a36Sopenharmony_ci		if (IS_ERR(bh)) {
238062306a36Sopenharmony_ci			error = PTR_ERR(bh);
238162306a36Sopenharmony_ci			goto cleanup;
238262306a36Sopenharmony_ci		}
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci		credits = __ext4_xattr_set_credits(inode->i_sb, inode, bh,
238562306a36Sopenharmony_ci						   value_len,
238662306a36Sopenharmony_ci						   flags & XATTR_CREATE);
238762306a36Sopenharmony_ci		brelse(bh);
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci		if (jbd2_handle_buffer_credits(handle) < credits) {
239062306a36Sopenharmony_ci			error = -ENOSPC;
239162306a36Sopenharmony_ci			goto cleanup;
239262306a36Sopenharmony_ci		}
239362306a36Sopenharmony_ci		WARN_ON_ONCE(!(current->flags & PF_MEMALLOC_NOFS));
239462306a36Sopenharmony_ci	}
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	error = ext4_reserve_inode_write(handle, inode, &is.iloc);
239762306a36Sopenharmony_ci	if (error)
239862306a36Sopenharmony_ci		goto cleanup;
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
240162306a36Sopenharmony_ci		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
240262306a36Sopenharmony_ci		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
240362306a36Sopenharmony_ci		ext4_clear_inode_state(inode, EXT4_STATE_NEW);
240462306a36Sopenharmony_ci	}
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	error = ext4_xattr_ibody_find(inode, &i, &is);
240762306a36Sopenharmony_ci	if (error)
240862306a36Sopenharmony_ci		goto cleanup;
240962306a36Sopenharmony_ci	if (is.s.not_found)
241062306a36Sopenharmony_ci		error = ext4_xattr_block_find(inode, &i, &bs);
241162306a36Sopenharmony_ci	if (error)
241262306a36Sopenharmony_ci		goto cleanup;
241362306a36Sopenharmony_ci	if (is.s.not_found && bs.s.not_found) {
241462306a36Sopenharmony_ci		error = -ENODATA;
241562306a36Sopenharmony_ci		if (flags & XATTR_REPLACE)
241662306a36Sopenharmony_ci			goto cleanup;
241762306a36Sopenharmony_ci		error = 0;
241862306a36Sopenharmony_ci		if (!value)
241962306a36Sopenharmony_ci			goto cleanup;
242062306a36Sopenharmony_ci	} else {
242162306a36Sopenharmony_ci		error = -EEXIST;
242262306a36Sopenharmony_ci		if (flags & XATTR_CREATE)
242362306a36Sopenharmony_ci			goto cleanup;
242462306a36Sopenharmony_ci	}
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	if (!value) {
242762306a36Sopenharmony_ci		if (!is.s.not_found)
242862306a36Sopenharmony_ci			error = ext4_xattr_ibody_set(handle, inode, &i, &is);
242962306a36Sopenharmony_ci		else if (!bs.s.not_found)
243062306a36Sopenharmony_ci			error = ext4_xattr_block_set(handle, inode, &i, &bs);
243162306a36Sopenharmony_ci	} else {
243262306a36Sopenharmony_ci		error = 0;
243362306a36Sopenharmony_ci		/* Xattr value did not change? Save us some work and bail out */
243462306a36Sopenharmony_ci		if (!is.s.not_found && ext4_xattr_value_same(&is.s, &i))
243562306a36Sopenharmony_ci			goto cleanup;
243662306a36Sopenharmony_ci		if (!bs.s.not_found && ext4_xattr_value_same(&bs.s, &i))
243762306a36Sopenharmony_ci			goto cleanup;
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci		if (ext4_has_feature_ea_inode(inode->i_sb) &&
244062306a36Sopenharmony_ci		    (EXT4_XATTR_SIZE(i.value_len) >
244162306a36Sopenharmony_ci			EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize)))
244262306a36Sopenharmony_ci			i.in_inode = 1;
244362306a36Sopenharmony_ciretry_inode:
244462306a36Sopenharmony_ci		error = ext4_xattr_ibody_set(handle, inode, &i, &is);
244562306a36Sopenharmony_ci		if (!error && !bs.s.not_found) {
244662306a36Sopenharmony_ci			i.value = NULL;
244762306a36Sopenharmony_ci			error = ext4_xattr_block_set(handle, inode, &i, &bs);
244862306a36Sopenharmony_ci		} else if (error == -ENOSPC) {
244962306a36Sopenharmony_ci			if (EXT4_I(inode)->i_file_acl && !bs.s.base) {
245062306a36Sopenharmony_ci				brelse(bs.bh);
245162306a36Sopenharmony_ci				bs.bh = NULL;
245262306a36Sopenharmony_ci				error = ext4_xattr_block_find(inode, &i, &bs);
245362306a36Sopenharmony_ci				if (error)
245462306a36Sopenharmony_ci					goto cleanup;
245562306a36Sopenharmony_ci			}
245662306a36Sopenharmony_ci			error = ext4_xattr_block_set(handle, inode, &i, &bs);
245762306a36Sopenharmony_ci			if (!error && !is.s.not_found) {
245862306a36Sopenharmony_ci				i.value = NULL;
245962306a36Sopenharmony_ci				error = ext4_xattr_ibody_set(handle, inode, &i,
246062306a36Sopenharmony_ci							     &is);
246162306a36Sopenharmony_ci			} else if (error == -ENOSPC) {
246262306a36Sopenharmony_ci				/*
246362306a36Sopenharmony_ci				 * Xattr does not fit in the block, store at
246462306a36Sopenharmony_ci				 * external inode if possible.
246562306a36Sopenharmony_ci				 */
246662306a36Sopenharmony_ci				if (ext4_has_feature_ea_inode(inode->i_sb) &&
246762306a36Sopenharmony_ci				    i.value_len && !i.in_inode) {
246862306a36Sopenharmony_ci					i.in_inode = 1;
246962306a36Sopenharmony_ci					goto retry_inode;
247062306a36Sopenharmony_ci				}
247162306a36Sopenharmony_ci			}
247262306a36Sopenharmony_ci		}
247362306a36Sopenharmony_ci	}
247462306a36Sopenharmony_ci	if (!error) {
247562306a36Sopenharmony_ci		ext4_xattr_update_super_block(handle, inode->i_sb);
247662306a36Sopenharmony_ci		inode_set_ctime_current(inode);
247762306a36Sopenharmony_ci		inode_inc_iversion(inode);
247862306a36Sopenharmony_ci		if (!value)
247962306a36Sopenharmony_ci			no_expand = 0;
248062306a36Sopenharmony_ci		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
248162306a36Sopenharmony_ci		/*
248262306a36Sopenharmony_ci		 * The bh is consumed by ext4_mark_iloc_dirty, even with
248362306a36Sopenharmony_ci		 * error != 0.
248462306a36Sopenharmony_ci		 */
248562306a36Sopenharmony_ci		is.iloc.bh = NULL;
248662306a36Sopenharmony_ci		if (IS_SYNC(inode))
248762306a36Sopenharmony_ci			ext4_handle_sync(handle);
248862306a36Sopenharmony_ci	}
248962306a36Sopenharmony_ci	ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_cicleanup:
249262306a36Sopenharmony_ci	brelse(is.iloc.bh);
249362306a36Sopenharmony_ci	brelse(bs.bh);
249462306a36Sopenharmony_ci	ext4_write_unlock_xattr(inode, &no_expand);
249562306a36Sopenharmony_ci	return error;
249662306a36Sopenharmony_ci}
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_ciint ext4_xattr_set_credits(struct inode *inode, size_t value_len,
249962306a36Sopenharmony_ci			   bool is_create, int *credits)
250062306a36Sopenharmony_ci{
250162306a36Sopenharmony_ci	struct buffer_head *bh;
250262306a36Sopenharmony_ci	int err;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	*credits = 0;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci	if (!EXT4_SB(inode->i_sb)->s_journal)
250762306a36Sopenharmony_ci		return 0;
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	down_read(&EXT4_I(inode)->xattr_sem);
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	bh = ext4_xattr_get_block(inode);
251262306a36Sopenharmony_ci	if (IS_ERR(bh)) {
251362306a36Sopenharmony_ci		err = PTR_ERR(bh);
251462306a36Sopenharmony_ci	} else {
251562306a36Sopenharmony_ci		*credits = __ext4_xattr_set_credits(inode->i_sb, inode, bh,
251662306a36Sopenharmony_ci						    value_len, is_create);
251762306a36Sopenharmony_ci		brelse(bh);
251862306a36Sopenharmony_ci		err = 0;
251962306a36Sopenharmony_ci	}
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci	up_read(&EXT4_I(inode)->xattr_sem);
252262306a36Sopenharmony_ci	return err;
252362306a36Sopenharmony_ci}
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci/*
252662306a36Sopenharmony_ci * ext4_xattr_set()
252762306a36Sopenharmony_ci *
252862306a36Sopenharmony_ci * Like ext4_xattr_set_handle, but start from an inode. This extended
252962306a36Sopenharmony_ci * attribute modification is a filesystem transaction by itself.
253062306a36Sopenharmony_ci *
253162306a36Sopenharmony_ci * Returns 0, or a negative error number on failure.
253262306a36Sopenharmony_ci */
253362306a36Sopenharmony_ciint
253462306a36Sopenharmony_ciext4_xattr_set(struct inode *inode, int name_index, const char *name,
253562306a36Sopenharmony_ci	       const void *value, size_t value_len, int flags)
253662306a36Sopenharmony_ci{
253762306a36Sopenharmony_ci	handle_t *handle;
253862306a36Sopenharmony_ci	struct super_block *sb = inode->i_sb;
253962306a36Sopenharmony_ci	int error, retries = 0;
254062306a36Sopenharmony_ci	int credits;
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_ci	error = dquot_initialize(inode);
254362306a36Sopenharmony_ci	if (error)
254462306a36Sopenharmony_ci		return error;
254562306a36Sopenharmony_ci
254662306a36Sopenharmony_ciretry:
254762306a36Sopenharmony_ci	error = ext4_xattr_set_credits(inode, value_len, flags & XATTR_CREATE,
254862306a36Sopenharmony_ci				       &credits);
254962306a36Sopenharmony_ci	if (error)
255062306a36Sopenharmony_ci		return error;
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
255362306a36Sopenharmony_ci	if (IS_ERR(handle)) {
255462306a36Sopenharmony_ci		error = PTR_ERR(handle);
255562306a36Sopenharmony_ci	} else {
255662306a36Sopenharmony_ci		int error2;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci		error = ext4_xattr_set_handle(handle, inode, name_index, name,
255962306a36Sopenharmony_ci					      value, value_len, flags);
256062306a36Sopenharmony_ci		error2 = ext4_journal_stop(handle);
256162306a36Sopenharmony_ci		if (error == -ENOSPC &&
256262306a36Sopenharmony_ci		    ext4_should_retry_alloc(sb, &retries))
256362306a36Sopenharmony_ci			goto retry;
256462306a36Sopenharmony_ci		if (error == 0)
256562306a36Sopenharmony_ci			error = error2;
256662306a36Sopenharmony_ci	}
256762306a36Sopenharmony_ci	ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, NULL);
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	return error;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci/*
257362306a36Sopenharmony_ci * Shift the EA entries in the inode to create space for the increased
257462306a36Sopenharmony_ci * i_extra_isize.
257562306a36Sopenharmony_ci */
257662306a36Sopenharmony_cistatic void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
257762306a36Sopenharmony_ci				     int value_offs_shift, void *to,
257862306a36Sopenharmony_ci				     void *from, size_t n)
257962306a36Sopenharmony_ci{
258062306a36Sopenharmony_ci	struct ext4_xattr_entry *last = entry;
258162306a36Sopenharmony_ci	int new_offs;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	/* We always shift xattr headers further thus offsets get lower */
258462306a36Sopenharmony_ci	BUG_ON(value_offs_shift > 0);
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	/* Adjust the value offsets of the entries */
258762306a36Sopenharmony_ci	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
258862306a36Sopenharmony_ci		if (!last->e_value_inum && last->e_value_size) {
258962306a36Sopenharmony_ci			new_offs = le16_to_cpu(last->e_value_offs) +
259062306a36Sopenharmony_ci							value_offs_shift;
259162306a36Sopenharmony_ci			last->e_value_offs = cpu_to_le16(new_offs);
259262306a36Sopenharmony_ci		}
259362306a36Sopenharmony_ci	}
259462306a36Sopenharmony_ci	/* Shift the entries by n bytes */
259562306a36Sopenharmony_ci	memmove(to, from, n);
259662306a36Sopenharmony_ci}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci/*
259962306a36Sopenharmony_ci * Move xattr pointed to by 'entry' from inode into external xattr block
260062306a36Sopenharmony_ci */
260162306a36Sopenharmony_cistatic int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
260262306a36Sopenharmony_ci				    struct ext4_inode *raw_inode,
260362306a36Sopenharmony_ci				    struct ext4_xattr_entry *entry)
260462306a36Sopenharmony_ci{
260562306a36Sopenharmony_ci	struct ext4_xattr_ibody_find *is = NULL;
260662306a36Sopenharmony_ci	struct ext4_xattr_block_find *bs = NULL;
260762306a36Sopenharmony_ci	char *buffer = NULL, *b_entry_name = NULL;
260862306a36Sopenharmony_ci	size_t value_size = le32_to_cpu(entry->e_value_size);
260962306a36Sopenharmony_ci	struct ext4_xattr_info i = {
261062306a36Sopenharmony_ci		.value = NULL,
261162306a36Sopenharmony_ci		.value_len = 0,
261262306a36Sopenharmony_ci		.name_index = entry->e_name_index,
261362306a36Sopenharmony_ci		.in_inode = !!entry->e_value_inum,
261462306a36Sopenharmony_ci	};
261562306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
261662306a36Sopenharmony_ci	int needs_kvfree = 0;
261762306a36Sopenharmony_ci	int error;
261862306a36Sopenharmony_ci
261962306a36Sopenharmony_ci	is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
262062306a36Sopenharmony_ci	bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
262162306a36Sopenharmony_ci	b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
262262306a36Sopenharmony_ci	if (!is || !bs || !b_entry_name) {
262362306a36Sopenharmony_ci		error = -ENOMEM;
262462306a36Sopenharmony_ci		goto out;
262562306a36Sopenharmony_ci	}
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	is->s.not_found = -ENODATA;
262862306a36Sopenharmony_ci	bs->s.not_found = -ENODATA;
262962306a36Sopenharmony_ci	is->iloc.bh = NULL;
263062306a36Sopenharmony_ci	bs->bh = NULL;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	/* Save the entry name and the entry value */
263362306a36Sopenharmony_ci	if (entry->e_value_inum) {
263462306a36Sopenharmony_ci		buffer = kvmalloc(value_size, GFP_NOFS);
263562306a36Sopenharmony_ci		if (!buffer) {
263662306a36Sopenharmony_ci			error = -ENOMEM;
263762306a36Sopenharmony_ci			goto out;
263862306a36Sopenharmony_ci		}
263962306a36Sopenharmony_ci		needs_kvfree = 1;
264062306a36Sopenharmony_ci		error = ext4_xattr_inode_get(inode, entry, buffer, value_size);
264162306a36Sopenharmony_ci		if (error)
264262306a36Sopenharmony_ci			goto out;
264362306a36Sopenharmony_ci	} else {
264462306a36Sopenharmony_ci		size_t value_offs = le16_to_cpu(entry->e_value_offs);
264562306a36Sopenharmony_ci		buffer = (void *)IFIRST(header) + value_offs;
264662306a36Sopenharmony_ci	}
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	memcpy(b_entry_name, entry->e_name, entry->e_name_len);
264962306a36Sopenharmony_ci	b_entry_name[entry->e_name_len] = '\0';
265062306a36Sopenharmony_ci	i.name = b_entry_name;
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	error = ext4_get_inode_loc(inode, &is->iloc);
265362306a36Sopenharmony_ci	if (error)
265462306a36Sopenharmony_ci		goto out;
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci	error = ext4_xattr_ibody_find(inode, &i, is);
265762306a36Sopenharmony_ci	if (error)
265862306a36Sopenharmony_ci		goto out;
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci	i.value = buffer;
266162306a36Sopenharmony_ci	i.value_len = value_size;
266262306a36Sopenharmony_ci	error = ext4_xattr_block_find(inode, &i, bs);
266362306a36Sopenharmony_ci	if (error)
266462306a36Sopenharmony_ci		goto out;
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	/* Move ea entry from the inode into the block */
266762306a36Sopenharmony_ci	error = ext4_xattr_block_set(handle, inode, &i, bs);
266862306a36Sopenharmony_ci	if (error)
266962306a36Sopenharmony_ci		goto out;
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci	/* Remove the chosen entry from the inode */
267262306a36Sopenharmony_ci	i.value = NULL;
267362306a36Sopenharmony_ci	i.value_len = 0;
267462306a36Sopenharmony_ci	error = ext4_xattr_ibody_set(handle, inode, &i, is);
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ciout:
267762306a36Sopenharmony_ci	kfree(b_entry_name);
267862306a36Sopenharmony_ci	if (needs_kvfree && buffer)
267962306a36Sopenharmony_ci		kvfree(buffer);
268062306a36Sopenharmony_ci	if (is)
268162306a36Sopenharmony_ci		brelse(is->iloc.bh);
268262306a36Sopenharmony_ci	if (bs)
268362306a36Sopenharmony_ci		brelse(bs->bh);
268462306a36Sopenharmony_ci	kfree(is);
268562306a36Sopenharmony_ci	kfree(bs);
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	return error;
268862306a36Sopenharmony_ci}
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_cistatic int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode,
269162306a36Sopenharmony_ci				       struct ext4_inode *raw_inode,
269262306a36Sopenharmony_ci				       int isize_diff, size_t ifree,
269362306a36Sopenharmony_ci				       size_t bfree, int *total_ino)
269462306a36Sopenharmony_ci{
269562306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
269662306a36Sopenharmony_ci	struct ext4_xattr_entry *small_entry;
269762306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
269862306a36Sopenharmony_ci	struct ext4_xattr_entry *last;
269962306a36Sopenharmony_ci	unsigned int entry_size;	/* EA entry size */
270062306a36Sopenharmony_ci	unsigned int total_size;	/* EA entry size + value size */
270162306a36Sopenharmony_ci	unsigned int min_total_size;
270262306a36Sopenharmony_ci	int error;
270362306a36Sopenharmony_ci
270462306a36Sopenharmony_ci	while (isize_diff > ifree) {
270562306a36Sopenharmony_ci		entry = NULL;
270662306a36Sopenharmony_ci		small_entry = NULL;
270762306a36Sopenharmony_ci		min_total_size = ~0U;
270862306a36Sopenharmony_ci		last = IFIRST(header);
270962306a36Sopenharmony_ci		/* Find the entry best suited to be pushed into EA block */
271062306a36Sopenharmony_ci		for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
271162306a36Sopenharmony_ci			/* never move system.data out of the inode */
271262306a36Sopenharmony_ci			if ((last->e_name_len == 4) &&
271362306a36Sopenharmony_ci			    (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) &&
271462306a36Sopenharmony_ci			    !memcmp(last->e_name, "data", 4))
271562306a36Sopenharmony_ci				continue;
271662306a36Sopenharmony_ci			total_size = EXT4_XATTR_LEN(last->e_name_len);
271762306a36Sopenharmony_ci			if (!last->e_value_inum)
271862306a36Sopenharmony_ci				total_size += EXT4_XATTR_SIZE(
271962306a36Sopenharmony_ci					       le32_to_cpu(last->e_value_size));
272062306a36Sopenharmony_ci			if (total_size <= bfree &&
272162306a36Sopenharmony_ci			    total_size < min_total_size) {
272262306a36Sopenharmony_ci				if (total_size + ifree < isize_diff) {
272362306a36Sopenharmony_ci					small_entry = last;
272462306a36Sopenharmony_ci				} else {
272562306a36Sopenharmony_ci					entry = last;
272662306a36Sopenharmony_ci					min_total_size = total_size;
272762306a36Sopenharmony_ci				}
272862306a36Sopenharmony_ci			}
272962306a36Sopenharmony_ci		}
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ci		if (entry == NULL) {
273262306a36Sopenharmony_ci			if (small_entry == NULL)
273362306a36Sopenharmony_ci				return -ENOSPC;
273462306a36Sopenharmony_ci			entry = small_entry;
273562306a36Sopenharmony_ci		}
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci		entry_size = EXT4_XATTR_LEN(entry->e_name_len);
273862306a36Sopenharmony_ci		total_size = entry_size;
273962306a36Sopenharmony_ci		if (!entry->e_value_inum)
274062306a36Sopenharmony_ci			total_size += EXT4_XATTR_SIZE(
274162306a36Sopenharmony_ci					      le32_to_cpu(entry->e_value_size));
274262306a36Sopenharmony_ci		error = ext4_xattr_move_to_block(handle, inode, raw_inode,
274362306a36Sopenharmony_ci						 entry);
274462306a36Sopenharmony_ci		if (error)
274562306a36Sopenharmony_ci			return error;
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci		*total_ino -= entry_size;
274862306a36Sopenharmony_ci		ifree += total_size;
274962306a36Sopenharmony_ci		bfree -= total_size;
275062306a36Sopenharmony_ci	}
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	return 0;
275362306a36Sopenharmony_ci}
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci/*
275662306a36Sopenharmony_ci * Expand an inode by new_extra_isize bytes when EAs are present.
275762306a36Sopenharmony_ci * Returns 0 on success or negative error number on failure.
275862306a36Sopenharmony_ci */
275962306a36Sopenharmony_ciint ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
276062306a36Sopenharmony_ci			       struct ext4_inode *raw_inode, handle_t *handle)
276162306a36Sopenharmony_ci{
276262306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
276362306a36Sopenharmony_ci	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
276462306a36Sopenharmony_ci	static unsigned int mnt_count;
276562306a36Sopenharmony_ci	size_t min_offs;
276662306a36Sopenharmony_ci	size_t ifree, bfree;
276762306a36Sopenharmony_ci	int total_ino;
276862306a36Sopenharmony_ci	void *base, *end;
276962306a36Sopenharmony_ci	int error = 0, tried_min_extra_isize = 0;
277062306a36Sopenharmony_ci	int s_min_extra_isize = le16_to_cpu(sbi->s_es->s_min_extra_isize);
277162306a36Sopenharmony_ci	int isize_diff;	/* How much do we need to grow i_extra_isize */
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ciretry:
277462306a36Sopenharmony_ci	isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
277562306a36Sopenharmony_ci	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
277662306a36Sopenharmony_ci		return 0;
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_ci	header = IHDR(inode, raw_inode);
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	/*
278162306a36Sopenharmony_ci	 * Check if enough free space is available in the inode to shift the
278262306a36Sopenharmony_ci	 * entries ahead by new_extra_isize.
278362306a36Sopenharmony_ci	 */
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	base = IFIRST(header);
278662306a36Sopenharmony_ci	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
278762306a36Sopenharmony_ci	min_offs = end - base;
278862306a36Sopenharmony_ci	total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci	error = xattr_check_inode(inode, header, end);
279162306a36Sopenharmony_ci	if (error)
279262306a36Sopenharmony_ci		goto cleanup;
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci	ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino);
279562306a36Sopenharmony_ci	if (ifree >= isize_diff)
279662306a36Sopenharmony_ci		goto shift;
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	/*
279962306a36Sopenharmony_ci	 * Enough free space isn't available in the inode, check if
280062306a36Sopenharmony_ci	 * EA block can hold new_extra_isize bytes.
280162306a36Sopenharmony_ci	 */
280262306a36Sopenharmony_ci	if (EXT4_I(inode)->i_file_acl) {
280362306a36Sopenharmony_ci		struct buffer_head *bh;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
280662306a36Sopenharmony_ci		if (IS_ERR(bh)) {
280762306a36Sopenharmony_ci			error = PTR_ERR(bh);
280862306a36Sopenharmony_ci			goto cleanup;
280962306a36Sopenharmony_ci		}
281062306a36Sopenharmony_ci		error = ext4_xattr_check_block(inode, bh);
281162306a36Sopenharmony_ci		if (error) {
281262306a36Sopenharmony_ci			brelse(bh);
281362306a36Sopenharmony_ci			goto cleanup;
281462306a36Sopenharmony_ci		}
281562306a36Sopenharmony_ci		base = BHDR(bh);
281662306a36Sopenharmony_ci		end = bh->b_data + bh->b_size;
281762306a36Sopenharmony_ci		min_offs = end - base;
281862306a36Sopenharmony_ci		bfree = ext4_xattr_free_space(BFIRST(bh), &min_offs, base,
281962306a36Sopenharmony_ci					      NULL);
282062306a36Sopenharmony_ci		brelse(bh);
282162306a36Sopenharmony_ci		if (bfree + ifree < isize_diff) {
282262306a36Sopenharmony_ci			if (!tried_min_extra_isize && s_min_extra_isize) {
282362306a36Sopenharmony_ci				tried_min_extra_isize++;
282462306a36Sopenharmony_ci				new_extra_isize = s_min_extra_isize;
282562306a36Sopenharmony_ci				goto retry;
282662306a36Sopenharmony_ci			}
282762306a36Sopenharmony_ci			error = -ENOSPC;
282862306a36Sopenharmony_ci			goto cleanup;
282962306a36Sopenharmony_ci		}
283062306a36Sopenharmony_ci	} else {
283162306a36Sopenharmony_ci		bfree = inode->i_sb->s_blocksize;
283262306a36Sopenharmony_ci	}
283362306a36Sopenharmony_ci
283462306a36Sopenharmony_ci	error = ext4_xattr_make_inode_space(handle, inode, raw_inode,
283562306a36Sopenharmony_ci					    isize_diff, ifree, bfree,
283662306a36Sopenharmony_ci					    &total_ino);
283762306a36Sopenharmony_ci	if (error) {
283862306a36Sopenharmony_ci		if (error == -ENOSPC && !tried_min_extra_isize &&
283962306a36Sopenharmony_ci		    s_min_extra_isize) {
284062306a36Sopenharmony_ci			tried_min_extra_isize++;
284162306a36Sopenharmony_ci			new_extra_isize = s_min_extra_isize;
284262306a36Sopenharmony_ci			goto retry;
284362306a36Sopenharmony_ci		}
284462306a36Sopenharmony_ci		goto cleanup;
284562306a36Sopenharmony_ci	}
284662306a36Sopenharmony_cishift:
284762306a36Sopenharmony_ci	/* Adjust the offsets and shift the remaining entries ahead */
284862306a36Sopenharmony_ci	ext4_xattr_shift_entries(IFIRST(header), EXT4_I(inode)->i_extra_isize
284962306a36Sopenharmony_ci			- new_extra_isize, (void *)raw_inode +
285062306a36Sopenharmony_ci			EXT4_GOOD_OLD_INODE_SIZE + new_extra_isize,
285162306a36Sopenharmony_ci			(void *)header, total_ino);
285262306a36Sopenharmony_ci	EXT4_I(inode)->i_extra_isize = new_extra_isize;
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci	if (ext4_has_inline_data(inode))
285562306a36Sopenharmony_ci		error = ext4_find_inline_data_nolock(inode);
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_cicleanup:
285862306a36Sopenharmony_ci	if (error && (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count))) {
285962306a36Sopenharmony_ci		ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.",
286062306a36Sopenharmony_ci			     inode->i_ino);
286162306a36Sopenharmony_ci		mnt_count = le16_to_cpu(sbi->s_es->s_mnt_count);
286262306a36Sopenharmony_ci	}
286362306a36Sopenharmony_ci	return error;
286462306a36Sopenharmony_ci}
286562306a36Sopenharmony_ci
286662306a36Sopenharmony_ci#define EIA_INCR 16 /* must be 2^n */
286762306a36Sopenharmony_ci#define EIA_MASK (EIA_INCR - 1)
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci/* Add the large xattr @inode into @ea_inode_array for deferred iput().
287062306a36Sopenharmony_ci * If @ea_inode_array is new or full it will be grown and the old
287162306a36Sopenharmony_ci * contents copied over.
287262306a36Sopenharmony_ci */
287362306a36Sopenharmony_cistatic int
287462306a36Sopenharmony_ciext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
287562306a36Sopenharmony_ci			struct inode *inode)
287662306a36Sopenharmony_ci{
287762306a36Sopenharmony_ci	if (*ea_inode_array == NULL) {
287862306a36Sopenharmony_ci		/*
287962306a36Sopenharmony_ci		 * Start with 15 inodes, so it fits into a power-of-two size.
288062306a36Sopenharmony_ci		 * If *ea_inode_array is NULL, this is essentially offsetof()
288162306a36Sopenharmony_ci		 */
288262306a36Sopenharmony_ci		(*ea_inode_array) =
288362306a36Sopenharmony_ci			kmalloc(offsetof(struct ext4_xattr_inode_array,
288462306a36Sopenharmony_ci					 inodes[EIA_MASK]),
288562306a36Sopenharmony_ci				GFP_NOFS);
288662306a36Sopenharmony_ci		if (*ea_inode_array == NULL)
288762306a36Sopenharmony_ci			return -ENOMEM;
288862306a36Sopenharmony_ci		(*ea_inode_array)->count = 0;
288962306a36Sopenharmony_ci	} else if (((*ea_inode_array)->count & EIA_MASK) == EIA_MASK) {
289062306a36Sopenharmony_ci		/* expand the array once all 15 + n * 16 slots are full */
289162306a36Sopenharmony_ci		struct ext4_xattr_inode_array *new_array = NULL;
289262306a36Sopenharmony_ci		int count = (*ea_inode_array)->count;
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci		/* if new_array is NULL, this is essentially offsetof() */
289562306a36Sopenharmony_ci		new_array = kmalloc(
289662306a36Sopenharmony_ci				offsetof(struct ext4_xattr_inode_array,
289762306a36Sopenharmony_ci					 inodes[count + EIA_INCR]),
289862306a36Sopenharmony_ci				GFP_NOFS);
289962306a36Sopenharmony_ci		if (new_array == NULL)
290062306a36Sopenharmony_ci			return -ENOMEM;
290162306a36Sopenharmony_ci		memcpy(new_array, *ea_inode_array,
290262306a36Sopenharmony_ci		       offsetof(struct ext4_xattr_inode_array, inodes[count]));
290362306a36Sopenharmony_ci		kfree(*ea_inode_array);
290462306a36Sopenharmony_ci		*ea_inode_array = new_array;
290562306a36Sopenharmony_ci	}
290662306a36Sopenharmony_ci	(*ea_inode_array)->inodes[(*ea_inode_array)->count++] = inode;
290762306a36Sopenharmony_ci	return 0;
290862306a36Sopenharmony_ci}
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci/*
291162306a36Sopenharmony_ci * ext4_xattr_delete_inode()
291262306a36Sopenharmony_ci *
291362306a36Sopenharmony_ci * Free extended attribute resources associated with this inode. Traverse
291462306a36Sopenharmony_ci * all entries and decrement reference on any xattr inodes associated with this
291562306a36Sopenharmony_ci * inode. This is called immediately before an inode is freed. We have exclusive
291662306a36Sopenharmony_ci * access to the inode. If an orphan inode is deleted it will also release its
291762306a36Sopenharmony_ci * references on xattr block and xattr inodes.
291862306a36Sopenharmony_ci */
291962306a36Sopenharmony_ciint ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
292062306a36Sopenharmony_ci			    struct ext4_xattr_inode_array **ea_inode_array,
292162306a36Sopenharmony_ci			    int extra_credits)
292262306a36Sopenharmony_ci{
292362306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
292462306a36Sopenharmony_ci	struct ext4_xattr_ibody_header *header;
292562306a36Sopenharmony_ci	struct ext4_iloc iloc = { .bh = NULL };
292662306a36Sopenharmony_ci	struct ext4_xattr_entry *entry;
292762306a36Sopenharmony_ci	struct inode *ea_inode;
292862306a36Sopenharmony_ci	int error;
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	error = ext4_journal_ensure_credits(handle, extra_credits,
293162306a36Sopenharmony_ci			ext4_free_metadata_revoke_credits(inode->i_sb, 1));
293262306a36Sopenharmony_ci	if (error < 0) {
293362306a36Sopenharmony_ci		EXT4_ERROR_INODE(inode, "ensure credits (error %d)", error);
293462306a36Sopenharmony_ci		goto cleanup;
293562306a36Sopenharmony_ci	}
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci	if (ext4_has_feature_ea_inode(inode->i_sb) &&
293862306a36Sopenharmony_ci	    ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci		error = ext4_get_inode_loc(inode, &iloc);
294162306a36Sopenharmony_ci		if (error) {
294262306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "inode loc (error %d)", error);
294362306a36Sopenharmony_ci			goto cleanup;
294462306a36Sopenharmony_ci		}
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_ci		error = ext4_journal_get_write_access(handle, inode->i_sb,
294762306a36Sopenharmony_ci						iloc.bh, EXT4_JTR_NONE);
294862306a36Sopenharmony_ci		if (error) {
294962306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "write access (error %d)",
295062306a36Sopenharmony_ci					 error);
295162306a36Sopenharmony_ci			goto cleanup;
295262306a36Sopenharmony_ci		}
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci		header = IHDR(inode, ext4_raw_inode(&iloc));
295562306a36Sopenharmony_ci		if (header->h_magic == cpu_to_le32(EXT4_XATTR_MAGIC))
295662306a36Sopenharmony_ci			ext4_xattr_inode_dec_ref_all(handle, inode, iloc.bh,
295762306a36Sopenharmony_ci						     IFIRST(header),
295862306a36Sopenharmony_ci						     false /* block_csum */,
295962306a36Sopenharmony_ci						     ea_inode_array,
296062306a36Sopenharmony_ci						     extra_credits,
296162306a36Sopenharmony_ci						     false /* skip_quota */);
296262306a36Sopenharmony_ci	}
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci	if (EXT4_I(inode)->i_file_acl) {
296562306a36Sopenharmony_ci		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
296662306a36Sopenharmony_ci		if (IS_ERR(bh)) {
296762306a36Sopenharmony_ci			error = PTR_ERR(bh);
296862306a36Sopenharmony_ci			if (error == -EIO) {
296962306a36Sopenharmony_ci				EXT4_ERROR_INODE_ERR(inode, EIO,
297062306a36Sopenharmony_ci						     "block %llu read error",
297162306a36Sopenharmony_ci						     EXT4_I(inode)->i_file_acl);
297262306a36Sopenharmony_ci			}
297362306a36Sopenharmony_ci			bh = NULL;
297462306a36Sopenharmony_ci			goto cleanup;
297562306a36Sopenharmony_ci		}
297662306a36Sopenharmony_ci		error = ext4_xattr_check_block(inode, bh);
297762306a36Sopenharmony_ci		if (error)
297862306a36Sopenharmony_ci			goto cleanup;
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci		if (ext4_has_feature_ea_inode(inode->i_sb)) {
298162306a36Sopenharmony_ci			for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry);
298262306a36Sopenharmony_ci			     entry = EXT4_XATTR_NEXT(entry)) {
298362306a36Sopenharmony_ci				if (!entry->e_value_inum)
298462306a36Sopenharmony_ci					continue;
298562306a36Sopenharmony_ci				error = ext4_xattr_inode_iget(inode,
298662306a36Sopenharmony_ci					      le32_to_cpu(entry->e_value_inum),
298762306a36Sopenharmony_ci					      le32_to_cpu(entry->e_hash),
298862306a36Sopenharmony_ci					      &ea_inode);
298962306a36Sopenharmony_ci				if (error)
299062306a36Sopenharmony_ci					continue;
299162306a36Sopenharmony_ci				ext4_xattr_inode_free_quota(inode, ea_inode,
299262306a36Sopenharmony_ci					      le32_to_cpu(entry->e_value_size));
299362306a36Sopenharmony_ci				iput(ea_inode);
299462306a36Sopenharmony_ci			}
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci		}
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci		ext4_xattr_release_block(handle, inode, bh, ea_inode_array,
299962306a36Sopenharmony_ci					 extra_credits);
300062306a36Sopenharmony_ci		/*
300162306a36Sopenharmony_ci		 * Update i_file_acl value in the same transaction that releases
300262306a36Sopenharmony_ci		 * block.
300362306a36Sopenharmony_ci		 */
300462306a36Sopenharmony_ci		EXT4_I(inode)->i_file_acl = 0;
300562306a36Sopenharmony_ci		error = ext4_mark_inode_dirty(handle, inode);
300662306a36Sopenharmony_ci		if (error) {
300762306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "mark inode dirty (error %d)",
300862306a36Sopenharmony_ci					 error);
300962306a36Sopenharmony_ci			goto cleanup;
301062306a36Sopenharmony_ci		}
301162306a36Sopenharmony_ci		ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle);
301262306a36Sopenharmony_ci	}
301362306a36Sopenharmony_ci	error = 0;
301462306a36Sopenharmony_cicleanup:
301562306a36Sopenharmony_ci	brelse(iloc.bh);
301662306a36Sopenharmony_ci	brelse(bh);
301762306a36Sopenharmony_ci	return error;
301862306a36Sopenharmony_ci}
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_civoid ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *ea_inode_array)
302162306a36Sopenharmony_ci{
302262306a36Sopenharmony_ci	int idx;
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ci	if (ea_inode_array == NULL)
302562306a36Sopenharmony_ci		return;
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci	for (idx = 0; idx < ea_inode_array->count; ++idx)
302862306a36Sopenharmony_ci		iput(ea_inode_array->inodes[idx]);
302962306a36Sopenharmony_ci	kfree(ea_inode_array);
303062306a36Sopenharmony_ci}
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci/*
303362306a36Sopenharmony_ci * ext4_xattr_block_cache_insert()
303462306a36Sopenharmony_ci *
303562306a36Sopenharmony_ci * Create a new entry in the extended attribute block cache, and insert
303662306a36Sopenharmony_ci * it unless such an entry is already in the cache.
303762306a36Sopenharmony_ci *
303862306a36Sopenharmony_ci * Returns 0, or a negative error number on failure.
303962306a36Sopenharmony_ci */
304062306a36Sopenharmony_cistatic void
304162306a36Sopenharmony_ciext4_xattr_block_cache_insert(struct mb_cache *ea_block_cache,
304262306a36Sopenharmony_ci			      struct buffer_head *bh)
304362306a36Sopenharmony_ci{
304462306a36Sopenharmony_ci	struct ext4_xattr_header *header = BHDR(bh);
304562306a36Sopenharmony_ci	__u32 hash = le32_to_cpu(header->h_hash);
304662306a36Sopenharmony_ci	int reusable = le32_to_cpu(header->h_refcount) <
304762306a36Sopenharmony_ci		       EXT4_XATTR_REFCOUNT_MAX;
304862306a36Sopenharmony_ci	int error;
304962306a36Sopenharmony_ci
305062306a36Sopenharmony_ci	if (!ea_block_cache)
305162306a36Sopenharmony_ci		return;
305262306a36Sopenharmony_ci	error = mb_cache_entry_create(ea_block_cache, GFP_NOFS, hash,
305362306a36Sopenharmony_ci				      bh->b_blocknr, reusable);
305462306a36Sopenharmony_ci	if (error) {
305562306a36Sopenharmony_ci		if (error == -EBUSY)
305662306a36Sopenharmony_ci			ea_bdebug(bh, "already in cache");
305762306a36Sopenharmony_ci	} else
305862306a36Sopenharmony_ci		ea_bdebug(bh, "inserting [%x]", (int)hash);
305962306a36Sopenharmony_ci}
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ci/*
306262306a36Sopenharmony_ci * ext4_xattr_cmp()
306362306a36Sopenharmony_ci *
306462306a36Sopenharmony_ci * Compare two extended attribute blocks for equality.
306562306a36Sopenharmony_ci *
306662306a36Sopenharmony_ci * Returns 0 if the blocks are equal, 1 if they differ, and
306762306a36Sopenharmony_ci * a negative error number on errors.
306862306a36Sopenharmony_ci */
306962306a36Sopenharmony_cistatic int
307062306a36Sopenharmony_ciext4_xattr_cmp(struct ext4_xattr_header *header1,
307162306a36Sopenharmony_ci	       struct ext4_xattr_header *header2)
307262306a36Sopenharmony_ci{
307362306a36Sopenharmony_ci	struct ext4_xattr_entry *entry1, *entry2;
307462306a36Sopenharmony_ci
307562306a36Sopenharmony_ci	entry1 = ENTRY(header1+1);
307662306a36Sopenharmony_ci	entry2 = ENTRY(header2+1);
307762306a36Sopenharmony_ci	while (!IS_LAST_ENTRY(entry1)) {
307862306a36Sopenharmony_ci		if (IS_LAST_ENTRY(entry2))
307962306a36Sopenharmony_ci			return 1;
308062306a36Sopenharmony_ci		if (entry1->e_hash != entry2->e_hash ||
308162306a36Sopenharmony_ci		    entry1->e_name_index != entry2->e_name_index ||
308262306a36Sopenharmony_ci		    entry1->e_name_len != entry2->e_name_len ||
308362306a36Sopenharmony_ci		    entry1->e_value_size != entry2->e_value_size ||
308462306a36Sopenharmony_ci		    entry1->e_value_inum != entry2->e_value_inum ||
308562306a36Sopenharmony_ci		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
308662306a36Sopenharmony_ci			return 1;
308762306a36Sopenharmony_ci		if (!entry1->e_value_inum &&
308862306a36Sopenharmony_ci		    memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
308962306a36Sopenharmony_ci			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
309062306a36Sopenharmony_ci			   le32_to_cpu(entry1->e_value_size)))
309162306a36Sopenharmony_ci			return 1;
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_ci		entry1 = EXT4_XATTR_NEXT(entry1);
309462306a36Sopenharmony_ci		entry2 = EXT4_XATTR_NEXT(entry2);
309562306a36Sopenharmony_ci	}
309662306a36Sopenharmony_ci	if (!IS_LAST_ENTRY(entry2))
309762306a36Sopenharmony_ci		return 1;
309862306a36Sopenharmony_ci	return 0;
309962306a36Sopenharmony_ci}
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci/*
310262306a36Sopenharmony_ci * ext4_xattr_block_cache_find()
310362306a36Sopenharmony_ci *
310462306a36Sopenharmony_ci * Find an identical extended attribute block.
310562306a36Sopenharmony_ci *
310662306a36Sopenharmony_ci * Returns a pointer to the block found, or NULL if such a block was
310762306a36Sopenharmony_ci * not found or an error occurred.
310862306a36Sopenharmony_ci */
310962306a36Sopenharmony_cistatic struct buffer_head *
311062306a36Sopenharmony_ciext4_xattr_block_cache_find(struct inode *inode,
311162306a36Sopenharmony_ci			    struct ext4_xattr_header *header,
311262306a36Sopenharmony_ci			    struct mb_cache_entry **pce)
311362306a36Sopenharmony_ci{
311462306a36Sopenharmony_ci	__u32 hash = le32_to_cpu(header->h_hash);
311562306a36Sopenharmony_ci	struct mb_cache_entry *ce;
311662306a36Sopenharmony_ci	struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
311762306a36Sopenharmony_ci
311862306a36Sopenharmony_ci	if (!ea_block_cache)
311962306a36Sopenharmony_ci		return NULL;
312062306a36Sopenharmony_ci	if (!header->h_hash)
312162306a36Sopenharmony_ci		return NULL;  /* never share */
312262306a36Sopenharmony_ci	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
312362306a36Sopenharmony_ci	ce = mb_cache_entry_find_first(ea_block_cache, hash);
312462306a36Sopenharmony_ci	while (ce) {
312562306a36Sopenharmony_ci		struct buffer_head *bh;
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci		bh = ext4_sb_bread(inode->i_sb, ce->e_value, REQ_PRIO);
312862306a36Sopenharmony_ci		if (IS_ERR(bh)) {
312962306a36Sopenharmony_ci			if (PTR_ERR(bh) == -ENOMEM)
313062306a36Sopenharmony_ci				return NULL;
313162306a36Sopenharmony_ci			bh = NULL;
313262306a36Sopenharmony_ci			EXT4_ERROR_INODE(inode, "block %lu read error",
313362306a36Sopenharmony_ci					 (unsigned long)ce->e_value);
313462306a36Sopenharmony_ci		} else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) {
313562306a36Sopenharmony_ci			*pce = ce;
313662306a36Sopenharmony_ci			return bh;
313762306a36Sopenharmony_ci		}
313862306a36Sopenharmony_ci		brelse(bh);
313962306a36Sopenharmony_ci		ce = mb_cache_entry_find_next(ea_block_cache, ce);
314062306a36Sopenharmony_ci	}
314162306a36Sopenharmony_ci	return NULL;
314262306a36Sopenharmony_ci}
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_ci#define NAME_HASH_SHIFT 5
314562306a36Sopenharmony_ci#define VALUE_HASH_SHIFT 16
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci/*
314862306a36Sopenharmony_ci * ext4_xattr_hash_entry()
314962306a36Sopenharmony_ci *
315062306a36Sopenharmony_ci * Compute the hash of an extended attribute.
315162306a36Sopenharmony_ci */
315262306a36Sopenharmony_cistatic __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
315362306a36Sopenharmony_ci				    size_t value_count)
315462306a36Sopenharmony_ci{
315562306a36Sopenharmony_ci	__u32 hash = 0;
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci	while (name_len--) {
315862306a36Sopenharmony_ci		hash = (hash << NAME_HASH_SHIFT) ^
315962306a36Sopenharmony_ci		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
316062306a36Sopenharmony_ci		       (unsigned char)*name++;
316162306a36Sopenharmony_ci	}
316262306a36Sopenharmony_ci	while (value_count--) {
316362306a36Sopenharmony_ci		hash = (hash << VALUE_HASH_SHIFT) ^
316462306a36Sopenharmony_ci		       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
316562306a36Sopenharmony_ci		       le32_to_cpu(*value++);
316662306a36Sopenharmony_ci	}
316762306a36Sopenharmony_ci	return cpu_to_le32(hash);
316862306a36Sopenharmony_ci}
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci/*
317162306a36Sopenharmony_ci * ext4_xattr_hash_entry_signed()
317262306a36Sopenharmony_ci *
317362306a36Sopenharmony_ci * Compute the hash of an extended attribute incorrectly.
317462306a36Sopenharmony_ci */
317562306a36Sopenharmony_cistatic __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value, size_t value_count)
317662306a36Sopenharmony_ci{
317762306a36Sopenharmony_ci	__u32 hash = 0;
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ci	while (name_len--) {
318062306a36Sopenharmony_ci		hash = (hash << NAME_HASH_SHIFT) ^
318162306a36Sopenharmony_ci		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
318262306a36Sopenharmony_ci		       (signed char)*name++;
318362306a36Sopenharmony_ci	}
318462306a36Sopenharmony_ci	while (value_count--) {
318562306a36Sopenharmony_ci		hash = (hash << VALUE_HASH_SHIFT) ^
318662306a36Sopenharmony_ci		       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
318762306a36Sopenharmony_ci		       le32_to_cpu(*value++);
318862306a36Sopenharmony_ci	}
318962306a36Sopenharmony_ci	return cpu_to_le32(hash);
319062306a36Sopenharmony_ci}
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci#undef NAME_HASH_SHIFT
319362306a36Sopenharmony_ci#undef VALUE_HASH_SHIFT
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci#define BLOCK_HASH_SHIFT 16
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_ci/*
319862306a36Sopenharmony_ci * ext4_xattr_rehash()
319962306a36Sopenharmony_ci *
320062306a36Sopenharmony_ci * Re-compute the extended attribute hash value after an entry has changed.
320162306a36Sopenharmony_ci */
320262306a36Sopenharmony_cistatic void ext4_xattr_rehash(struct ext4_xattr_header *header)
320362306a36Sopenharmony_ci{
320462306a36Sopenharmony_ci	struct ext4_xattr_entry *here;
320562306a36Sopenharmony_ci	__u32 hash = 0;
320662306a36Sopenharmony_ci
320762306a36Sopenharmony_ci	here = ENTRY(header+1);
320862306a36Sopenharmony_ci	while (!IS_LAST_ENTRY(here)) {
320962306a36Sopenharmony_ci		if (!here->e_hash) {
321062306a36Sopenharmony_ci			/* Block is not shared if an entry's hash value == 0 */
321162306a36Sopenharmony_ci			hash = 0;
321262306a36Sopenharmony_ci			break;
321362306a36Sopenharmony_ci		}
321462306a36Sopenharmony_ci		hash = (hash << BLOCK_HASH_SHIFT) ^
321562306a36Sopenharmony_ci		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
321662306a36Sopenharmony_ci		       le32_to_cpu(here->e_hash);
321762306a36Sopenharmony_ci		here = EXT4_XATTR_NEXT(here);
321862306a36Sopenharmony_ci	}
321962306a36Sopenharmony_ci	header->h_hash = cpu_to_le32(hash);
322062306a36Sopenharmony_ci}
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci#undef BLOCK_HASH_SHIFT
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci#define	HASH_BUCKET_BITS	10
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_cistruct mb_cache *
322762306a36Sopenharmony_ciext4_xattr_create_cache(void)
322862306a36Sopenharmony_ci{
322962306a36Sopenharmony_ci	return mb_cache_create(HASH_BUCKET_BITS);
323062306a36Sopenharmony_ci}
323162306a36Sopenharmony_ci
323262306a36Sopenharmony_civoid ext4_xattr_destroy_cache(struct mb_cache *cache)
323362306a36Sopenharmony_ci{
323462306a36Sopenharmony_ci	if (cache)
323562306a36Sopenharmony_ci		mb_cache_destroy(cache);
323662306a36Sopenharmony_ci}
323762306a36Sopenharmony_ci
3238