xref: /openbmc/linux/fs/btrfs/xattr.c (revision d5e09e38)
1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0
25103e947SJosef Bacik /*
35103e947SJosef Bacik  * Copyright (C) 2007 Red Hat.  All rights reserved.
45103e947SJosef Bacik  */
55103e947SJosef Bacik 
65103e947SJosef Bacik #include <linux/init.h>
75103e947SJosef Bacik #include <linux/fs.h>
85103e947SJosef Bacik #include <linux/slab.h>
95103e947SJosef Bacik #include <linux/rwsem.h>
105103e947SJosef Bacik #include <linux/xattr.h>
110279b4cdSJim Owens #include <linux/security.h>
12996a710dSChristoph Hellwig #include <linux/posix_acl_xattr.h>
13ae5e165dSJeff Layton #include <linux/iversion.h>
14827aa18eSFilipe Manana #include <linux/sched/mm.h>
155103e947SJosef Bacik #include "ctree.h"
16ec8eb376SJosef Bacik #include "fs.h"
17ec8eb376SJosef Bacik #include "messages.h"
185103e947SJosef Bacik #include "btrfs_inode.h"
195103e947SJosef Bacik #include "transaction.h"
205103e947SJosef Bacik #include "xattr.h"
215103e947SJosef Bacik #include "disk-io.h"
2263541927SFilipe David Borba Manana #include "props.h"
235f5bc6b1SFilipe Manana #include "locking.h"
2407e81dc9SJosef Bacik #include "accessors.h"
25f2b39277SJosef Bacik #include "dir-item.h"
2633268eafSJosef Bacik 
btrfs_getxattr(struct inode * inode,const char * name,void * buffer,size_t size)27bcadd705SDavid Sterba int btrfs_getxattr(struct inode *inode, const char *name,
2895819c05SChristoph Hellwig 				void *buffer, size_t size)
295103e947SJosef Bacik {
305103e947SJosef Bacik 	struct btrfs_dir_item *di;
315103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
325103e947SJosef Bacik 	struct btrfs_path *path;
335103e947SJosef Bacik 	struct extent_buffer *leaf;
345103e947SJosef Bacik 	int ret = 0;
355103e947SJosef Bacik 	unsigned long data_ptr;
365103e947SJosef Bacik 
375103e947SJosef Bacik 	path = btrfs_alloc_path();
3895819c05SChristoph Hellwig 	if (!path)
395103e947SJosef Bacik 		return -ENOMEM;
405103e947SJosef Bacik 
415103e947SJosef Bacik 	/* lookup the xattr by name */
42f85b7379SDavid Sterba 	di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(BTRFS_I(inode)),
43f85b7379SDavid Sterba 			name, strlen(name), 0);
4407060404SJosef Bacik 	if (!di) {
455103e947SJosef Bacik 		ret = -ENODATA;
465103e947SJosef Bacik 		goto out;
4707060404SJosef Bacik 	} else if (IS_ERR(di)) {
4807060404SJosef Bacik 		ret = PTR_ERR(di);
4907060404SJosef Bacik 		goto out;
505103e947SJosef Bacik 	}
515103e947SJosef Bacik 
525103e947SJosef Bacik 	leaf = path->nodes[0];
535103e947SJosef Bacik 	/* if size is 0, that means we want the size of the attr */
545103e947SJosef Bacik 	if (!size) {
555103e947SJosef Bacik 		ret = btrfs_dir_data_len(leaf, di);
565103e947SJosef Bacik 		goto out;
575103e947SJosef Bacik 	}
585103e947SJosef Bacik 
595103e947SJosef Bacik 	/* now get the data out of our dir_item */
605103e947SJosef Bacik 	if (btrfs_dir_data_len(leaf, di) > size) {
615103e947SJosef Bacik 		ret = -ERANGE;
625103e947SJosef Bacik 		goto out;
635103e947SJosef Bacik 	}
6407060404SJosef Bacik 
6507060404SJosef Bacik 	/*
6607060404SJosef Bacik 	 * The way things are packed into the leaf is like this
6707060404SJosef Bacik 	 * |struct btrfs_dir_item|name|data|
6807060404SJosef Bacik 	 * where name is the xattr name, so security.foo, and data is the
6907060404SJosef Bacik 	 * content of the xattr.  data_ptr points to the location in memory
7007060404SJosef Bacik 	 * where the data starts in the in memory leaf
7107060404SJosef Bacik 	 */
725103e947SJosef Bacik 	data_ptr = (unsigned long)((char *)(di + 1) +
735103e947SJosef Bacik 				   btrfs_dir_name_len(leaf, di));
745103e947SJosef Bacik 	read_extent_buffer(leaf, buffer, data_ptr,
753acd7ee8SJosef Bacik 			   btrfs_dir_data_len(leaf, di));
765103e947SJosef Bacik 	ret = btrfs_dir_data_len(leaf, di);
775103e947SJosef Bacik 
785103e947SJosef Bacik out:
795103e947SJosef Bacik 	btrfs_free_path(path);
805103e947SJosef Bacik 	return ret;
815103e947SJosef Bacik }
825103e947SJosef Bacik 
btrfs_setxattr(struct btrfs_trans_handle * trans,struct inode * inode,const char * name,const void * value,size_t size,int flags)833e125a74SAnand Jain int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode,
843e125a74SAnand Jain 		   const char *name, const void *value, size_t size, int flags)
855103e947SJosef Bacik {
865f5bc6b1SFilipe Manana 	struct btrfs_dir_item *di = NULL;
875103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
882ff7e61eSJeff Mahoney 	struct btrfs_fs_info *fs_info = root->fs_info;
895103e947SJosef Bacik 	struct btrfs_path *path;
90f34f57a3SYan, Zheng 	size_t name_len = strlen(name);
91f34f57a3SYan, Zheng 	int ret = 0;
92f34f57a3SYan, Zheng 
9304e6863bSAnand Jain 	ASSERT(trans);
9404e6863bSAnand Jain 
95da17066cSJeff Mahoney 	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root->fs_info))
96f34f57a3SYan, Zheng 		return -ENOSPC;
975103e947SJosef Bacik 
985103e947SJosef Bacik 	path = btrfs_alloc_path();
9995819c05SChristoph Hellwig 	if (!path)
1005103e947SJosef Bacik 		return -ENOMEM;
1015f5bc6b1SFilipe Manana 	path->skip_release_on_error = 1;
1025103e947SJosef Bacik 
1035f5bc6b1SFilipe Manana 	if (!value) {
104f85b7379SDavid Sterba 		di = btrfs_lookup_xattr(trans, root, path,
105f85b7379SDavid Sterba 				btrfs_ino(BTRFS_I(inode)), name, name_len, -1);
1065f5bc6b1SFilipe Manana 		if (!di && (flags & XATTR_REPLACE))
1075f5bc6b1SFilipe Manana 			ret = -ENODATA;
1085cdf83edSFilipe Manana 		else if (IS_ERR(di))
1095cdf83edSFilipe Manana 			ret = PTR_ERR(di);
1105f5bc6b1SFilipe Manana 		else if (di)
1115f5bc6b1SFilipe Manana 			ret = btrfs_delete_one_dir_name(trans, root, path, di);
1125103e947SJosef Bacik 		goto out;
1135f5bc6b1SFilipe Manana 	}
1145f5bc6b1SFilipe Manana 
1155f5bc6b1SFilipe Manana 	/*
1165f5bc6b1SFilipe Manana 	 * For a replace we can't just do the insert blindly.
1175f5bc6b1SFilipe Manana 	 * Do a lookup first (read-only btrfs_search_slot), and return if xattr
1185f5bc6b1SFilipe Manana 	 * doesn't exist. If it exists, fall down below to the insert/replace
1195f5bc6b1SFilipe Manana 	 * path - we can't race with a concurrent xattr delete, because the VFS
1205f5bc6b1SFilipe Manana 	 * locks the inode's i_mutex before calling setxattr or removexattr.
1215f5bc6b1SFilipe Manana 	 */
1225f5bc6b1SFilipe Manana 	if (flags & XATTR_REPLACE) {
1235955102cSAl Viro 		ASSERT(inode_is_locked(inode));
124f85b7379SDavid Sterba 		di = btrfs_lookup_xattr(NULL, root, path,
125f85b7379SDavid Sterba 				btrfs_ino(BTRFS_I(inode)), name, name_len, 0);
1265cdf83edSFilipe Manana 		if (!di)
1275103e947SJosef Bacik 			ret = -ENODATA;
1285cdf83edSFilipe Manana 		else if (IS_ERR(di))
1295cdf83edSFilipe Manana 			ret = PTR_ERR(di);
1305cdf83edSFilipe Manana 		if (ret)
1315103e947SJosef Bacik 			goto out;
132fa09200bSJosef Bacik 		btrfs_release_path(path);
1335f5bc6b1SFilipe Manana 		di = NULL;
13433268eafSJosef Bacik 	}
1355103e947SJosef Bacik 
1364a0cc7caSNikolay Borisov 	ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(BTRFS_I(inode)),
137f34f57a3SYan, Zheng 				      name, name_len, value, size);
1385f5bc6b1SFilipe Manana 	if (ret == -EOVERFLOW) {
139ed3ee9f4SJosef Bacik 		/*
1405f5bc6b1SFilipe Manana 		 * We have an existing item in a leaf, split_leaf couldn't
1415f5bc6b1SFilipe Manana 		 * expand it. That item might have or not a dir_item that
1425f5bc6b1SFilipe Manana 		 * matches our target xattr, so lets check.
143ed3ee9f4SJosef Bacik 		 */
1445f5bc6b1SFilipe Manana 		ret = 0;
14549d0c642SFilipe Manana 		btrfs_assert_tree_write_locked(path->nodes[0]);
1462ff7e61eSJeff Mahoney 		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
1475f5bc6b1SFilipe Manana 		if (!di && !(flags & XATTR_REPLACE)) {
1485f5bc6b1SFilipe Manana 			ret = -ENOSPC;
149fa09200bSJosef Bacik 			goto out;
1505f5bc6b1SFilipe Manana 		}
1515f5bc6b1SFilipe Manana 	} else if (ret == -EEXIST) {
1525f5bc6b1SFilipe Manana 		ret = 0;
1532ff7e61eSJeff Mahoney 		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
1545f5bc6b1SFilipe Manana 		ASSERT(di); /* logic error */
1555f5bc6b1SFilipe Manana 	} else if (ret) {
156fa09200bSJosef Bacik 		goto out;
157fa09200bSJosef Bacik 	}
158fa09200bSJosef Bacik 
1595f5bc6b1SFilipe Manana 	if (di && (flags & XATTR_CREATE)) {
1605f5bc6b1SFilipe Manana 		ret = -EEXIST;
1615f5bc6b1SFilipe Manana 		goto out;
1625f5bc6b1SFilipe Manana 	}
1635f5bc6b1SFilipe Manana 
1645f5bc6b1SFilipe Manana 	if (di) {
1655f5bc6b1SFilipe Manana 		/*
1665f5bc6b1SFilipe Manana 		 * We're doing a replace, and it must be atomic, that is, at
1675f5bc6b1SFilipe Manana 		 * any point in time we have either the old or the new xattr
1685f5bc6b1SFilipe Manana 		 * value in the tree. We don't want readers (getxattr and
1695f5bc6b1SFilipe Manana 		 * listxattrs) to miss a value, this is specially important
1705f5bc6b1SFilipe Manana 		 * for ACLs.
1715f5bc6b1SFilipe Manana 		 */
1725f5bc6b1SFilipe Manana 		const int slot = path->slots[0];
1735f5bc6b1SFilipe Manana 		struct extent_buffer *leaf = path->nodes[0];
1745f5bc6b1SFilipe Manana 		const u16 old_data_len = btrfs_dir_data_len(leaf, di);
1753212fa14SJosef Bacik 		const u32 item_size = btrfs_item_size(leaf, slot);
1765f5bc6b1SFilipe Manana 		const u32 data_size = sizeof(*di) + name_len + size;
1775f5bc6b1SFilipe Manana 		unsigned long data_ptr;
1785f5bc6b1SFilipe Manana 		char *ptr;
1795f5bc6b1SFilipe Manana 
1805f5bc6b1SFilipe Manana 		if (size > old_data_len) {
181e902baacSDavid Sterba 			if (btrfs_leaf_free_space(leaf) <
1825f5bc6b1SFilipe Manana 			    (size - old_data_len)) {
1835f5bc6b1SFilipe Manana 				ret = -ENOSPC;
1845f5bc6b1SFilipe Manana 				goto out;
1855f5bc6b1SFilipe Manana 			}
1865f5bc6b1SFilipe Manana 		}
1875f5bc6b1SFilipe Manana 
1885f5bc6b1SFilipe Manana 		if (old_data_len + name_len + sizeof(*di) == item_size) {
1895f5bc6b1SFilipe Manana 			/* No other xattrs packed in the same leaf item. */
1905f5bc6b1SFilipe Manana 			if (size > old_data_len)
191*d5e09e38SFilipe Manana 				btrfs_extend_item(trans, path, size - old_data_len);
1925f5bc6b1SFilipe Manana 			else if (size < old_data_len)
193*d5e09e38SFilipe Manana 				btrfs_truncate_item(trans, path, data_size, 1);
1945f5bc6b1SFilipe Manana 		} else {
1955f5bc6b1SFilipe Manana 			/* There are other xattrs packed in the same item. */
196fa09200bSJosef Bacik 			ret = btrfs_delete_one_dir_name(trans, root, path, di);
197fa09200bSJosef Bacik 			if (ret)
198fa09200bSJosef Bacik 				goto out;
199*d5e09e38SFilipe Manana 			btrfs_extend_item(trans, path, data_size);
200fa09200bSJosef Bacik 		}
2015f5bc6b1SFilipe Manana 
2025f5bc6b1SFilipe Manana 		ptr = btrfs_item_ptr(leaf, slot, char);
2033212fa14SJosef Bacik 		ptr += btrfs_item_size(leaf, slot) - data_size;
2045f5bc6b1SFilipe Manana 		di = (struct btrfs_dir_item *)ptr;
2055f5bc6b1SFilipe Manana 		btrfs_set_dir_data_len(leaf, di, size);
2065f5bc6b1SFilipe Manana 		data_ptr = ((unsigned long)(di + 1)) + name_len;
2075f5bc6b1SFilipe Manana 		write_extent_buffer(leaf, value, data_ptr, size);
208*d5e09e38SFilipe Manana 		btrfs_mark_buffer_dirty(trans, leaf);
2095f5bc6b1SFilipe Manana 	} else {
2105f5bc6b1SFilipe Manana 		/*
2115f5bc6b1SFilipe Manana 		 * Insert, and we had space for the xattr, so path->slots[0] is
2125f5bc6b1SFilipe Manana 		 * where our xattr dir_item is and btrfs_insert_xattr_item()
2135f5bc6b1SFilipe Manana 		 * filled it.
2145f5bc6b1SFilipe Manana 		 */
215fa09200bSJosef Bacik 	}
2165103e947SJosef Bacik out:
217f34f57a3SYan, Zheng 	btrfs_free_path(path);
218f2f121abSFilipe Manana 	if (!ret) {
2193763771cSFilipe Manana 		set_bit(BTRFS_INODE_COPY_EVERYTHING,
2203763771cSFilipe Manana 			&BTRFS_I(inode)->runtime_flags);
221f2f121abSFilipe Manana 		clear_bit(BTRFS_INODE_NO_XATTRS, &BTRFS_I(inode)->runtime_flags);
222f2f121abSFilipe Manana 	}
223f34f57a3SYan, Zheng 	return ret;
2245103e947SJosef Bacik }
2255103e947SJosef Bacik 
2264815053aSDavid Sterba /*
2274815053aSDavid Sterba  * @value: "" makes the attribute to empty, NULL removes it
2284815053aSDavid Sterba  */
btrfs_setxattr_trans(struct inode * inode,const char * name,const void * value,size_t size,int flags)229e3de9b15SAnand Jain int btrfs_setxattr_trans(struct inode *inode, const char *name,
230f34f57a3SYan, Zheng 			 const void *value, size_t size, int flags)
231f34f57a3SYan, Zheng {
232f34f57a3SYan, Zheng 	struct btrfs_root *root = BTRFS_I(inode)->root;
233e3de9b15SAnand Jain 	struct btrfs_trans_handle *trans;
234fd57a98dSFilipe Manana 	const bool start_trans = (current->journal_info == NULL);
235f34f57a3SYan, Zheng 	int ret;
236f34f57a3SYan, Zheng 
237fd57a98dSFilipe Manana 	if (start_trans) {
238fd57a98dSFilipe Manana 		/*
239fd57a98dSFilipe Manana 		 * 1 unit for inserting/updating/deleting the xattr
240fd57a98dSFilipe Manana 		 * 1 unit for the inode item update
241fd57a98dSFilipe Manana 		 */
242a22285a6SYan, Zheng 		trans = btrfs_start_transaction(root, 2);
243a22285a6SYan, Zheng 		if (IS_ERR(trans))
244a22285a6SYan, Zheng 			return PTR_ERR(trans);
245fd57a98dSFilipe Manana 	} else {
246fd57a98dSFilipe Manana 		/*
247fd57a98dSFilipe Manana 		 * This can happen when smack is enabled and a directory is being
248fd57a98dSFilipe Manana 		 * created. It happens through d_instantiate_new(), which calls
249fd57a98dSFilipe Manana 		 * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
250fd57a98dSFilipe Manana 		 * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
251fd57a98dSFilipe Manana 		 * inode. We have already reserved space for the xattr and inode
252fd57a98dSFilipe Manana 		 * update at btrfs_mkdir(), so just use the transaction handle.
253fd57a98dSFilipe Manana 		 * We don't join or start a transaction, as that will reset the
254fd57a98dSFilipe Manana 		 * block_rsv of the handle and trigger a warning for the start
255fd57a98dSFilipe Manana 		 * case.
256fd57a98dSFilipe Manana 		 */
257fd57a98dSFilipe Manana 		ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
258fd57a98dSFilipe Manana 			       XATTR_SECURITY_PREFIX_LEN) == 0);
259fd57a98dSFilipe Manana 		trans = current->journal_info;
260fd57a98dSFilipe Manana 	}
261f34f57a3SYan, Zheng 
2622d74fa3eSAnand Jain 	ret = btrfs_setxattr(trans, inode, name, value, size, flags);
263f34f57a3SYan, Zheng 	if (ret)
264f34f57a3SYan, Zheng 		goto out;
265f34f57a3SYan, Zheng 
2660c4d2d95SJosef Bacik 	inode_inc_iversion(inode);
2672a9462deSJeff Layton 	inode_set_ctime_current(inode);
2689a56fcd1SNikolay Borisov 	ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
269193b4e83SFilipe Manana 	if (ret)
270193b4e83SFilipe Manana 		btrfs_abort_transaction(trans, ret);
271f34f57a3SYan, Zheng out:
272fd57a98dSFilipe Manana 	if (start_trans)
2733a45bb20SJeff Mahoney 		btrfs_end_transaction(trans);
2745103e947SJosef Bacik 	return ret;
2755103e947SJosef Bacik }
2765103e947SJosef Bacik 
btrfs_listxattr(struct dentry * dentry,char * buffer,size_t size)2775103e947SJosef Bacik ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
2785103e947SJosef Bacik {
279184b3d19SGabriel Niebler 	struct btrfs_key found_key;
280daac7ba6SFilipe Manana 	struct btrfs_key key;
2812b0143b5SDavid Howells 	struct inode *inode = d_inode(dentry);
2825103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
2835103e947SJosef Bacik 	struct btrfs_path *path;
284184b3d19SGabriel Niebler 	int iter_ret = 0;
285daac7ba6SFilipe Manana 	int ret = 0;
286eaa47d86SChristoph Hellwig 	size_t total_size = 0, size_left = size;
2875103e947SJosef Bacik 
2885103e947SJosef Bacik 	/*
2895103e947SJosef Bacik 	 * ok we want all objects associated with this id.
2905103e947SJosef Bacik 	 * NOTE: we set key.offset = 0; because we want to start with the
2915103e947SJosef Bacik 	 * first xattr that we find and walk forward
2925103e947SJosef Bacik 	 */
2934a0cc7caSNikolay Borisov 	key.objectid = btrfs_ino(BTRFS_I(inode));
294962a298fSDavid Sterba 	key.type = BTRFS_XATTR_ITEM_KEY;
2955103e947SJosef Bacik 	key.offset = 0;
2965103e947SJosef Bacik 
2975103e947SJosef Bacik 	path = btrfs_alloc_path();
2985103e947SJosef Bacik 	if (!path)
2995103e947SJosef Bacik 		return -ENOMEM;
300e4058b54SDavid Sterba 	path->reada = READA_FORWARD;
3015103e947SJosef Bacik 
3025103e947SJosef Bacik 	/* search for our xattrs */
303184b3d19SGabriel Niebler 	btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) {
304daac7ba6SFilipe Manana 		struct extent_buffer *leaf;
305daac7ba6SFilipe Manana 		int slot;
306daac7ba6SFilipe Manana 		struct btrfs_dir_item *di;
307daac7ba6SFilipe Manana 		u32 item_size;
308daac7ba6SFilipe Manana 		u32 cur;
309daac7ba6SFilipe Manana 
3105103e947SJosef Bacik 		leaf = path->nodes[0];
3115103e947SJosef Bacik 		slot = path->slots[0];
3125103e947SJosef Bacik 
3135103e947SJosef Bacik 		/* check to make sure this item is what we want */
3145103e947SJosef Bacik 		if (found_key.objectid != key.objectid)
3155103e947SJosef Bacik 			break;
316f1cd1f0bSFilipe Manana 		if (found_key.type > BTRFS_XATTR_ITEM_KEY)
3175103e947SJosef Bacik 			break;
318f1cd1f0bSFilipe Manana 		if (found_key.type < BTRFS_XATTR_ITEM_KEY)
319184b3d19SGabriel Niebler 			continue;
3205103e947SJosef Bacik 
3215103e947SJosef Bacik 		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
3223212fa14SJosef Bacik 		item_size = btrfs_item_size(leaf, slot);
323daac7ba6SFilipe Manana 		cur = 0;
324daac7ba6SFilipe Manana 		while (cur < item_size) {
325daac7ba6SFilipe Manana 			u16 name_len = btrfs_dir_name_len(leaf, di);
326daac7ba6SFilipe Manana 			u16 data_len = btrfs_dir_data_len(leaf, di);
327daac7ba6SFilipe Manana 			u32 this_len = sizeof(*di) + name_len + data_len;
328daac7ba6SFilipe Manana 			unsigned long name_ptr = (unsigned long)(di + 1);
3295103e947SJosef Bacik 
330eaa47d86SChristoph Hellwig 			total_size += name_len + 1;
331daac7ba6SFilipe Manana 			/*
332daac7ba6SFilipe Manana 			 * We are just looking for how big our buffer needs to
333daac7ba6SFilipe Manana 			 * be.
334daac7ba6SFilipe Manana 			 */
3355103e947SJosef Bacik 			if (!size)
3362e6a0035SLi Zefan 				goto next;
3375103e947SJosef Bacik 
338eaa47d86SChristoph Hellwig 			if (!buffer || (name_len + 1) > size_left) {
339184b3d19SGabriel Niebler 			        iter_ret = -ERANGE;
340184b3d19SGabriel Niebler 				break;
3415103e947SJosef Bacik 			}
3425103e947SJosef Bacik 
343eaa47d86SChristoph Hellwig 			read_extent_buffer(leaf, buffer, name_ptr, name_len);
344eaa47d86SChristoph Hellwig 			buffer[name_len] = '\0';
345eaa47d86SChristoph Hellwig 
346eaa47d86SChristoph Hellwig 			size_left -= name_len + 1;
347eaa47d86SChristoph Hellwig 			buffer += name_len + 1;
3482e6a0035SLi Zefan next:
349daac7ba6SFilipe Manana 			cur += this_len;
350daac7ba6SFilipe Manana 			di = (struct btrfs_dir_item *)((char *)di + this_len);
351daac7ba6SFilipe Manana 		}
3525103e947SJosef Bacik 	}
353184b3d19SGabriel Niebler 
354184b3d19SGabriel Niebler 	if (iter_ret < 0)
355184b3d19SGabriel Niebler 		ret = iter_ret;
356184b3d19SGabriel Niebler 	else
3575103e947SJosef Bacik 		ret = total_size;
3585103e947SJosef Bacik 
3595103e947SJosef Bacik 	btrfs_free_path(path);
3605103e947SJosef Bacik 
3615103e947SJosef Bacik 	return ret;
3625103e947SJosef Bacik }
3635103e947SJosef Bacik 
btrfs_xattr_handler_get(const struct xattr_handler * handler,struct dentry * unused,struct inode * inode,const char * name,void * buffer,size_t size)3649172abbcSAndreas Gruenbacher static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
365b296821aSAl Viro 				   struct dentry *unused, struct inode *inode,
366b296821aSAl Viro 				   const char *name, void *buffer, size_t size)
3679172abbcSAndreas Gruenbacher {
3689172abbcSAndreas Gruenbacher 	name = xattr_full_name(handler, name);
3697852781dSDavid Sterba 	return btrfs_getxattr(inode, name, buffer, size);
3709172abbcSAndreas Gruenbacher }
3719172abbcSAndreas Gruenbacher 
btrfs_xattr_handler_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * unused,struct inode * inode,const char * name,const void * buffer,size_t size,int flags)3729172abbcSAndreas Gruenbacher static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
37339f60c1cSChristian Brauner 				   struct mnt_idmap *idmap,
37459301226SAl Viro 				   struct dentry *unused, struct inode *inode,
37559301226SAl Viro 				   const char *name, const void *buffer,
37659301226SAl Viro 				   size_t size, int flags)
3779172abbcSAndreas Gruenbacher {
378b5111127SGoldwyn Rodrigues 	if (btrfs_root_readonly(BTRFS_I(inode)->root))
379b5111127SGoldwyn Rodrigues 		return -EROFS;
380b5111127SGoldwyn Rodrigues 
3819172abbcSAndreas Gruenbacher 	name = xattr_full_name(handler, name);
382e3de9b15SAnand Jain 	return btrfs_setxattr_trans(inode, name, buffer, size, flags);
3839172abbcSAndreas Gruenbacher }
3849172abbcSAndreas Gruenbacher 
btrfs_xattr_handler_set_prop(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * unused,struct inode * inode,const char * name,const void * value,size_t size,int flags)3859172abbcSAndreas Gruenbacher static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
38639f60c1cSChristian Brauner 					struct mnt_idmap *idmap,
38759301226SAl Viro 					struct dentry *unused, struct inode *inode,
3889172abbcSAndreas Gruenbacher 					const char *name, const void *value,
3899172abbcSAndreas Gruenbacher 					size_t size, int flags)
3909172abbcSAndreas Gruenbacher {
391f22125e5SAnand Jain 	int ret;
392b3f6a4beSAnand Jain 	struct btrfs_trans_handle *trans;
393b3f6a4beSAnand Jain 	struct btrfs_root *root = BTRFS_I(inode)->root;
394f22125e5SAnand Jain 
3959172abbcSAndreas Gruenbacher 	name = xattr_full_name(handler, name);
3960e852ab8SChung-Chiang Cheng 	ret = btrfs_validate_prop(BTRFS_I(inode), name, value, size);
397f22125e5SAnand Jain 	if (ret)
398f22125e5SAnand Jain 		return ret;
399b3f6a4beSAnand Jain 
4004b73c55fSFilipe Manana 	if (btrfs_ignore_prop(BTRFS_I(inode), name))
4014b73c55fSFilipe Manana 		return 0;
4024b73c55fSFilipe Manana 
403b3f6a4beSAnand Jain 	trans = btrfs_start_transaction(root, 2);
404b3f6a4beSAnand Jain 	if (IS_ERR(trans))
405b3f6a4beSAnand Jain 		return PTR_ERR(trans);
406b3f6a4beSAnand Jain 
407b3f6a4beSAnand Jain 	ret = btrfs_set_prop(trans, inode, name, value, size, flags);
408b3f6a4beSAnand Jain 	if (!ret) {
409b3f6a4beSAnand Jain 		inode_inc_iversion(inode);
4102a9462deSJeff Layton 		inode_set_ctime_current(inode);
4119a56fcd1SNikolay Borisov 		ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
412193b4e83SFilipe Manana 		if (ret)
413193b4e83SFilipe Manana 			btrfs_abort_transaction(trans, ret);
414b3f6a4beSAnand Jain 	}
415b3f6a4beSAnand Jain 
416b3f6a4beSAnand Jain 	btrfs_end_transaction(trans);
417b3f6a4beSAnand Jain 
418b3f6a4beSAnand Jain 	return ret;
4199172abbcSAndreas Gruenbacher }
4209172abbcSAndreas Gruenbacher 
4219172abbcSAndreas Gruenbacher static const struct xattr_handler btrfs_security_xattr_handler = {
4229172abbcSAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
4239172abbcSAndreas Gruenbacher 	.get = btrfs_xattr_handler_get,
4249172abbcSAndreas Gruenbacher 	.set = btrfs_xattr_handler_set,
4259172abbcSAndreas Gruenbacher };
4269172abbcSAndreas Gruenbacher 
4279172abbcSAndreas Gruenbacher static const struct xattr_handler btrfs_trusted_xattr_handler = {
4289172abbcSAndreas Gruenbacher 	.prefix = XATTR_TRUSTED_PREFIX,
4299172abbcSAndreas Gruenbacher 	.get = btrfs_xattr_handler_get,
4309172abbcSAndreas Gruenbacher 	.set = btrfs_xattr_handler_set,
4319172abbcSAndreas Gruenbacher };
4329172abbcSAndreas Gruenbacher 
4339172abbcSAndreas Gruenbacher static const struct xattr_handler btrfs_user_xattr_handler = {
4349172abbcSAndreas Gruenbacher 	.prefix = XATTR_USER_PREFIX,
4359172abbcSAndreas Gruenbacher 	.get = btrfs_xattr_handler_get,
4369172abbcSAndreas Gruenbacher 	.set = btrfs_xattr_handler_set,
4379172abbcSAndreas Gruenbacher };
4389172abbcSAndreas Gruenbacher 
4399172abbcSAndreas Gruenbacher static const struct xattr_handler btrfs_btrfs_xattr_handler = {
4409172abbcSAndreas Gruenbacher 	.prefix = XATTR_BTRFS_PREFIX,
4419172abbcSAndreas Gruenbacher 	.get = btrfs_xattr_handler_get,
4429172abbcSAndreas Gruenbacher 	.set = btrfs_xattr_handler_set_prop,
4439172abbcSAndreas Gruenbacher };
4449172abbcSAndreas Gruenbacher 
445f01cbd3fSStephen Hemminger const struct xattr_handler *btrfs_xattr_handlers[] = {
4469172abbcSAndreas Gruenbacher 	&btrfs_security_xattr_handler,
4479172abbcSAndreas Gruenbacher 	&btrfs_trusted_xattr_handler,
4489172abbcSAndreas Gruenbacher 	&btrfs_user_xattr_handler,
4499172abbcSAndreas Gruenbacher 	&btrfs_btrfs_xattr_handler,
45095819c05SChristoph Hellwig 	NULL,
45195819c05SChristoph Hellwig };
45295819c05SChristoph Hellwig 
btrfs_initxattrs(struct inode * inode,const struct xattr * xattr_array,void * fs_private)45348a3b636SEric Sandeen static int btrfs_initxattrs(struct inode *inode,
454419a6f30SAnand Jain 			    const struct xattr *xattr_array, void *fs_private)
4559d8f13baSMimi Zohar {
456419a6f30SAnand Jain 	struct btrfs_trans_handle *trans = fs_private;
4579d8f13baSMimi Zohar 	const struct xattr *xattr;
458827aa18eSFilipe Manana 	unsigned int nofs_flag;
4599d8f13baSMimi Zohar 	char *name;
4609d8f13baSMimi Zohar 	int err = 0;
4619d8f13baSMimi Zohar 
462827aa18eSFilipe Manana 	/*
463827aa18eSFilipe Manana 	 * We're holding a transaction handle, so use a NOFS memory allocation
464827aa18eSFilipe Manana 	 * context to avoid deadlock if reclaim happens.
465827aa18eSFilipe Manana 	 */
466827aa18eSFilipe Manana 	nofs_flag = memalloc_nofs_save();
4679d8f13baSMimi Zohar 	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
4689d8f13baSMimi Zohar 		name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
46939a27ec1SDavid Sterba 			       strlen(xattr->name) + 1, GFP_KERNEL);
4709d8f13baSMimi Zohar 		if (!name) {
4719d8f13baSMimi Zohar 			err = -ENOMEM;
4729d8f13baSMimi Zohar 			break;
4739d8f13baSMimi Zohar 		}
4749d8f13baSMimi Zohar 		strcpy(name, XATTR_SECURITY_PREFIX);
4759d8f13baSMimi Zohar 		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
47604e6863bSAnand Jain 		err = btrfs_setxattr(trans, inode, name, xattr->value,
4777852781dSDavid Sterba 				     xattr->value_len, 0);
4789d8f13baSMimi Zohar 		kfree(name);
4799d8f13baSMimi Zohar 		if (err < 0)
4809d8f13baSMimi Zohar 			break;
4819d8f13baSMimi Zohar 	}
482827aa18eSFilipe Manana 	memalloc_nofs_restore(nofs_flag);
4839d8f13baSMimi Zohar 	return err;
4849d8f13baSMimi Zohar }
4859d8f13baSMimi Zohar 
btrfs_xattr_security_init(struct btrfs_trans_handle * trans,struct inode * inode,struct inode * dir,const struct qstr * qstr)486f34f57a3SYan, Zheng int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
4872a7dba39SEric Paris 			      struct inode *inode, struct inode *dir,
4882a7dba39SEric Paris 			      const struct qstr *qstr)
4890279b4cdSJim Owens {
4909d8f13baSMimi Zohar 	return security_inode_init_security(inode, dir, qstr,
4919d8f13baSMimi Zohar 					    &btrfs_initxattrs, trans);
4920279b4cdSJim Owens }
493