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);

_______________________________________________
Btrfs-devel mailing list
[email protected]
http://oss.oracle.com/mailman/listinfo/btrfs-devel

Reply via email to