From 5103e947b9b7ac18ddb21a04ee3486e94c6504d7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 16 Nov 2007 11:45:54 -0500 Subject: xattr support for btrfs Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 497 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 fs/btrfs/xattr.c (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c new file mode 100644 index 000000000000..f4ac5e0bbad1 --- /dev/null +++ b/fs/btrfs/xattr.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2007 Red Hat. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include +#include +#include +#include +#include +#include "ctree.h" +#include "btrfs_inode.h" +#include "transaction.h" +#include "xattr.h" +#include "disk-io.h" + +static struct xattr_handler *btrfs_xattr_handler_map[] = { + [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler, + [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, + [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, + [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler, + [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler, + [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, +}; + +struct xattr_handler *btrfs_xattr_handlers[] = { + &btrfs_xattr_user_handler, + &btrfs_xattr_acl_access_handler, + &btrfs_xattr_acl_default_handler, + &btrfs_xattr_trusted_handler, + &btrfs_xattr_security_handler, + &btrfs_xattr_system_handler, + NULL, +}; + +/* + * @param name - the xattr name + * @return - the xattr_handler for the xattr, NULL if its not found + * + * use this with listxattr where we don't already know the type of xattr we + * have + */ +static struct xattr_handler *find_btrfs_xattr_handler(struct extent_buffer *l, + unsigned long name_ptr, + u16 name_len) +{ + struct xattr_handler *handler = NULL; + int i = 0; + + for (handler = btrfs_xattr_handlers[i]; handler != NULL; i++, + handler = btrfs_xattr_handlers[i]) { + u16 prefix_len = strlen(handler->prefix); + + if (name_len < prefix_len) + continue; + + if (memcmp_extent_buffer(l, handler->prefix, name_ptr, + prefix_len) == 0) + break; + } + + return handler; +} + +/* + * @param name_index - the index for the xattr handler + * @return the xattr_handler if we found it, NULL otherwise + * + * use this if we know the type of the xattr already + */ +static struct xattr_handler *btrfs_xattr_handler(int name_index) +{ + struct xattr_handler *handler = NULL; + + if (name_index >= 0 && + name_index < ARRAY_SIZE(btrfs_xattr_handler_map)) + handler = btrfs_xattr_handler_map[name_index]; + + return handler; +} + +static inline char *get_name(const char *name, int name_index) +{ + char *ret = NULL; + struct xattr_handler *handler = btrfs_xattr_handler(name_index); + int prefix_len; + + if (!handler) + return ret; + + prefix_len = strlen(handler->prefix); + + ret = kmalloc(strlen(name) + prefix_len + 1, GFP_KERNEL); + if (!ret) + return ret; + + memcpy(ret, handler->prefix, prefix_len); + memcpy(ret+prefix_len, name, strlen(name)); + ret[prefix_len + strlen(name)] = '\0'; + + return ret; +} + +size_t btrfs_xattr_generic_list(struct inode *inode, char *list, + size_t list_size, const char *name, + size_t name_len) +{ + if (list && (name_len+1) <= list_size) { + memcpy(list, name, name_len); + list[name_len] = '\0'; + } else + return -ERANGE; + + return name_len+1; +} + +ssize_t btrfs_xattr_get(struct inode *inode, int name_index, + const char *attr_name, void *buffer, size_t size) +{ + struct btrfs_dir_item *di; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_path *path; + struct extent_buffer *leaf; + struct xattr_handler *handler = btrfs_xattr_handler(name_index); + int ret = 0; + unsigned long data_ptr; + char *name; + + if (!handler) + return -EOPNOTSUPP; + + /* just in case... */ + if (*attr_name == '\0') + return -EINVAL; + + name = get_name(attr_name, name_index); + if (!name) + return -ENOMEM; + + path = btrfs_alloc_path(); + if (!path) { + kfree(name); + return -ENOMEM; + } + + mutex_lock(&root->fs_info->fs_mutex); + /* lookup the xattr by name */ + di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, + strlen(name), 0); + if (!di || IS_ERR(di)) { + ret = -ENODATA; + goto out; + } + + leaf = path->nodes[0]; + /* if size is 0, that means we want the size of the attr */ + if (!size) { + ret = btrfs_dir_data_len(leaf, di); + goto out; + } + + /* now get the data out of our dir_item */ + if (btrfs_dir_data_len(leaf, di) > size) { + ret = -ERANGE; + goto out; + } + data_ptr = (unsigned long)((char *)(di + 1) + + btrfs_dir_name_len(leaf, di)); + read_extent_buffer(leaf, buffer, data_ptr, + btrfs_dir_name_len(leaf, di)); + ret = btrfs_dir_data_len(leaf, di); + +out: + mutex_unlock(&root->fs_info->fs_mutex); + kfree(name); + btrfs_free_path(path); + return ret; +} + +int btrfs_xattr_set(struct inode *inode, int name_index, + const char *attr_name, const void *value, size_t size, + int flags) +{ + struct btrfs_dir_item *di; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_trans_handle *trans; + struct btrfs_path *path; + struct xattr_handler *handler = btrfs_xattr_handler(name_index); + char *name; + int ret = 0, mod = 0; + + if (!handler) + return -EOPNOTSUPP; + + /* just in case... */ + if (*attr_name == '\0') + return -EINVAL; + + name = get_name(attr_name, name_index); + if (!name) + return -ENOMEM; + + path = btrfs_alloc_path(); + if (!path) { + kfree(name); + return -ENOMEM; + } + + mutex_lock(&root->fs_info->fs_mutex); + trans = btrfs_start_transaction(root, 1); + btrfs_set_trans_block_group(trans, inode); + + /* first lets see if we already have this xattr */ + di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name, + strlen(name), -1); + if (IS_ERR(di)) { + ret = PTR_ERR(di); + goto out; + } + + /* ok we already have this xattr, lets remove it */ + if (di) { + /* if we want create only exit */ + if (flags & XATTR_CREATE) { + ret = -EEXIST; + goto out; + } + + ret = btrfs_delete_one_dir_name(trans, root, path, di); + if (ret) + goto out; + btrfs_release_path(root, path); + + /* if we don't have a value then we are removing the xattr */ + if (!value) { + mod = 1; + goto out; + } + } else if (flags & XATTR_REPLACE) { + /* we couldn't find the attr to replace, so error out */ + ret = -ENODATA; + goto out; + } + + /* ok we have to create a completely new xattr */ + ret = btrfs_insert_xattr_item(trans, root, name, strlen(name), + value, size, inode->i_ino); + if (ret) + goto out; + mod = 1; + +out: + if (mod) { + inode->i_ctime = CURRENT_TIME; + ret = btrfs_update_inode(trans, root, inode); + } + + btrfs_end_transaction(trans, root); + mutex_unlock(&root->fs_info->fs_mutex); + kfree(name); + btrfs_free_path(path); + + return ret; +} + +ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct btrfs_key key, found_key; + struct inode *inode = dentry->d_inode; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_path *path; + struct btrfs_item *item; + struct extent_buffer *leaf; + struct btrfs_dir_item *di; + struct xattr_handler *handler; + int ret = 0, slot, advance; + size_t total_size = 0, size_left = size, written; + unsigned long name_ptr; + char *name; + u32 nritems; + + /* + * ok we want all objects associated with this id. + * NOTE: we set key.offset = 0; because we want to start with the + * first xattr that we find and walk forward + */ + key.objectid = inode->i_ino; + btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); + key.offset = 0; + + path = btrfs_alloc_path(); + path->reada = 2; + if (!path) + return -ENOMEM; + + mutex_lock(&root->fs_info->fs_mutex); + + /* search for our xattrs */ + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + goto err; + ret = 0; + advance = 0; + while (1) { + leaf = path->nodes[0]; + nritems = btrfs_header_nritems(leaf); + slot = path->slots[0]; + + /* this is where we start walking through the path */ + if (advance || slot >= nritems) { + /* + * if we've reached the last slot in this leaf we need + * to go to the next leaf and reset everything + */ + if (slot >= nritems-1) { + ret = btrfs_next_leaf(root, path); + if (ret) + break; + leaf = path->nodes[0]; + nritems = btrfs_header_nritems(leaf); + slot = path->slots[0]; + } else { + /* + * just walking through the slots on this leaf + */ + slot++; + path->slots[0]++; + } + } + advance = 1; + + item = btrfs_item_nr(leaf, slot); + btrfs_item_key_to_cpu(leaf, &found_key, slot); + + /* check to make sure this item is what we want */ + if (found_key.objectid != key.objectid) + break; + if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY) + break; + + di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); + + total_size += btrfs_dir_name_len(leaf, di)+1; + + /* we are just looking for how big our buffer needs to be */ + if (!size) + continue; + + /* find our handler for this xattr */ + name_ptr = (unsigned long)(di + 1); + handler = find_btrfs_xattr_handler(leaf, name_ptr, + btrfs_dir_name_len(leaf, di)); + if (!handler) { + printk(KERN_ERR "btrfs: unsupported xattr found\n"); + continue; + } + + name = kmalloc(btrfs_dir_name_len(leaf, di), GFP_KERNEL); + read_extent_buffer(leaf, name, name_ptr, + btrfs_dir_name_len(leaf, di)); + + /* call the list function associated with this xattr */ + written = handler->list(inode, buffer, size_left, name, + btrfs_dir_name_len(leaf, di)); + kfree(name); + + if (written < 0) { + ret = -ERANGE; + break; + } + + size_left -= written; + buffer += written; + } + ret = total_size; + +err: + mutex_unlock(&root->fs_info->fs_mutex); + btrfs_free_path(path); + + return ret; +} + +/* + * delete all the xattrs associated with the inode. fs_mutex should be + * held when we come into here + */ +int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct inode *inode) +{ + struct btrfs_path *path; + struct btrfs_key key, found_key; + struct btrfs_item *item; + struct extent_buffer *leaf; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + key.objectid = inode->i_ino; + btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); + key.offset = (u64)-1; + + while(1) { + /* look for our next xattr */ + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret < 0) + goto out; + BUG_ON(ret == 0); + + if (path->slots[0] == 0) + break; + + path->slots[0]--; + leaf = path->nodes[0]; + item = btrfs_item_nr(leaf, path->slots[0]); + btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); + + if (found_key.objectid != key.objectid) + break; + if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY) + break; + + ret = btrfs_del_item(trans, root, path); + BUG_ON(ret); + btrfs_release_path(root, path); + } + ret = 0; +out: + btrfs_free_path(path); + + return ret; +} + +/* + * Handler functions + */ +#define BTRFS_XATTR_SETGET_FUNCS(name, index) \ +static int btrfs_xattr_##name##_get(struct inode *inode, \ + const char *name, void *value, \ + size_t size) \ +{ \ + return btrfs_xattr_get(inode, index, name, value, size); \ +} \ +static int btrfs_xattr_##name##_set(struct inode *inode, \ + const char *name, const void *value,\ + size_t size, int flags) \ +{ \ + return btrfs_xattr_set(inode, index, name, value, size, flags); \ +} \ + +BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); +BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); +BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); +BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); + +struct xattr_handler btrfs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .list = btrfs_xattr_generic_list, + .get = btrfs_xattr_security_get, + .set = btrfs_xattr_security_set, +}; + +struct xattr_handler btrfs_xattr_system_handler = { + .prefix = XATTR_SYSTEM_PREFIX, + .list = btrfs_xattr_generic_list, + .get = btrfs_xattr_system_get, + .set = btrfs_xattr_system_set, +}; + +struct xattr_handler btrfs_xattr_user_handler = { + .prefix = XATTR_USER_PREFIX, + .list = btrfs_xattr_generic_list, + .get = btrfs_xattr_user_get, + .set = btrfs_xattr_user_set, +}; + +struct xattr_handler btrfs_xattr_trusted_handler = { + .prefix = XATTR_USER_PREFIX, + .list = btrfs_xattr_generic_list, + .get = btrfs_xattr_trusted_get, + .set = btrfs_xattr_trusted_set, +}; -- cgit v1.2.1 From 1caf9342fc71d020e788a59598a44d4ea0136b36 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 19 Nov 2007 10:18:17 -0500 Subject: Btrfs: Make ACLs return EOPNOTSUPP for now There was a slight problem with ACL's returning EINVAL when you tried to set an ACL. This isn't correct, we should be returning EOPNOTSUPP, so I did a very ugly thing and just commented everybody out and made them return EOPNOTSUPP. This is only temporary, I'm going back to implement ACL's, but Chris wants to push out a release so this will suffice for now. Also Yan suggested setting reada to -1 in the delete case to enable backwards readahead, and in the listxattr case I moved path->reada = 2; to after the if (!path) check so we can avoid a possible null dereference. Thank you, Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index f4ac5e0bbad1..984616cca254 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -302,9 +302,9 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) key.offset = 0; path = btrfs_alloc_path(); - path->reada = 2; if (!path) return -ENOMEM; + path->reada = 2; mutex_lock(&root->fs_info->fs_mutex); @@ -410,7 +410,7 @@ int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, path = btrfs_alloc_path(); if (!path) return -ENOMEM; - + path->reada = -1; key.objectid = inode->i_ino; btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); key.offset = (u64)-1; -- cgit v1.2.1 From 3acd7ee876c508973eb4722de5b00b3dff4c7372 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 19 Nov 2007 10:18:19 -0500 Subject: Btrfs: xattr fixes This fixes two typos that Yan pointed out to me. Thanks much, Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 984616cca254..33caaf5b4b0c 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -180,7 +180,7 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, data_ptr = (unsigned long)((char *)(di + 1) + btrfs_dir_name_len(leaf, di)); read_extent_buffer(leaf, buffer, data_ptr, - btrfs_dir_name_len(leaf, di)); + btrfs_dir_data_len(leaf, di)); ret = btrfs_dir_data_len(leaf, di); out: @@ -490,7 +490,7 @@ struct xattr_handler btrfs_xattr_user_handler = { }; struct xattr_handler btrfs_xattr_trusted_handler = { - .prefix = XATTR_USER_PREFIX, + .prefix = XATTR_TRUSTED_PREFIX, .list = btrfs_xattr_generic_list, .get = btrfs_xattr_trusted_get, .set = btrfs_xattr_trusted_set, -- cgit v1.2.1 From 744f52f997b21de2a01931f79cf6c198bf688120 Mon Sep 17 00:00:00 2001 From: Yan Date: Mon, 14 Jan 2008 13:26:08 -0500 Subject: Btrfs: Implement ACLs setting and getting ACLs are stored but not used for permission checks (yet) Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 33caaf5b4b0c..85ac42605f8d 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -141,11 +141,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, if (!handler) return -EOPNOTSUPP; - - /* just in case... */ - if (*attr_name == '\0') - return -EINVAL; - name = get_name(attr_name, name_index); if (!name) return -ENOMEM; @@ -201,14 +196,8 @@ int btrfs_xattr_set(struct inode *inode, int name_index, struct xattr_handler *handler = btrfs_xattr_handler(name_index); char *name; int ret = 0, mod = 0; - if (!handler) return -EOPNOTSUPP; - - /* just in case... */ - if (*attr_name == '\0') - return -EINVAL; - name = get_name(attr_name, name_index); if (!name) return -ENOMEM; @@ -454,15 +443,18 @@ static int btrfs_xattr_##name##_get(struct inode *inode, \ const char *name, void *value, \ size_t size) \ { \ + if (*name == '\0') \ + return -EINVAL; \ return btrfs_xattr_get(inode, index, name, value, size); \ } \ static int btrfs_xattr_##name##_set(struct inode *inode, \ const char *name, const void *value,\ size_t size, int flags) \ { \ + if (*name == '\0') \ + return -EINVAL; \ return btrfs_xattr_set(inode, index, name, value, size, flags); \ } \ - BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); -- cgit v1.2.1 From 69a32ac5175ec9bcfb407e8619a024e5eaea87b7 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 14 Jan 2008 14:33:35 -0500 Subject: Btrfs: Change magic string to reflect new format Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 85ac42605f8d..4b3bd24af72b 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -454,7 +454,8 @@ static int btrfs_xattr_##name##_set(struct inode *inode, \ if (*name == '\0') \ return -EINVAL; \ return btrfs_xattr_set(inode, index, name, value, size, flags); \ -} \ +} + BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); -- cgit v1.2.1 From caaca38b8fdcf63a17647fddae2195b189e19e37 Mon Sep 17 00:00:00 2001 From: Yan Date: Thu, 17 Jan 2008 11:59:48 -0500 Subject: Btrfs: Fix compile on kernel without ACLs enabled Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 4b3bd24af72b..0a4950400f85 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -26,20 +26,22 @@ #include "transaction.h" #include "xattr.h" #include "disk-io.h" - static struct xattr_handler *btrfs_xattr_handler_map[] = { [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler, +#ifdef CONFIG_FS_POSIX_ACL [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, +#endif [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler, [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler, [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, }; - struct xattr_handler *btrfs_xattr_handlers[] = { &btrfs_xattr_user_handler, +#ifdef CONFIG_FS_POSIX_ACL &btrfs_xattr_acl_access_handler, &btrfs_xattr_acl_default_handler, +#endif &btrfs_xattr_trusted_handler, &btrfs_xattr_security_handler, &btrfs_xattr_system_handler, -- cgit v1.2.1 From eba12c7bfcb4855fc757357e5e5b0b9a474499ba Mon Sep 17 00:00:00 2001 From: Yan Date: Mon, 9 Jun 2008 22:21:46 -0400 Subject: Btrfs: Dislable acl xattr handlers The acl code is not yet complete, and the xattr handlers are causing problems for cp -p on some distros. Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 0a4950400f85..f63488dc2f16 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -29,22 +29,22 @@ static struct xattr_handler *btrfs_xattr_handler_map[] = { [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler, #ifdef CONFIG_FS_POSIX_ACL - [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, - [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, +// [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, +// [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, #endif [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler, [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler, - [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, +// [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, }; struct xattr_handler *btrfs_xattr_handlers[] = { &btrfs_xattr_user_handler, #ifdef CONFIG_FS_POSIX_ACL - &btrfs_xattr_acl_access_handler, - &btrfs_xattr_acl_default_handler, +// &btrfs_xattr_acl_access_handler, +// &btrfs_xattr_acl_default_handler, #endif &btrfs_xattr_trusted_handler, &btrfs_xattr_security_handler, - &btrfs_xattr_system_handler, +// &btrfs_xattr_system_handler, NULL, }; -- cgit v1.2.1 From a213501153fd66e2359e091b1612841305ba6551 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 25 Jun 2008 16:01:30 -0400 Subject: Btrfs: Replace the big fs_mutex with a collection of other locks Extent alloctions are still protected by a large alloc_mutex. Objectid allocations are covered by a objectid mutex Other btree operations are protected by a lock on individual btree nodes Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index f63488dc2f16..3e9eb91c3c89 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -153,7 +153,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, return -ENOMEM; } - mutex_lock(&root->fs_info->fs_mutex); /* lookup the xattr by name */ di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, strlen(name), 0); @@ -181,7 +180,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, ret = btrfs_dir_data_len(leaf, di); out: - mutex_unlock(&root->fs_info->fs_mutex); kfree(name); btrfs_free_path(path); return ret; @@ -210,7 +208,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index, return -ENOMEM; } - mutex_lock(&root->fs_info->fs_mutex); trans = btrfs_start_transaction(root, 1); btrfs_set_trans_block_group(trans, inode); @@ -260,7 +257,6 @@ out: } btrfs_end_transaction(trans, root); - mutex_unlock(&root->fs_info->fs_mutex); kfree(name); btrfs_free_path(path); @@ -297,8 +293,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) return -ENOMEM; path->reada = 2; - mutex_lock(&root->fs_info->fs_mutex); - /* search for our xattrs */ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) @@ -379,15 +373,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) ret = total_size; err: - mutex_unlock(&root->fs_info->fs_mutex); btrfs_free_path(path); return ret; } /* - * delete all the xattrs associated with the inode. fs_mutex should be - * held when we come into here + * delete all the xattrs associated with the inode. */ int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) -- cgit v1.2.1 From 6099afe88fe64b2f47c43a8a71c13be3a416bbf7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 24 Jul 2008 12:16:03 -0400 Subject: Btrfs: Remove unused xattr code Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 3e9eb91c3c89..6730b5958844 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -378,57 +378,6 @@ err: return ret; } -/* - * delete all the xattrs associated with the inode. - */ -int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) -{ - struct btrfs_path *path; - struct btrfs_key key, found_key; - struct btrfs_item *item; - struct extent_buffer *leaf; - int ret; - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - path->reada = -1; - key.objectid = inode->i_ino; - btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); - key.offset = (u64)-1; - - while(1) { - /* look for our next xattr */ - ret = btrfs_search_slot(trans, root, &key, path, -1, 1); - if (ret < 0) - goto out; - BUG_ON(ret == 0); - - if (path->slots[0] == 0) - break; - - path->slots[0]--; - leaf = path->nodes[0]; - item = btrfs_item_nr(leaf, path->slots[0]); - btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); - - if (found_key.objectid != key.objectid) - break; - if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY) - break; - - ret = btrfs_del_item(trans, root, path); - BUG_ON(ret); - btrfs_release_path(root, path); - } - ret = 0; -out: - btrfs_free_path(path); - - return ret; -} - /* * Handler functions */ -- cgit v1.2.1 From 33268eaf0b3db5e2bd12c0ada81a8e8f87a46d68 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 24 Jul 2008 12:16:36 -0400 Subject: Btrfs: Add ACL support Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 6730b5958844..121c9550314f 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -26,25 +26,27 @@ #include "transaction.h" #include "xattr.h" #include "disk-io.h" + static struct xattr_handler *btrfs_xattr_handler_map[] = { [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler, #ifdef CONFIG_FS_POSIX_ACL -// [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, -// [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, + [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, + [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, #endif [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler, [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler, -// [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, + [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, }; + struct xattr_handler *btrfs_xattr_handlers[] = { &btrfs_xattr_user_handler, #ifdef CONFIG_FS_POSIX_ACL -// &btrfs_xattr_acl_access_handler, -// &btrfs_xattr_acl_default_handler, + &btrfs_xattr_acl_access_handler, + &btrfs_xattr_acl_default_handler, #endif &btrfs_xattr_trusted_handler, &btrfs_xattr_security_handler, -// &btrfs_xattr_system_handler, + &btrfs_xattr_system_handler, NULL, }; @@ -237,10 +239,14 @@ int btrfs_xattr_set(struct inode *inode, int name_index, mod = 1; goto out; } - } else if (flags & XATTR_REPLACE) { - /* we couldn't find the attr to replace, so error out */ - ret = -ENODATA; - goto out; + } else { + btrfs_release_path(root, path); + + if (flags & XATTR_REPLACE) { + /* we couldn't find the attr to replace */ + ret = -ENODATA; + goto out; + } } /* ok we have to create a completely new xattr */ -- cgit v1.2.1 From eaa47d8612783807ef9703ebc9bf0d0f0455bf62 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 28 Aug 2008 06:21:16 -0400 Subject: btrfs: optmize listxattr The ->list handler is really not useful at all, because we always call btrfs_xattr_generic_list anyway. After this is done find_btrfs_xattr_handler becomes unused, and it becomes obvious that the temporary name buffer allocation isn't needed but we can directly copy into the supplied buffer. Tested with various getfattr -d calls on varying xattr lists. Signed-off-by: Christoph Hellwig Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 82 ++++++++------------------------------------------------ 1 file changed, 11 insertions(+), 71 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 121c9550314f..fdfece41dd16 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -50,35 +50,6 @@ struct xattr_handler *btrfs_xattr_handlers[] = { NULL, }; -/* - * @param name - the xattr name - * @return - the xattr_handler for the xattr, NULL if its not found - * - * use this with listxattr where we don't already know the type of xattr we - * have - */ -static struct xattr_handler *find_btrfs_xattr_handler(struct extent_buffer *l, - unsigned long name_ptr, - u16 name_len) -{ - struct xattr_handler *handler = NULL; - int i = 0; - - for (handler = btrfs_xattr_handlers[i]; handler != NULL; i++, - handler = btrfs_xattr_handlers[i]) { - u16 prefix_len = strlen(handler->prefix); - - if (name_len < prefix_len) - continue; - - if (memcmp_extent_buffer(l, handler->prefix, name_ptr, - prefix_len) == 0) - break; - } - - return handler; -} - /* * @param name_index - the index for the xattr handler * @return the xattr_handler if we found it, NULL otherwise @@ -118,19 +89,6 @@ static inline char *get_name(const char *name, int name_index) return ret; } -size_t btrfs_xattr_generic_list(struct inode *inode, char *list, - size_t list_size, const char *name, - size_t name_len) -{ - if (list && (name_len+1) <= list_size) { - memcpy(list, name, name_len); - list[name_len] = '\0'; - } else - return -ERANGE; - - return name_len+1; -} - ssize_t btrfs_xattr_get(struct inode *inode, int name_index, const char *attr_name, void *buffer, size_t size) { @@ -278,11 +236,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) struct btrfs_item *item; struct extent_buffer *leaf; struct btrfs_dir_item *di; - struct xattr_handler *handler; int ret = 0, slot, advance; - size_t total_size = 0, size_left = size, written; + size_t total_size = 0, size_left = size; unsigned long name_ptr; - char *name; + size_t name_len; u32 nritems; /* @@ -344,37 +301,24 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); - total_size += btrfs_dir_name_len(leaf, di)+1; + name_len = btrfs_dir_name_len(leaf, di); + total_size += name_len + 1; /* we are just looking for how big our buffer needs to be */ if (!size) continue; - /* find our handler for this xattr */ - name_ptr = (unsigned long)(di + 1); - handler = find_btrfs_xattr_handler(leaf, name_ptr, - btrfs_dir_name_len(leaf, di)); - if (!handler) { - printk(KERN_ERR "btrfs: unsupported xattr found\n"); - continue; - } - - name = kmalloc(btrfs_dir_name_len(leaf, di), GFP_KERNEL); - read_extent_buffer(leaf, name, name_ptr, - btrfs_dir_name_len(leaf, di)); - - /* call the list function associated with this xattr */ - written = handler->list(inode, buffer, size_left, name, - btrfs_dir_name_len(leaf, di)); - kfree(name); - - if (written < 0) { + if (!buffer || (name_len + 1) > size_left) { ret = -ERANGE; break; } - size_left -= written; - buffer += written; + name_ptr = (unsigned long)(di + 1); + read_extent_buffer(leaf, buffer, name_ptr, name_len); + buffer[name_len] = '\0'; + + size_left -= name_len + 1; + buffer += name_len + 1; } ret = total_size; @@ -412,28 +356,24 @@ BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); struct xattr_handler btrfs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, - .list = btrfs_xattr_generic_list, .get = btrfs_xattr_security_get, .set = btrfs_xattr_security_set, }; struct xattr_handler btrfs_xattr_system_handler = { .prefix = XATTR_SYSTEM_PREFIX, - .list = btrfs_xattr_generic_list, .get = btrfs_xattr_system_get, .set = btrfs_xattr_system_set, }; struct xattr_handler btrfs_xattr_user_handler = { .prefix = XATTR_USER_PREFIX, - .list = btrfs_xattr_generic_list, .get = btrfs_xattr_user_get, .set = btrfs_xattr_user_set, }; struct xattr_handler btrfs_xattr_trusted_handler = { .prefix = XATTR_TRUSTED_PREFIX, - .list = btrfs_xattr_generic_list, .get = btrfs_xattr_trusted_get, .set = btrfs_xattr_trusted_set, }; -- cgit v1.2.1 From 95819c05732c511338b43c115ffbcee978c02888 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 28 Aug 2008 06:21:17 -0400 Subject: Btrfs: optimize btrget/set/removexattr btrfs actually stores the whole xattr name, including the prefix ondisk, so using the generic resolver that strips off the prefix is not very helpful. Instead do the real ondisk xattrs manually and only use the generic resolver for synthetic xattrs like ACLs. (Sorry Josef for guiding you towards the wrong direction here intially) Signed-off-by: Christoph Hellwig Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 204 ++++++++++++++++++++----------------------------------- 1 file changed, 73 insertions(+), 131 deletions(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index fdfece41dd16..adb4b32a9d51 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -27,91 +27,20 @@ #include "xattr.h" #include "disk-io.h" -static struct xattr_handler *btrfs_xattr_handler_map[] = { - [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler, -#ifdef CONFIG_FS_POSIX_ACL - [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler, - [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler, -#endif - [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler, - [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler, - [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler, -}; - -struct xattr_handler *btrfs_xattr_handlers[] = { - &btrfs_xattr_user_handler, -#ifdef CONFIG_FS_POSIX_ACL - &btrfs_xattr_acl_access_handler, - &btrfs_xattr_acl_default_handler, -#endif - &btrfs_xattr_trusted_handler, - &btrfs_xattr_security_handler, - &btrfs_xattr_system_handler, - NULL, -}; - -/* - * @param name_index - the index for the xattr handler - * @return the xattr_handler if we found it, NULL otherwise - * - * use this if we know the type of the xattr already - */ -static struct xattr_handler *btrfs_xattr_handler(int name_index) -{ - struct xattr_handler *handler = NULL; - - if (name_index >= 0 && - name_index < ARRAY_SIZE(btrfs_xattr_handler_map)) - handler = btrfs_xattr_handler_map[name_index]; - - return handler; -} - -static inline char *get_name(const char *name, int name_index) -{ - char *ret = NULL; - struct xattr_handler *handler = btrfs_xattr_handler(name_index); - int prefix_len; - - if (!handler) - return ret; - - prefix_len = strlen(handler->prefix); - - ret = kmalloc(strlen(name) + prefix_len + 1, GFP_KERNEL); - if (!ret) - return ret; - - memcpy(ret, handler->prefix, prefix_len); - memcpy(ret+prefix_len, name, strlen(name)); - ret[prefix_len + strlen(name)] = '\0'; - - return ret; -} -ssize_t btrfs_xattr_get(struct inode *inode, int name_index, - const char *attr_name, void *buffer, size_t size) +ssize_t __btrfs_getxattr(struct inode *inode, const char *name, + void *buffer, size_t size) { struct btrfs_dir_item *di; struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_path *path; struct extent_buffer *leaf; - struct xattr_handler *handler = btrfs_xattr_handler(name_index); int ret = 0; unsigned long data_ptr; - char *name; - - if (!handler) - return -EOPNOTSUPP; - name = get_name(attr_name, name_index); - if (!name) - return -ENOMEM; path = btrfs_alloc_path(); - if (!path) { - kfree(name); + if (!path) return -ENOMEM; - } /* lookup the xattr by name */ di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, @@ -140,33 +69,22 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, ret = btrfs_dir_data_len(leaf, di); out: - kfree(name); btrfs_free_path(path); return ret; } -int btrfs_xattr_set(struct inode *inode, int name_index, - const char *attr_name, const void *value, size_t size, - int flags) +int __btrfs_setxattr(struct inode *inode, const char *name, + const void *value, size_t size, int flags) { struct btrfs_dir_item *di; struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; struct btrfs_path *path; - struct xattr_handler *handler = btrfs_xattr_handler(name_index); - char *name; int ret = 0, mod = 0; - if (!handler) - return -EOPNOTSUPP; - name = get_name(attr_name, name_index); - if (!name) - return -ENOMEM; path = btrfs_alloc_path(); - if (!path) { - kfree(name); + if (!path) return -ENOMEM; - } trans = btrfs_start_transaction(root, 1); btrfs_set_trans_block_group(trans, inode); @@ -221,9 +139,7 @@ out: } btrfs_end_transaction(trans, root); - kfree(name); btrfs_free_path(path); - return ret; } @@ -329,51 +245,77 @@ err: } /* - * Handler functions + * List of handlers for synthetic system.* attributes. All real ondisk + * attributes are handled directly. + */ +struct xattr_handler *btrfs_xattr_handlers[] = { +#ifdef CONFIG_FS_POSIX_ACL + &btrfs_xattr_acl_access_handler, + &btrfs_xattr_acl_default_handler, +#endif + NULL, +}; + +/* + * Check if the attribute is in a supported namespace. + * + * This applied after the check for the synthetic attributes in the system + * namespace. */ -#define BTRFS_XATTR_SETGET_FUNCS(name, index) \ -static int btrfs_xattr_##name##_get(struct inode *inode, \ - const char *name, void *value, \ - size_t size) \ -{ \ - if (*name == '\0') \ - return -EINVAL; \ - return btrfs_xattr_get(inode, index, name, value, size); \ -} \ -static int btrfs_xattr_##name##_set(struct inode *inode, \ - const char *name, const void *value,\ - size_t size, int flags) \ -{ \ - if (*name == '\0') \ - return -EINVAL; \ - return btrfs_xattr_set(inode, index, name, value, size, flags); \ +static bool btrfs_is_valid_xattr(const char *name) +{ + return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || + !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || + !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || + !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } -BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); -BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); -BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); -BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); +ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) +{ + /* + * If this is a request for a synthetic attribute in the system.* + * namespace use the generic infrastructure to resolve a handler + * for it via sb->s_xattr. + */ + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_getxattr(dentry, name, buffer, size); -struct xattr_handler btrfs_xattr_security_handler = { - .prefix = XATTR_SECURITY_PREFIX, - .get = btrfs_xattr_security_get, - .set = btrfs_xattr_security_set, -}; + if (!btrfs_is_valid_xattr(name)) + return -EOPNOTSUPP; + return __btrfs_getxattr(dentry->d_inode, name, buffer, size); +} -struct xattr_handler btrfs_xattr_system_handler = { - .prefix = XATTR_SYSTEM_PREFIX, - .get = btrfs_xattr_system_get, - .set = btrfs_xattr_system_set, -}; +int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) +{ + /* + * If this is a request for a synthetic attribute in the system.* + * namespace use the generic infrastructure to resolve a handler + * for it via sb->s_xattr. + */ + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_setxattr(dentry, name, value, size, flags); -struct xattr_handler btrfs_xattr_user_handler = { - .prefix = XATTR_USER_PREFIX, - .get = btrfs_xattr_user_get, - .set = btrfs_xattr_user_set, -}; + if (!btrfs_is_valid_xattr(name)) + return -EOPNOTSUPP; -struct xattr_handler btrfs_xattr_trusted_handler = { - .prefix = XATTR_TRUSTED_PREFIX, - .get = btrfs_xattr_trusted_get, - .set = btrfs_xattr_trusted_set, -}; + if (size == 0) + value = ""; /* empty EA, do not remove */ + return __btrfs_setxattr(dentry->d_inode, name, value, size, flags); +} + +int btrfs_removexattr(struct dentry *dentry, const char *name) +{ + /* + * If this is a request for a synthetic attribute in the system.* + * namespace use the generic infrastructure to resolve a handler + * for it via sb->s_xattr. + */ + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_removexattr(dentry, name); + + if (!btrfs_is_valid_xattr(name)) + return -EOPNOTSUPP; + return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); +} -- cgit v1.2.1 From b16281c30c841c6d999ff36c8d903f42a69315f2 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Weinraub Date: Wed, 17 Dec 2008 10:21:26 -0500 Subject: Btrfs: fix return value from btrfs_listxattr when buffer size is too small The return value was being overwritten. Signed-off-by: Yehuda Sadeh --- fs/btrfs/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index adb4b32a9d51..4146f0710e6a 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -226,7 +226,7 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) if (!buffer || (name_len + 1) > size_left) { ret = -ERANGE; - break; + goto err; } name_ptr = (unsigned long)(di + 1); -- cgit v1.2.1 From d397712bcc6a759a560fd247e6053ecae091f958 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 5 Jan 2009 21:25:51 -0500 Subject: Btrfs: Fix checkpatch.pl warnings There were many, most are fixed now. struct-funcs.c generates some warnings but these are bogus. Signed-off-by: Chris Mason --- fs/btrfs/xattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/btrfs/xattr.c') diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 4146f0710e6a..7f332e270894 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -264,7 +264,8 @@ struct xattr_handler *btrfs_xattr_handlers[] = { */ static bool btrfs_is_valid_xattr(const char *name) { - return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || + return !strncmp(name, XATTR_SECURITY_PREFIX, + XATTR_SECURITY_PREFIX_LEN) || !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); -- cgit v1.2.1