xref: /openbmc/linux/fs/btrfs/xattr.c (revision 3acd7ee8)
15103e947SJosef Bacik /*
25103e947SJosef Bacik  * Copyright (C) 2007 Red Hat.  All rights reserved.
35103e947SJosef Bacik  *
45103e947SJosef Bacik  * This program is free software; you can redistribute it and/or
55103e947SJosef Bacik  * modify it under the terms of the GNU General Public
65103e947SJosef Bacik  * License v2 as published by the Free Software Foundation.
75103e947SJosef Bacik  *
85103e947SJosef Bacik  * This program is distributed in the hope that it will be useful,
95103e947SJosef Bacik  * but WITHOUT ANY WARRANTY; without even the implied warranty of
105103e947SJosef Bacik  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
115103e947SJosef Bacik  * General Public License for more details.
125103e947SJosef Bacik  *
135103e947SJosef Bacik  * You should have received a copy of the GNU General Public
145103e947SJosef Bacik  * License along with this program; if not, write to the
155103e947SJosef Bacik  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
165103e947SJosef Bacik  * Boston, MA 021110-1307, USA.
175103e947SJosef Bacik  */
185103e947SJosef Bacik 
195103e947SJosef Bacik #include <linux/init.h>
205103e947SJosef Bacik #include <linux/fs.h>
215103e947SJosef Bacik #include <linux/slab.h>
225103e947SJosef Bacik #include <linux/rwsem.h>
235103e947SJosef Bacik #include <linux/xattr.h>
245103e947SJosef Bacik #include "ctree.h"
255103e947SJosef Bacik #include "btrfs_inode.h"
265103e947SJosef Bacik #include "transaction.h"
275103e947SJosef Bacik #include "xattr.h"
285103e947SJosef Bacik #include "disk-io.h"
295103e947SJosef Bacik 
305103e947SJosef Bacik static struct xattr_handler *btrfs_xattr_handler_map[] = {
315103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_USER]		= &btrfs_xattr_user_handler,
325103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS]	= &btrfs_xattr_acl_access_handler,
335103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT]	= &btrfs_xattr_acl_default_handler,
345103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_TRUSTED]		= &btrfs_xattr_trusted_handler,
355103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_SECURITY]		= &btrfs_xattr_security_handler,
365103e947SJosef Bacik 	[BTRFS_XATTR_INDEX_SYSTEM]		= &btrfs_xattr_system_handler,
375103e947SJosef Bacik };
385103e947SJosef Bacik 
395103e947SJosef Bacik struct xattr_handler *btrfs_xattr_handlers[] = {
405103e947SJosef Bacik 	&btrfs_xattr_user_handler,
415103e947SJosef Bacik 	&btrfs_xattr_acl_access_handler,
425103e947SJosef Bacik 	&btrfs_xattr_acl_default_handler,
435103e947SJosef Bacik 	&btrfs_xattr_trusted_handler,
445103e947SJosef Bacik 	&btrfs_xattr_security_handler,
455103e947SJosef Bacik 	&btrfs_xattr_system_handler,
465103e947SJosef Bacik 	NULL,
475103e947SJosef Bacik };
485103e947SJosef Bacik 
495103e947SJosef Bacik /*
505103e947SJosef Bacik  * @param name - the xattr name
515103e947SJosef Bacik  * @return - the xattr_handler for the xattr, NULL if its not found
525103e947SJosef Bacik  *
535103e947SJosef Bacik  * use this with listxattr where we don't already know the type of xattr we
545103e947SJosef Bacik  * have
555103e947SJosef Bacik  */
565103e947SJosef Bacik static struct xattr_handler *find_btrfs_xattr_handler(struct extent_buffer *l,
575103e947SJosef Bacik 						      unsigned long name_ptr,
585103e947SJosef Bacik 						      u16 name_len)
595103e947SJosef Bacik {
605103e947SJosef Bacik 	struct xattr_handler *handler = NULL;
615103e947SJosef Bacik 	int i = 0;
625103e947SJosef Bacik 
635103e947SJosef Bacik 	for (handler = btrfs_xattr_handlers[i]; handler != NULL; i++,
645103e947SJosef Bacik 	     handler = btrfs_xattr_handlers[i]) {
655103e947SJosef Bacik 		u16 prefix_len = strlen(handler->prefix);
665103e947SJosef Bacik 
675103e947SJosef Bacik 		if (name_len < prefix_len)
685103e947SJosef Bacik 			continue;
695103e947SJosef Bacik 
705103e947SJosef Bacik 		if (memcmp_extent_buffer(l, handler->prefix, name_ptr,
715103e947SJosef Bacik 					 prefix_len) == 0)
725103e947SJosef Bacik 			break;
735103e947SJosef Bacik 	}
745103e947SJosef Bacik 
755103e947SJosef Bacik 	return handler;
765103e947SJosef Bacik }
775103e947SJosef Bacik 
785103e947SJosef Bacik /*
795103e947SJosef Bacik  * @param name_index - the index for the xattr handler
805103e947SJosef Bacik  * @return the xattr_handler if we found it, NULL otherwise
815103e947SJosef Bacik  *
825103e947SJosef Bacik  * use this if we know the type of the xattr already
835103e947SJosef Bacik  */
845103e947SJosef Bacik static struct xattr_handler *btrfs_xattr_handler(int name_index)
855103e947SJosef Bacik {
865103e947SJosef Bacik 	struct xattr_handler *handler = NULL;
875103e947SJosef Bacik 
885103e947SJosef Bacik 	if (name_index >= 0 &&
895103e947SJosef Bacik 	    name_index < ARRAY_SIZE(btrfs_xattr_handler_map))
905103e947SJosef Bacik 		handler = btrfs_xattr_handler_map[name_index];
915103e947SJosef Bacik 
925103e947SJosef Bacik 	return handler;
935103e947SJosef Bacik }
945103e947SJosef Bacik 
955103e947SJosef Bacik static inline char *get_name(const char *name, int name_index)
965103e947SJosef Bacik {
975103e947SJosef Bacik 	char *ret = NULL;
985103e947SJosef Bacik 	struct xattr_handler *handler = btrfs_xattr_handler(name_index);
995103e947SJosef Bacik 	int prefix_len;
1005103e947SJosef Bacik 
1015103e947SJosef Bacik 	if (!handler)
1025103e947SJosef Bacik 		return ret;
1035103e947SJosef Bacik 
1045103e947SJosef Bacik 	prefix_len = strlen(handler->prefix);
1055103e947SJosef Bacik 
1065103e947SJosef Bacik 	ret = kmalloc(strlen(name) + prefix_len + 1, GFP_KERNEL);
1075103e947SJosef Bacik 	if (!ret)
1085103e947SJosef Bacik 		return ret;
1095103e947SJosef Bacik 
1105103e947SJosef Bacik 	memcpy(ret, handler->prefix, prefix_len);
1115103e947SJosef Bacik 	memcpy(ret+prefix_len, name, strlen(name));
1125103e947SJosef Bacik 	ret[prefix_len + strlen(name)] = '\0';
1135103e947SJosef Bacik 
1145103e947SJosef Bacik 	return ret;
1155103e947SJosef Bacik }
1165103e947SJosef Bacik 
1175103e947SJosef Bacik size_t btrfs_xattr_generic_list(struct inode *inode, char *list,
1185103e947SJosef Bacik 				size_t list_size, const char *name,
1195103e947SJosef Bacik 				size_t name_len)
1205103e947SJosef Bacik {
1215103e947SJosef Bacik 	if (list && (name_len+1) <= list_size) {
1225103e947SJosef Bacik 		memcpy(list, name, name_len);
1235103e947SJosef Bacik 		list[name_len] = '\0';
1245103e947SJosef Bacik 	} else
1255103e947SJosef Bacik 		return -ERANGE;
1265103e947SJosef Bacik 
1275103e947SJosef Bacik 	return name_len+1;
1285103e947SJosef Bacik }
1295103e947SJosef Bacik 
1305103e947SJosef Bacik ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
1315103e947SJosef Bacik 			const char *attr_name, void *buffer, size_t size)
1325103e947SJosef Bacik {
1335103e947SJosef Bacik 	struct btrfs_dir_item *di;
1345103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
1355103e947SJosef Bacik 	struct btrfs_path *path;
1365103e947SJosef Bacik 	struct extent_buffer *leaf;
1375103e947SJosef Bacik 	struct xattr_handler *handler = btrfs_xattr_handler(name_index);
1385103e947SJosef Bacik 	int ret = 0;
1395103e947SJosef Bacik 	unsigned long data_ptr;
1405103e947SJosef Bacik 	char *name;
1415103e947SJosef Bacik 
1425103e947SJosef Bacik 	if (!handler)
1435103e947SJosef Bacik 		return -EOPNOTSUPP;
1445103e947SJosef Bacik 
1455103e947SJosef Bacik 	/* just in case... */
1465103e947SJosef Bacik 	if (*attr_name == '\0')
1475103e947SJosef Bacik 		return -EINVAL;
1485103e947SJosef Bacik 
1495103e947SJosef Bacik 	name = get_name(attr_name, name_index);
1505103e947SJosef Bacik 	if (!name)
1515103e947SJosef Bacik 		return -ENOMEM;
1525103e947SJosef Bacik 
1535103e947SJosef Bacik 	path = btrfs_alloc_path();
1545103e947SJosef Bacik 	if (!path) {
1555103e947SJosef Bacik 		kfree(name);
1565103e947SJosef Bacik 		return -ENOMEM;
1575103e947SJosef Bacik 	}
1585103e947SJosef Bacik 
1595103e947SJosef Bacik 	mutex_lock(&root->fs_info->fs_mutex);
1605103e947SJosef Bacik 	/* lookup the xattr by name */
1615103e947SJosef Bacik 	di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
1625103e947SJosef Bacik 				strlen(name), 0);
1635103e947SJosef Bacik 	if (!di || IS_ERR(di)) {
1645103e947SJosef Bacik 		ret = -ENODATA;
1655103e947SJosef Bacik 		goto out;
1665103e947SJosef Bacik 	}
1675103e947SJosef Bacik 
1685103e947SJosef Bacik 	leaf = path->nodes[0];
1695103e947SJosef Bacik 	/* if size is 0, that means we want the size of the attr */
1705103e947SJosef Bacik 	if (!size) {
1715103e947SJosef Bacik 		ret = btrfs_dir_data_len(leaf, di);
1725103e947SJosef Bacik 		goto out;
1735103e947SJosef Bacik 	}
1745103e947SJosef Bacik 
1755103e947SJosef Bacik 	/* now get the data out of our dir_item */
1765103e947SJosef Bacik 	if (btrfs_dir_data_len(leaf, di) > size) {
1775103e947SJosef Bacik 		ret = -ERANGE;
1785103e947SJosef Bacik 		goto out;
1795103e947SJosef Bacik 	}
1805103e947SJosef Bacik 	data_ptr = (unsigned long)((char *)(di + 1) +
1815103e947SJosef Bacik 				   btrfs_dir_name_len(leaf, di));
1825103e947SJosef Bacik 	read_extent_buffer(leaf, buffer, data_ptr,
1833acd7ee8SJosef Bacik 			   btrfs_dir_data_len(leaf, di));
1845103e947SJosef Bacik 	ret = btrfs_dir_data_len(leaf, di);
1855103e947SJosef Bacik 
1865103e947SJosef Bacik out:
1875103e947SJosef Bacik 	mutex_unlock(&root->fs_info->fs_mutex);
1885103e947SJosef Bacik 	kfree(name);
1895103e947SJosef Bacik 	btrfs_free_path(path);
1905103e947SJosef Bacik 	return ret;
1915103e947SJosef Bacik }
1925103e947SJosef Bacik 
1935103e947SJosef Bacik int btrfs_xattr_set(struct inode *inode, int name_index,
1945103e947SJosef Bacik 		    const char *attr_name, const void *value, size_t size,
1955103e947SJosef Bacik 		    int flags)
1965103e947SJosef Bacik {
1975103e947SJosef Bacik 	struct btrfs_dir_item *di;
1985103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
1995103e947SJosef Bacik 	struct btrfs_trans_handle *trans;
2005103e947SJosef Bacik 	struct btrfs_path *path;
2015103e947SJosef Bacik 	struct xattr_handler *handler = btrfs_xattr_handler(name_index);
2025103e947SJosef Bacik 	char *name;
2035103e947SJosef Bacik 	int ret = 0, mod = 0;
2045103e947SJosef Bacik 
2055103e947SJosef Bacik 	if (!handler)
2065103e947SJosef Bacik 		return -EOPNOTSUPP;
2075103e947SJosef Bacik 
2085103e947SJosef Bacik 	/* just in case... */
2095103e947SJosef Bacik 	if (*attr_name == '\0')
2105103e947SJosef Bacik 		return -EINVAL;
2115103e947SJosef Bacik 
2125103e947SJosef Bacik 	name = get_name(attr_name, name_index);
2135103e947SJosef Bacik 	if (!name)
2145103e947SJosef Bacik 		return -ENOMEM;
2155103e947SJosef Bacik 
2165103e947SJosef Bacik 	path = btrfs_alloc_path();
2175103e947SJosef Bacik 	if (!path) {
2185103e947SJosef Bacik 		kfree(name);
2195103e947SJosef Bacik 		return -ENOMEM;
2205103e947SJosef Bacik 	}
2215103e947SJosef Bacik 
2225103e947SJosef Bacik 	mutex_lock(&root->fs_info->fs_mutex);
2235103e947SJosef Bacik 	trans = btrfs_start_transaction(root, 1);
2245103e947SJosef Bacik 	btrfs_set_trans_block_group(trans, inode);
2255103e947SJosef Bacik 
2265103e947SJosef Bacik 	/* first lets see if we already have this xattr */
2275103e947SJosef Bacik 	di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
2285103e947SJosef Bacik 				strlen(name), -1);
2295103e947SJosef Bacik 	if (IS_ERR(di)) {
2305103e947SJosef Bacik 		ret = PTR_ERR(di);
2315103e947SJosef Bacik 		goto out;
2325103e947SJosef Bacik 	}
2335103e947SJosef Bacik 
2345103e947SJosef Bacik 	/* ok we already have this xattr, lets remove it */
2355103e947SJosef Bacik 	if (di) {
2365103e947SJosef Bacik 		/* if we want create only exit */
2375103e947SJosef Bacik 		if (flags & XATTR_CREATE) {
2385103e947SJosef Bacik 			ret = -EEXIST;
2395103e947SJosef Bacik 			goto out;
2405103e947SJosef Bacik 		}
2415103e947SJosef Bacik 
2425103e947SJosef Bacik 		ret = btrfs_delete_one_dir_name(trans, root, path, di);
2435103e947SJosef Bacik 		if (ret)
2445103e947SJosef Bacik 			goto out;
2455103e947SJosef Bacik 		btrfs_release_path(root, path);
2465103e947SJosef Bacik 
2475103e947SJosef Bacik 		/* if we don't have a value then we are removing the xattr */
2485103e947SJosef Bacik 		if (!value) {
2495103e947SJosef Bacik 			mod = 1;
2505103e947SJosef Bacik 			goto out;
2515103e947SJosef Bacik 		}
2525103e947SJosef Bacik 	} else if (flags & XATTR_REPLACE) {
2535103e947SJosef Bacik 		/* we couldn't find the attr to replace, so error out */
2545103e947SJosef Bacik 		ret = -ENODATA;
2555103e947SJosef Bacik 		goto out;
2565103e947SJosef Bacik 	}
2575103e947SJosef Bacik 
2585103e947SJosef Bacik 	/* ok we have to create a completely new xattr */
2595103e947SJosef Bacik 	ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
2605103e947SJosef Bacik 				      value, size, inode->i_ino);
2615103e947SJosef Bacik 	if (ret)
2625103e947SJosef Bacik 		goto out;
2635103e947SJosef Bacik 	mod = 1;
2645103e947SJosef Bacik 
2655103e947SJosef Bacik out:
2665103e947SJosef Bacik 	if (mod) {
2675103e947SJosef Bacik 		inode->i_ctime = CURRENT_TIME;
2685103e947SJosef Bacik 		ret = btrfs_update_inode(trans, root, inode);
2695103e947SJosef Bacik 	}
2705103e947SJosef Bacik 
2715103e947SJosef Bacik 	btrfs_end_transaction(trans, root);
2725103e947SJosef Bacik 	mutex_unlock(&root->fs_info->fs_mutex);
2735103e947SJosef Bacik 	kfree(name);
2745103e947SJosef Bacik 	btrfs_free_path(path);
2755103e947SJosef Bacik 
2765103e947SJosef Bacik 	return ret;
2775103e947SJosef Bacik }
2785103e947SJosef Bacik 
2795103e947SJosef Bacik ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
2805103e947SJosef Bacik {
2815103e947SJosef Bacik 	struct btrfs_key key, found_key;
2825103e947SJosef Bacik 	struct inode *inode = dentry->d_inode;
2835103e947SJosef Bacik 	struct btrfs_root *root = BTRFS_I(inode)->root;
2845103e947SJosef Bacik 	struct btrfs_path *path;
2855103e947SJosef Bacik 	struct btrfs_item *item;
2865103e947SJosef Bacik 	struct extent_buffer *leaf;
2875103e947SJosef Bacik 	struct btrfs_dir_item *di;
2885103e947SJosef Bacik 	struct xattr_handler *handler;
2895103e947SJosef Bacik 	int ret = 0, slot, advance;
2905103e947SJosef Bacik 	size_t total_size = 0, size_left = size, written;
2915103e947SJosef Bacik 	unsigned long name_ptr;
2925103e947SJosef Bacik 	char *name;
2935103e947SJosef Bacik 	u32 nritems;
2945103e947SJosef Bacik 
2955103e947SJosef Bacik 	/*
2965103e947SJosef Bacik 	 * ok we want all objects associated with this id.
2975103e947SJosef Bacik 	 * NOTE: we set key.offset = 0; because we want to start with the
2985103e947SJosef Bacik 	 * first xattr that we find and walk forward
2995103e947SJosef Bacik 	 */
3005103e947SJosef Bacik 	key.objectid = inode->i_ino;
3015103e947SJosef Bacik 	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
3025103e947SJosef Bacik 	key.offset = 0;
3035103e947SJosef Bacik 
3045103e947SJosef Bacik 	path = btrfs_alloc_path();
3055103e947SJosef Bacik 	if (!path)
3065103e947SJosef Bacik 		return -ENOMEM;
3071caf9342SJosef Bacik 	path->reada = 2;
3085103e947SJosef Bacik 
3095103e947SJosef Bacik 	mutex_lock(&root->fs_info->fs_mutex);
3105103e947SJosef Bacik 
3115103e947SJosef Bacik 	/* search for our xattrs */
3125103e947SJosef Bacik 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
3135103e947SJosef Bacik 	if (ret < 0)
3145103e947SJosef Bacik 		goto err;
3155103e947SJosef Bacik 	ret = 0;
3165103e947SJosef Bacik 	advance = 0;
3175103e947SJosef Bacik 	while (1) {
3185103e947SJosef Bacik 		leaf = path->nodes[0];
3195103e947SJosef Bacik 		nritems = btrfs_header_nritems(leaf);
3205103e947SJosef Bacik 		slot = path->slots[0];
3215103e947SJosef Bacik 
3225103e947SJosef Bacik 		/* this is where we start walking through the path */
3235103e947SJosef Bacik 		if (advance || slot >= nritems) {
3245103e947SJosef Bacik 			/*
3255103e947SJosef Bacik 			 * if we've reached the last slot in this leaf we need
3265103e947SJosef Bacik 			 * to go to the next leaf and reset everything
3275103e947SJosef Bacik 			 */
3285103e947SJosef Bacik 			if (slot >= nritems-1) {
3295103e947SJosef Bacik 				ret = btrfs_next_leaf(root, path);
3305103e947SJosef Bacik 				if (ret)
3315103e947SJosef Bacik 					break;
3325103e947SJosef Bacik 				leaf = path->nodes[0];
3335103e947SJosef Bacik 				nritems = btrfs_header_nritems(leaf);
3345103e947SJosef Bacik 				slot = path->slots[0];
3355103e947SJosef Bacik 			} else {
3365103e947SJosef Bacik 				/*
3375103e947SJosef Bacik 				 * just walking through the slots on this leaf
3385103e947SJosef Bacik 				 */
3395103e947SJosef Bacik 				slot++;
3405103e947SJosef Bacik 				path->slots[0]++;
3415103e947SJosef Bacik 			}
3425103e947SJosef Bacik 		}
3435103e947SJosef Bacik 		advance = 1;
3445103e947SJosef Bacik 
3455103e947SJosef Bacik 		item = btrfs_item_nr(leaf, slot);
3465103e947SJosef Bacik 		btrfs_item_key_to_cpu(leaf, &found_key, slot);
3475103e947SJosef Bacik 
3485103e947SJosef Bacik 		/* check to make sure this item is what we want */
3495103e947SJosef Bacik 		if (found_key.objectid != key.objectid)
3505103e947SJosef Bacik 			break;
3515103e947SJosef Bacik 		if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
3525103e947SJosef Bacik 			break;
3535103e947SJosef Bacik 
3545103e947SJosef Bacik 		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
3555103e947SJosef Bacik 
3565103e947SJosef Bacik 		total_size += btrfs_dir_name_len(leaf, di)+1;
3575103e947SJosef Bacik 
3585103e947SJosef Bacik 		/* we are just looking for how big our buffer needs to be */
3595103e947SJosef Bacik 		if (!size)
3605103e947SJosef Bacik 			continue;
3615103e947SJosef Bacik 
3625103e947SJosef Bacik 		/* find our handler for this xattr */
3635103e947SJosef Bacik 		name_ptr = (unsigned long)(di + 1);
3645103e947SJosef Bacik 		handler = find_btrfs_xattr_handler(leaf, name_ptr,
3655103e947SJosef Bacik 						   btrfs_dir_name_len(leaf, di));
3665103e947SJosef Bacik 		if (!handler) {
3675103e947SJosef Bacik 			printk(KERN_ERR "btrfs: unsupported xattr found\n");
3685103e947SJosef Bacik 			continue;
3695103e947SJosef Bacik 		}
3705103e947SJosef Bacik 
3715103e947SJosef Bacik 		name = kmalloc(btrfs_dir_name_len(leaf, di), GFP_KERNEL);
3725103e947SJosef Bacik 		read_extent_buffer(leaf, name, name_ptr,
3735103e947SJosef Bacik 				   btrfs_dir_name_len(leaf, di));
3745103e947SJosef Bacik 
3755103e947SJosef Bacik 		/* call the list function associated with this xattr */
3765103e947SJosef Bacik 		written = handler->list(inode, buffer, size_left, name,
3775103e947SJosef Bacik 					btrfs_dir_name_len(leaf, di));
3785103e947SJosef Bacik 		kfree(name);
3795103e947SJosef Bacik 
3805103e947SJosef Bacik 		if (written < 0) {
3815103e947SJosef Bacik 			ret = -ERANGE;
3825103e947SJosef Bacik 			break;
3835103e947SJosef Bacik 		}
3845103e947SJosef Bacik 
3855103e947SJosef Bacik 		size_left -= written;
3865103e947SJosef Bacik 		buffer += written;
3875103e947SJosef Bacik 	}
3885103e947SJosef Bacik 	ret = total_size;
3895103e947SJosef Bacik 
3905103e947SJosef Bacik err:
3915103e947SJosef Bacik 	mutex_unlock(&root->fs_info->fs_mutex);
3925103e947SJosef Bacik 	btrfs_free_path(path);
3935103e947SJosef Bacik 
3945103e947SJosef Bacik 	return ret;
3955103e947SJosef Bacik }
3965103e947SJosef Bacik 
3975103e947SJosef Bacik /*
3985103e947SJosef Bacik  * delete all the xattrs associated with the inode.  fs_mutex should be
3995103e947SJosef Bacik  * held when we come into here
4005103e947SJosef Bacik  */
4015103e947SJosef Bacik int btrfs_delete_xattrs(struct btrfs_trans_handle *trans,
4025103e947SJosef Bacik 			struct btrfs_root *root, struct inode *inode)
4035103e947SJosef Bacik {
4045103e947SJosef Bacik 	struct btrfs_path *path;
4055103e947SJosef Bacik 	struct btrfs_key key, found_key;
4065103e947SJosef Bacik 	struct btrfs_item *item;
4075103e947SJosef Bacik 	struct extent_buffer *leaf;
4085103e947SJosef Bacik 	int ret;
4095103e947SJosef Bacik 
4105103e947SJosef Bacik 	path = btrfs_alloc_path();
4115103e947SJosef Bacik 	if (!path)
4125103e947SJosef Bacik 		return -ENOMEM;
4131caf9342SJosef Bacik 	path->reada = -1;
4145103e947SJosef Bacik 	key.objectid = inode->i_ino;
4155103e947SJosef Bacik 	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
4165103e947SJosef Bacik 	key.offset = (u64)-1;
4175103e947SJosef Bacik 
4185103e947SJosef Bacik 	while(1) {
4195103e947SJosef Bacik 		/* look for our next xattr */
4205103e947SJosef Bacik 		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
4215103e947SJosef Bacik 		if (ret < 0)
4225103e947SJosef Bacik 			goto out;
4235103e947SJosef Bacik 		BUG_ON(ret == 0);
4245103e947SJosef Bacik 
4255103e947SJosef Bacik 		if (path->slots[0] == 0)
4265103e947SJosef Bacik 			break;
4275103e947SJosef Bacik 
4285103e947SJosef Bacik 		path->slots[0]--;
4295103e947SJosef Bacik 		leaf = path->nodes[0];
4305103e947SJosef Bacik 		item = btrfs_item_nr(leaf, path->slots[0]);
4315103e947SJosef Bacik 		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
4325103e947SJosef Bacik 
4335103e947SJosef Bacik 		if (found_key.objectid != key.objectid)
4345103e947SJosef Bacik 			break;
4355103e947SJosef Bacik 		if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
4365103e947SJosef Bacik 			break;
4375103e947SJosef Bacik 
4385103e947SJosef Bacik 		ret = btrfs_del_item(trans, root, path);
4395103e947SJosef Bacik 		BUG_ON(ret);
4405103e947SJosef Bacik 		btrfs_release_path(root, path);
4415103e947SJosef Bacik 	}
4425103e947SJosef Bacik 	ret = 0;
4435103e947SJosef Bacik out:
4445103e947SJosef Bacik 	btrfs_free_path(path);
4455103e947SJosef Bacik 
4465103e947SJosef Bacik 	return ret;
4475103e947SJosef Bacik }
4485103e947SJosef Bacik 
4495103e947SJosef Bacik /*
4505103e947SJosef Bacik  * Handler functions
4515103e947SJosef Bacik  */
4525103e947SJosef Bacik #define BTRFS_XATTR_SETGET_FUNCS(name, index)				\
4535103e947SJosef Bacik static int btrfs_xattr_##name##_get(struct inode *inode,		\
4545103e947SJosef Bacik 				    const char *name, void *value,	\
4555103e947SJosef Bacik 				    size_t size)			\
4565103e947SJosef Bacik {									\
4575103e947SJosef Bacik 	return btrfs_xattr_get(inode, index, name, value, size);	\
4585103e947SJosef Bacik }									\
4595103e947SJosef Bacik static int btrfs_xattr_##name##_set(struct inode *inode,		\
4605103e947SJosef Bacik 				    const char *name, const void *value,\
4615103e947SJosef Bacik 				    size_t size, int flags)		\
4625103e947SJosef Bacik {									\
4635103e947SJosef Bacik 	return btrfs_xattr_set(inode, index, name, value, size, flags);	\
4645103e947SJosef Bacik }									\
4655103e947SJosef Bacik 
4665103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY);
4675103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM);
4685103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER);
4695103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED);
4705103e947SJosef Bacik 
4715103e947SJosef Bacik struct xattr_handler btrfs_xattr_security_handler = {
4725103e947SJosef Bacik 	.prefix = XATTR_SECURITY_PREFIX,
4735103e947SJosef Bacik 	.list	= btrfs_xattr_generic_list,
4745103e947SJosef Bacik 	.get	= btrfs_xattr_security_get,
4755103e947SJosef Bacik 	.set	= btrfs_xattr_security_set,
4765103e947SJosef Bacik };
4775103e947SJosef Bacik 
4785103e947SJosef Bacik struct xattr_handler btrfs_xattr_system_handler = {
4795103e947SJosef Bacik 	.prefix = XATTR_SYSTEM_PREFIX,
4805103e947SJosef Bacik 	.list	= btrfs_xattr_generic_list,
4815103e947SJosef Bacik 	.get	= btrfs_xattr_system_get,
4825103e947SJosef Bacik 	.set	= btrfs_xattr_system_set,
4835103e947SJosef Bacik };
4845103e947SJosef Bacik 
4855103e947SJosef Bacik struct xattr_handler btrfs_xattr_user_handler = {
4865103e947SJosef Bacik 	.prefix	= XATTR_USER_PREFIX,
4875103e947SJosef Bacik 	.list	= btrfs_xattr_generic_list,
4885103e947SJosef Bacik 	.get	= btrfs_xattr_user_get,
4895103e947SJosef Bacik 	.set	= btrfs_xattr_user_set,
4905103e947SJosef Bacik };
4915103e947SJosef Bacik 
4925103e947SJosef Bacik struct xattr_handler btrfs_xattr_trusted_handler = {
4933acd7ee8SJosef Bacik 	.prefix = XATTR_TRUSTED_PREFIX,
4945103e947SJosef Bacik 	.list	= btrfs_xattr_generic_list,
4955103e947SJosef Bacik 	.get	= btrfs_xattr_trusted_get,
4965103e947SJosef Bacik 	.set	= btrfs_xattr_trusted_set,
4975103e947SJosef Bacik };
498