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 name = get_name(attr_name, name_index); 1455103e947SJosef Bacik if (!name) 1465103e947SJosef Bacik return -ENOMEM; 1475103e947SJosef Bacik 1485103e947SJosef Bacik path = btrfs_alloc_path(); 1495103e947SJosef Bacik if (!path) { 1505103e947SJosef Bacik kfree(name); 1515103e947SJosef Bacik return -ENOMEM; 1525103e947SJosef Bacik } 1535103e947SJosef Bacik 1545103e947SJosef Bacik mutex_lock(&root->fs_info->fs_mutex); 1555103e947SJosef Bacik /* lookup the xattr by name */ 1565103e947SJosef Bacik di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, 1575103e947SJosef Bacik strlen(name), 0); 1585103e947SJosef Bacik if (!di || IS_ERR(di)) { 1595103e947SJosef Bacik ret = -ENODATA; 1605103e947SJosef Bacik goto out; 1615103e947SJosef Bacik } 1625103e947SJosef Bacik 1635103e947SJosef Bacik leaf = path->nodes[0]; 1645103e947SJosef Bacik /* if size is 0, that means we want the size of the attr */ 1655103e947SJosef Bacik if (!size) { 1665103e947SJosef Bacik ret = btrfs_dir_data_len(leaf, di); 1675103e947SJosef Bacik goto out; 1685103e947SJosef Bacik } 1695103e947SJosef Bacik 1705103e947SJosef Bacik /* now get the data out of our dir_item */ 1715103e947SJosef Bacik if (btrfs_dir_data_len(leaf, di) > size) { 1725103e947SJosef Bacik ret = -ERANGE; 1735103e947SJosef Bacik goto out; 1745103e947SJosef Bacik } 1755103e947SJosef Bacik data_ptr = (unsigned long)((char *)(di + 1) + 1765103e947SJosef Bacik btrfs_dir_name_len(leaf, di)); 1775103e947SJosef Bacik read_extent_buffer(leaf, buffer, data_ptr, 1783acd7ee8SJosef Bacik btrfs_dir_data_len(leaf, di)); 1795103e947SJosef Bacik ret = btrfs_dir_data_len(leaf, di); 1805103e947SJosef Bacik 1815103e947SJosef Bacik out: 1825103e947SJosef Bacik mutex_unlock(&root->fs_info->fs_mutex); 1835103e947SJosef Bacik kfree(name); 1845103e947SJosef Bacik btrfs_free_path(path); 1855103e947SJosef Bacik return ret; 1865103e947SJosef Bacik } 1875103e947SJosef Bacik 1885103e947SJosef Bacik int btrfs_xattr_set(struct inode *inode, int name_index, 1895103e947SJosef Bacik const char *attr_name, const void *value, size_t size, 1905103e947SJosef Bacik int flags) 1915103e947SJosef Bacik { 1925103e947SJosef Bacik struct btrfs_dir_item *di; 1935103e947SJosef Bacik struct btrfs_root *root = BTRFS_I(inode)->root; 1945103e947SJosef Bacik struct btrfs_trans_handle *trans; 1955103e947SJosef Bacik struct btrfs_path *path; 1965103e947SJosef Bacik struct xattr_handler *handler = btrfs_xattr_handler(name_index); 1975103e947SJosef Bacik char *name; 1985103e947SJosef Bacik int ret = 0, mod = 0; 1995103e947SJosef Bacik if (!handler) 2005103e947SJosef Bacik return -EOPNOTSUPP; 2015103e947SJosef Bacik name = get_name(attr_name, name_index); 2025103e947SJosef Bacik if (!name) 2035103e947SJosef Bacik return -ENOMEM; 2045103e947SJosef Bacik 2055103e947SJosef Bacik path = btrfs_alloc_path(); 2065103e947SJosef Bacik if (!path) { 2075103e947SJosef Bacik kfree(name); 2085103e947SJosef Bacik return -ENOMEM; 2095103e947SJosef Bacik } 2105103e947SJosef Bacik 2115103e947SJosef Bacik mutex_lock(&root->fs_info->fs_mutex); 2125103e947SJosef Bacik trans = btrfs_start_transaction(root, 1); 2135103e947SJosef Bacik btrfs_set_trans_block_group(trans, inode); 2145103e947SJosef Bacik 2155103e947SJosef Bacik /* first lets see if we already have this xattr */ 2165103e947SJosef Bacik di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name, 2175103e947SJosef Bacik strlen(name), -1); 2185103e947SJosef Bacik if (IS_ERR(di)) { 2195103e947SJosef Bacik ret = PTR_ERR(di); 2205103e947SJosef Bacik goto out; 2215103e947SJosef Bacik } 2225103e947SJosef Bacik 2235103e947SJosef Bacik /* ok we already have this xattr, lets remove it */ 2245103e947SJosef Bacik if (di) { 2255103e947SJosef Bacik /* if we want create only exit */ 2265103e947SJosef Bacik if (flags & XATTR_CREATE) { 2275103e947SJosef Bacik ret = -EEXIST; 2285103e947SJosef Bacik goto out; 2295103e947SJosef Bacik } 2305103e947SJosef Bacik 2315103e947SJosef Bacik ret = btrfs_delete_one_dir_name(trans, root, path, di); 2325103e947SJosef Bacik if (ret) 2335103e947SJosef Bacik goto out; 2345103e947SJosef Bacik btrfs_release_path(root, path); 2355103e947SJosef Bacik 2365103e947SJosef Bacik /* if we don't have a value then we are removing the xattr */ 2375103e947SJosef Bacik if (!value) { 2385103e947SJosef Bacik mod = 1; 2395103e947SJosef Bacik goto out; 2405103e947SJosef Bacik } 2415103e947SJosef Bacik } else if (flags & XATTR_REPLACE) { 2425103e947SJosef Bacik /* we couldn't find the attr to replace, so error out */ 2435103e947SJosef Bacik ret = -ENODATA; 2445103e947SJosef Bacik goto out; 2455103e947SJosef Bacik } 2465103e947SJosef Bacik 2475103e947SJosef Bacik /* ok we have to create a completely new xattr */ 2485103e947SJosef Bacik ret = btrfs_insert_xattr_item(trans, root, name, strlen(name), 2495103e947SJosef Bacik value, size, inode->i_ino); 2505103e947SJosef Bacik if (ret) 2515103e947SJosef Bacik goto out; 2525103e947SJosef Bacik mod = 1; 2535103e947SJosef Bacik 2545103e947SJosef Bacik out: 2555103e947SJosef Bacik if (mod) { 2565103e947SJosef Bacik inode->i_ctime = CURRENT_TIME; 2575103e947SJosef Bacik ret = btrfs_update_inode(trans, root, inode); 2585103e947SJosef Bacik } 2595103e947SJosef Bacik 2605103e947SJosef Bacik btrfs_end_transaction(trans, root); 2615103e947SJosef Bacik mutex_unlock(&root->fs_info->fs_mutex); 2625103e947SJosef Bacik kfree(name); 2635103e947SJosef Bacik btrfs_free_path(path); 2645103e947SJosef Bacik 2655103e947SJosef Bacik return ret; 2665103e947SJosef Bacik } 2675103e947SJosef Bacik 2685103e947SJosef Bacik ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) 2695103e947SJosef Bacik { 2705103e947SJosef Bacik struct btrfs_key key, found_key; 2715103e947SJosef Bacik struct inode *inode = dentry->d_inode; 2725103e947SJosef Bacik struct btrfs_root *root = BTRFS_I(inode)->root; 2735103e947SJosef Bacik struct btrfs_path *path; 2745103e947SJosef Bacik struct btrfs_item *item; 2755103e947SJosef Bacik struct extent_buffer *leaf; 2765103e947SJosef Bacik struct btrfs_dir_item *di; 2775103e947SJosef Bacik struct xattr_handler *handler; 2785103e947SJosef Bacik int ret = 0, slot, advance; 2795103e947SJosef Bacik size_t total_size = 0, size_left = size, written; 2805103e947SJosef Bacik unsigned long name_ptr; 2815103e947SJosef Bacik char *name; 2825103e947SJosef Bacik u32 nritems; 2835103e947SJosef Bacik 2845103e947SJosef Bacik /* 2855103e947SJosef Bacik * ok we want all objects associated with this id. 2865103e947SJosef Bacik * NOTE: we set key.offset = 0; because we want to start with the 2875103e947SJosef Bacik * first xattr that we find and walk forward 2885103e947SJosef Bacik */ 2895103e947SJosef Bacik key.objectid = inode->i_ino; 2905103e947SJosef Bacik btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); 2915103e947SJosef Bacik key.offset = 0; 2925103e947SJosef Bacik 2935103e947SJosef Bacik path = btrfs_alloc_path(); 2945103e947SJosef Bacik if (!path) 2955103e947SJosef Bacik return -ENOMEM; 2961caf9342SJosef Bacik path->reada = 2; 2975103e947SJosef Bacik 2985103e947SJosef Bacik mutex_lock(&root->fs_info->fs_mutex); 2995103e947SJosef Bacik 3005103e947SJosef Bacik /* search for our xattrs */ 3015103e947SJosef Bacik ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 3025103e947SJosef Bacik if (ret < 0) 3035103e947SJosef Bacik goto err; 3045103e947SJosef Bacik ret = 0; 3055103e947SJosef Bacik advance = 0; 3065103e947SJosef Bacik while (1) { 3075103e947SJosef Bacik leaf = path->nodes[0]; 3085103e947SJosef Bacik nritems = btrfs_header_nritems(leaf); 3095103e947SJosef Bacik slot = path->slots[0]; 3105103e947SJosef Bacik 3115103e947SJosef Bacik /* this is where we start walking through the path */ 3125103e947SJosef Bacik if (advance || slot >= nritems) { 3135103e947SJosef Bacik /* 3145103e947SJosef Bacik * if we've reached the last slot in this leaf we need 3155103e947SJosef Bacik * to go to the next leaf and reset everything 3165103e947SJosef Bacik */ 3175103e947SJosef Bacik if (slot >= nritems-1) { 3185103e947SJosef Bacik ret = btrfs_next_leaf(root, path); 3195103e947SJosef Bacik if (ret) 3205103e947SJosef Bacik break; 3215103e947SJosef Bacik leaf = path->nodes[0]; 3225103e947SJosef Bacik nritems = btrfs_header_nritems(leaf); 3235103e947SJosef Bacik slot = path->slots[0]; 3245103e947SJosef Bacik } else { 3255103e947SJosef Bacik /* 3265103e947SJosef Bacik * just walking through the slots on this leaf 3275103e947SJosef Bacik */ 3285103e947SJosef Bacik slot++; 3295103e947SJosef Bacik path->slots[0]++; 3305103e947SJosef Bacik } 3315103e947SJosef Bacik } 3325103e947SJosef Bacik advance = 1; 3335103e947SJosef Bacik 3345103e947SJosef Bacik item = btrfs_item_nr(leaf, slot); 3355103e947SJosef Bacik btrfs_item_key_to_cpu(leaf, &found_key, slot); 3365103e947SJosef Bacik 3375103e947SJosef Bacik /* check to make sure this item is what we want */ 3385103e947SJosef Bacik if (found_key.objectid != key.objectid) 3395103e947SJosef Bacik break; 3405103e947SJosef Bacik if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY) 3415103e947SJosef Bacik break; 3425103e947SJosef Bacik 3435103e947SJosef Bacik di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 3445103e947SJosef Bacik 3455103e947SJosef Bacik total_size += btrfs_dir_name_len(leaf, di)+1; 3465103e947SJosef Bacik 3475103e947SJosef Bacik /* we are just looking for how big our buffer needs to be */ 3485103e947SJosef Bacik if (!size) 3495103e947SJosef Bacik continue; 3505103e947SJosef Bacik 3515103e947SJosef Bacik /* find our handler for this xattr */ 3525103e947SJosef Bacik name_ptr = (unsigned long)(di + 1); 3535103e947SJosef Bacik handler = find_btrfs_xattr_handler(leaf, name_ptr, 3545103e947SJosef Bacik btrfs_dir_name_len(leaf, di)); 3555103e947SJosef Bacik if (!handler) { 3565103e947SJosef Bacik printk(KERN_ERR "btrfs: unsupported xattr found\n"); 3575103e947SJosef Bacik continue; 3585103e947SJosef Bacik } 3595103e947SJosef Bacik 3605103e947SJosef Bacik name = kmalloc(btrfs_dir_name_len(leaf, di), GFP_KERNEL); 3615103e947SJosef Bacik read_extent_buffer(leaf, name, name_ptr, 3625103e947SJosef Bacik btrfs_dir_name_len(leaf, di)); 3635103e947SJosef Bacik 3645103e947SJosef Bacik /* call the list function associated with this xattr */ 3655103e947SJosef Bacik written = handler->list(inode, buffer, size_left, name, 3665103e947SJosef Bacik btrfs_dir_name_len(leaf, di)); 3675103e947SJosef Bacik kfree(name); 3685103e947SJosef Bacik 3695103e947SJosef Bacik if (written < 0) { 3705103e947SJosef Bacik ret = -ERANGE; 3715103e947SJosef Bacik break; 3725103e947SJosef Bacik } 3735103e947SJosef Bacik 3745103e947SJosef Bacik size_left -= written; 3755103e947SJosef Bacik buffer += written; 3765103e947SJosef Bacik } 3775103e947SJosef Bacik ret = total_size; 3785103e947SJosef Bacik 3795103e947SJosef Bacik err: 3805103e947SJosef Bacik mutex_unlock(&root->fs_info->fs_mutex); 3815103e947SJosef Bacik btrfs_free_path(path); 3825103e947SJosef Bacik 3835103e947SJosef Bacik return ret; 3845103e947SJosef Bacik } 3855103e947SJosef Bacik 3865103e947SJosef Bacik /* 3875103e947SJosef Bacik * delete all the xattrs associated with the inode. fs_mutex should be 3885103e947SJosef Bacik * held when we come into here 3895103e947SJosef Bacik */ 3905103e947SJosef Bacik int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, 3915103e947SJosef Bacik struct btrfs_root *root, struct inode *inode) 3925103e947SJosef Bacik { 3935103e947SJosef Bacik struct btrfs_path *path; 3945103e947SJosef Bacik struct btrfs_key key, found_key; 3955103e947SJosef Bacik struct btrfs_item *item; 3965103e947SJosef Bacik struct extent_buffer *leaf; 3975103e947SJosef Bacik int ret; 3985103e947SJosef Bacik 3995103e947SJosef Bacik path = btrfs_alloc_path(); 4005103e947SJosef Bacik if (!path) 4015103e947SJosef Bacik return -ENOMEM; 4021caf9342SJosef Bacik path->reada = -1; 4035103e947SJosef Bacik key.objectid = inode->i_ino; 4045103e947SJosef Bacik btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); 4055103e947SJosef Bacik key.offset = (u64)-1; 4065103e947SJosef Bacik 4075103e947SJosef Bacik while(1) { 4085103e947SJosef Bacik /* look for our next xattr */ 4095103e947SJosef Bacik ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 4105103e947SJosef Bacik if (ret < 0) 4115103e947SJosef Bacik goto out; 4125103e947SJosef Bacik BUG_ON(ret == 0); 4135103e947SJosef Bacik 4145103e947SJosef Bacik if (path->slots[0] == 0) 4155103e947SJosef Bacik break; 4165103e947SJosef Bacik 4175103e947SJosef Bacik path->slots[0]--; 4185103e947SJosef Bacik leaf = path->nodes[0]; 4195103e947SJosef Bacik item = btrfs_item_nr(leaf, path->slots[0]); 4205103e947SJosef Bacik btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 4215103e947SJosef Bacik 4225103e947SJosef Bacik if (found_key.objectid != key.objectid) 4235103e947SJosef Bacik break; 4245103e947SJosef Bacik if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY) 4255103e947SJosef Bacik break; 4265103e947SJosef Bacik 4275103e947SJosef Bacik ret = btrfs_del_item(trans, root, path); 4285103e947SJosef Bacik BUG_ON(ret); 4295103e947SJosef Bacik btrfs_release_path(root, path); 4305103e947SJosef Bacik } 4315103e947SJosef Bacik ret = 0; 4325103e947SJosef Bacik out: 4335103e947SJosef Bacik btrfs_free_path(path); 4345103e947SJosef Bacik 4355103e947SJosef Bacik return ret; 4365103e947SJosef Bacik } 4375103e947SJosef Bacik 4385103e947SJosef Bacik /* 4395103e947SJosef Bacik * Handler functions 4405103e947SJosef Bacik */ 4415103e947SJosef Bacik #define BTRFS_XATTR_SETGET_FUNCS(name, index) \ 4425103e947SJosef Bacik static int btrfs_xattr_##name##_get(struct inode *inode, \ 4435103e947SJosef Bacik const char *name, void *value, \ 4445103e947SJosef Bacik size_t size) \ 4455103e947SJosef Bacik { \ 446744f52f9SYan if (*name == '\0') \ 447744f52f9SYan return -EINVAL; \ 4485103e947SJosef Bacik return btrfs_xattr_get(inode, index, name, value, size); \ 4495103e947SJosef Bacik } \ 4505103e947SJosef Bacik static int btrfs_xattr_##name##_set(struct inode *inode, \ 4515103e947SJosef Bacik const char *name, const void *value,\ 4525103e947SJosef Bacik size_t size, int flags) \ 4535103e947SJosef Bacik { \ 454744f52f9SYan if (*name == '\0') \ 455744f52f9SYan return -EINVAL; \ 4565103e947SJosef Bacik return btrfs_xattr_set(inode, index, name, value, size, flags); \ 457*69a32ac5SChris Mason } 458*69a32ac5SChris Mason 4595103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); 4605103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); 4615103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); 4625103e947SJosef Bacik BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); 4635103e947SJosef Bacik 4645103e947SJosef Bacik struct xattr_handler btrfs_xattr_security_handler = { 4655103e947SJosef Bacik .prefix = XATTR_SECURITY_PREFIX, 4665103e947SJosef Bacik .list = btrfs_xattr_generic_list, 4675103e947SJosef Bacik .get = btrfs_xattr_security_get, 4685103e947SJosef Bacik .set = btrfs_xattr_security_set, 4695103e947SJosef Bacik }; 4705103e947SJosef Bacik 4715103e947SJosef Bacik struct xattr_handler btrfs_xattr_system_handler = { 4725103e947SJosef Bacik .prefix = XATTR_SYSTEM_PREFIX, 4735103e947SJosef Bacik .list = btrfs_xattr_generic_list, 4745103e947SJosef Bacik .get = btrfs_xattr_system_get, 4755103e947SJosef Bacik .set = btrfs_xattr_system_set, 4765103e947SJosef Bacik }; 4775103e947SJosef Bacik 4785103e947SJosef Bacik struct xattr_handler btrfs_xattr_user_handler = { 4795103e947SJosef Bacik .prefix = XATTR_USER_PREFIX, 4805103e947SJosef Bacik .list = btrfs_xattr_generic_list, 4815103e947SJosef Bacik .get = btrfs_xattr_user_get, 4825103e947SJosef Bacik .set = btrfs_xattr_user_set, 4835103e947SJosef Bacik }; 4845103e947SJosef Bacik 4855103e947SJosef Bacik struct xattr_handler btrfs_xattr_trusted_handler = { 4863acd7ee8SJosef Bacik .prefix = XATTR_TRUSTED_PREFIX, 4875103e947SJosef Bacik .list = btrfs_xattr_generic_list, 4885103e947SJosef Bacik .get = btrfs_xattr_trusted_get, 4895103e947SJosef Bacik .set = btrfs_xattr_trusted_set, 4905103e947SJosef Bacik }; 491