Josef Bacik
2007-Nov-07 18:21 UTC
[Btrfs-devel] [PATCH 2/4] supporting code to add xattr support
Hello, This patch has all the supporting code that is required for xattr support. This adds the changes to the make file, changes to dir-item.c to handle xattr dir_item's, and it adds something to btrfs_unlink_trans() so that it will remove any/all xattrs associated with a file when it removes the file. Thank you, Josef diff -r 9cb5f0f5c713 Makefile --- a/Makefile Thu Aug 30 12:16:51 2007 -0400 +++ b/Makefile Tue Nov 06 21:31:20 2007 -0500 @@ -5,7 +5,8 @@ btrfs-y := super.o ctree.o extent-tree.o btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ hash.o file-item.o inode-item.o inode-map.o disk-io.o \ transaction.o bit-radix.o inode.o file.o tree-defrag.o \ - extent_map.o sysfs.o + extent_map.o sysfs.o xattr.o xattr_user.o xattr_security.o acl.o \ + xattr_trusted.o xattr_system.o #btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ # root-tree.o dir-item.o hash.o file-item.o inode-item.o \ diff -r 9cb5f0f5c713 ctree.h --- a/ctree.h Thu Aug 30 12:16:51 2007 -0400 +++ b/ctree.h Wed Nov 07 21:59:55 2007 -0500 @@ -61,6 +61,7 @@ extern struct kmem_cache *btrfs_path_cac #define BTRFS_FT_SOCK 6 #define BTRFS_FT_SYMLINK 7 #define BTRFS_FT_MAX 8 +#define BTRFS_FT_XATTR 9 /* * the key defines the order in the tree, and so it also defines (optimal) @@ -220,7 +221,7 @@ struct btrfs_inode_item { struct btrfs_dir_item { struct btrfs_disk_key location; - __le16 flags; + __le16 data_len; __le16 name_len; u8 type; } __attribute__ ((__packed__)); @@ -358,7 +359,7 @@ struct btrfs_root { * the FS */ #define BTRFS_INODE_ITEM_KEY 1 - +#define BTRFS_XATTR_ITEM_KEY 2 /* reserve 2-15 close to the inode for later flexibility */ /* @@ -400,7 +401,6 @@ struct btrfs_root { * data in the FS */ #define BTRFS_STRING_ITEM_KEY 253 - static inline u64 btrfs_block_group_used(struct btrfs_block_group_item *bi) { @@ -606,16 +606,6 @@ static inline void btrfs_set_item_size(s item->size = cpu_to_le16(val); } -static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) -{ - return le16_to_cpu(d->flags); -} - -static inline void btrfs_set_dir_flags(struct btrfs_dir_item *d, u16 val) -{ - d->flags = cpu_to_le16(val); -} - static inline u8 btrfs_dir_type(struct btrfs_dir_item *d) { return d->type; @@ -634,6 +624,16 @@ static inline void btrfs_set_dir_name_le static inline void btrfs_set_dir_name_len(struct btrfs_dir_item *d, u16 val) { d->name_len = cpu_to_le16(val); +} + +static inline u16 btrfs_dir_data_len(struct btrfs_dir_item *d) +{ + return le16_to_cpu(d->data_len); +} + +static inline void btrfs_set_dir_data_len(struct btrfs_dir_item *d, u16 val) +{ + d->data_len = cpu_to_le16(val); } static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu, @@ -1170,6 +1170,15 @@ int btrfs_delete_one_dir_name(struct btr struct btrfs_root *root, struct btrfs_path *path, struct btrfs_dir_item *di); +int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, const char *name, + int name_len, const void *data, int data_len, + u64 dir); +struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, + const char *name, int name_len, + int mod); /* inode-map.c */ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, struct btrfs_root *fs_root, @@ -1251,4 +1260,13 @@ void btrfs_sysfs_del_root(struct btrfs_r void btrfs_sysfs_del_root(struct btrfs_root *root); void btrfs_sysfs_del_super(struct btrfs_fs_info *root); +/* xattr.c */ +ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, void *buffer, + size_t size); +int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); +int btrfs_removexattr(struct dentry *dentry, const char *name); +ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size); +int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct inode *inode); #endif diff -r 9cb5f0f5c713 dir-item.c --- a/dir-item.c Thu Aug 30 12:16:51 2007 -0400 +++ b/dir-item.c Thu Nov 08 03:52:09 2007 -0500 @@ -43,8 +43,6 @@ static struct btrfs_dir_item *insert_wit return ERR_PTR(-EEXIST); ret = btrfs_extend_item(trans, root, path, data_size); WARN_ON(ret > 0); - if (ret) - return ERR_PTR(ret); } if (ret < 0) return ERR_PTR(ret); @@ -55,6 +53,51 @@ static struct btrfs_dir_item *insert_wit BUG_ON(data_size > btrfs_item_size(item)); ptr += btrfs_item_size(item) - data_size; return (struct btrfs_dir_item *)ptr; +} + +int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, const char *name, + int name_len, const void *data, int data_len, + u64 dir) +{ + int ret = 0; + struct btrfs_path *path; + struct btrfs_dir_item *dir_item; + char *name_ptr, *data_ptr; + struct btrfs_key key; + struct btrfs_key location; + u32 data_size; + + key.objectid = dir; + key.flags = 0; + btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); + ret = btrfs_name_hash(name, name_len, &key.offset); + BUG_ON(ret); + path = btrfs_alloc_path(); + data_size = sizeof(*dir_item) + name_len + data_len; + dir_item = insert_with_overflow(trans, root, path, &key, data_size, + name, name_len); + /* + * FIXME: at some point we should handle xattr's that are larger than + * what we can fit in our leaf + */ + BUG_ON(IS_ERR(dir_item)); + + memset(&location, 0, sizeof(location)); + btrfs_cpu_key_to_disk(&dir_item->location, &location); + btrfs_set_dir_type(dir_item, BTRFS_FT_XATTR); + btrfs_set_dir_name_len(dir_item, name_len); + btrfs_set_dir_data_len(dir_item, data_len); + name_ptr = (char *)(dir_item + 1); + data_ptr = (char *)(name_ptr + name_len); + + btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); + btrfs_memcpy(root, path->nodes[0]->b_data, data_ptr, data, data_len); + btrfs_mark_buffer_dirty(path->nodes[0]); + +out: + btrfs_free_path(path); + return ret; } int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root @@ -87,8 +130,8 @@ int btrfs_insert_dir_item(struct btrfs_t btrfs_cpu_key_to_disk(&dir_item->location, location); btrfs_set_dir_type(dir_item, type); - btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_name_len(dir_item, name_len); + btrfs_set_dir_data_len(dir_item, 0); name_ptr = (char *)(dir_item + 1); btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); @@ -112,8 +155,8 @@ second_insert: } btrfs_cpu_key_to_disk(&dir_item->location, location); btrfs_set_dir_type(dir_item, type); - btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_name_len(dir_item, name_len); + btrfs_set_dir_data_len(dir_item, 0); name_ptr = (char *)(dir_item + 1); btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); btrfs_mark_buffer_dirty(path->nodes[0]); @@ -188,6 +231,43 @@ btrfs_lookup_dir_index_item(struct btrfs return btrfs_match_dir_item_name(root, path, name, name_len); } +struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, + const char *name, int name_len, + int mod) +{ + int ret; + struct btrfs_key key; + int ins_len = mod < 0 ? -1 : 0; + int cow = mod != 0; + struct btrfs_disk_key *found_key; + struct btrfs_leaf *leaf; + + key.objectid = dir; + key.flags = 0; + btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); + ret = btrfs_name_hash(name, name_len, &key.offset); + BUG_ON(ret); + ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); + if (ret < 0) + return ERR_PTR(ret); + if (ret > 0) { + if (path->slots[0] == 0) + return NULL; + path->slots[0]--; + } + leaf = btrfs_buffer_leaf(path->nodes[0]); + found_key = &leaf->items[path->slots[0]].key; + + if (btrfs_disk_key_objectid(found_key) != dir || + btrfs_disk_key_type(found_key) != BTRFS_XATTR_ITEM_KEY || + btrfs_disk_key_offset(found_key) != key.offset) + return NULL; + + return btrfs_match_dir_item_name(root, path, name, name_len); +} + struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, const char *name, int name_len) @@ -229,7 +309,7 @@ int btrfs_delete_one_dir_name(struct btr int ret = 0; leaf = btrfs_buffer_leaf(path->nodes[0]); - sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); + sub_item_len = sizeof(*di) + btrfs_dir_name_len(di) + btrfs_dir_data_len(di); item_len = btrfs_item_size(leaf->items + path->slots[0]); if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { ret = btrfs_del_item(trans, root, path); diff -r 9cb5f0f5c713 inode.c --- a/inode.c Thu Aug 30 12:16:51 2007 -0400 +++ b/inode.c Thu Nov 08 03:54:17 2007 -0500 @@ -32,6 +32,7 @@ #include <linux/compat.h> #include <linux/bit_spinlock.h> #include <linux/version.h> +#include <linux/xattr.h> #include "ctree.h" #include "disk-io.h" #include "transaction.h" @@ -367,6 +368,10 @@ static int btrfs_unlink_trans(struct btr goto err; } ret = btrfs_delete_one_dir_name(trans, root, path, di); + if (ret) + goto err; + + ret = btrfs_delete_xattrs(trans, root, dentry->d_inode); dentry->d_inode->i_ctime = dir->i_ctime; err: @@ -2280,6 +2285,10 @@ static struct inode_operations btrfs_dir .symlink = btrfs_symlink, .setattr = btrfs_setattr, .mknod = btrfs_mknod, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = btrfs_listxattr, + .removexattr = generic_removexattr, }; static struct inode_operations btrfs_dir_ro_inode_operations = { @@ -2326,6 +2335,10 @@ static struct inode_operations btrfs_fil .truncate = btrfs_truncate, .getattr = btrfs_getattr, .setattr = btrfs_setattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = btrfs_listxattr, + .removexattr = generic_removexattr, }; static struct inode_operations btrfs_special_inode_operations = { diff -r 9cb5f0f5c713 print-tree.c --- a/print-tree.c Thu Aug 30 12:16:51 2007 -0400 +++ b/print-tree.c Wed Sep 05 12:05:29 2007 -0500 @@ -56,10 +56,9 @@ void btrfs_print_leaf(struct btrfs_root break; case BTRFS_DIR_ITEM_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); - printk("\t\tdir oid %llu flags %u type %u\n", + printk("\t\tdir oid %llu type %u\n", (unsigned long long)btrfs_disk_key_objectid( &di->location), - btrfs_dir_flags(di), btrfs_dir_type(di)); printk("\t\tname %.*s\n", btrfs_dir_name_len(di),(char *)(di + 1)); diff -r 9cb5f0f5c713 super.c --- a/super.c Thu Aug 30 12:16:51 2007 -0400 +++ b/super.c Wed Sep 05 12:05:29 2007 -0500 @@ -40,6 +40,7 @@ #include "btrfs_inode.h" #include "ioctl.h" #include "print-tree.h" +#include "xattr.h" #define BTRFS_SUPER_MAGIC 0x9123682E @@ -106,6 +107,7 @@ static int btrfs_fill_super(struct super sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_magic = BTRFS_SUPER_MAGIC; sb->s_op = &btrfs_super_ops; + sb->s_xattr = btrfs_xattr_handlers; sb->s_time_gran = 1; tree_root = open_ctree(sb);
Zach Brown
2007-Nov-08 10:00 UTC
[Btrfs-devel] [PATCH 2/4] supporting code to add xattr support
> + > +int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, > + struct btrfs_root *root, const char *name, > + int name_len, const void *data, int data_len,I bet those _lens can never be negative. They shouldn't be 'int's. (types that don't reflect the intended range of values is a pet peeve of mine :)). u32 is probably most appropriate, given that they're being jammed into data_size? - z