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, 1835103e947SJosef Bacik btrfs_dir_name_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; 307*1caf9342SJosef 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; 413*1caf9342SJosef 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 = { 4935103e947SJosef Bacik .prefix = XATTR_USER_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