[Btrfs-devel] Quick question

Josef Bacik jbacik at redhat.com
Tue Aug 28 08:36:10 PDT 2007


On Mon, Aug 27, 2007 at 07:21:49PM -0400, Chris Mason wrote:
> On Mon, 27 Aug 2007 17:37:37 -0400
> Josef Bacik <jbacik at redhat.com> wrote:
> 
> > Hello,
> > 
> > Ok I've just about got this xattr stuff working, the name is getting
> > saved properly, but the data isn't.  This is what I'm doing to write
> > the data in the dir item
> > 
> >         btrfs_set_dir_data_len(dir_item, data_len);
> >         name_ptr = (char *)(dir_item + 1);
> >         data_ptr = (char *)(name_ptr + name_len + 1);
> > 
> >         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]);
> > 
> > this keeps resulting in garbage when i try to read it off the disk.
> > What am I missing?  Thank you,
> 
> It works best to hack knowledge of your stuff into
> btrfsprogs/print-tree.c, so that debug-tree will show you what is going
> on.  But, the length of the item in the item header needs to include
> the length of the data, so my guess is that's the problem.  If you post
> the code I can take a look.
 
Right, here you go.  I account for the extra data_len for the initial item.
Here's my code in case its anything weird that I'm missing.  In the meantime
I'll fix the block accounting stuff and then come back to this.  Thank you,

Josef


diff -r d8bb3e6956c1 Makefile
--- a/Makefile	Fri Aug 24 14:11:28 2007 -0400
+++ b/Makefile	Mon Aug 27 16:16:49 2007 -0400
@@ -4,7 +4,8 @@ obj-m  := btrfs.o
 obj-m  := btrfs.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 sysfs.o
+	   transaction.o bit-radix.o inode.o file.o tree-defrag.o sysfs.o \
+	   xattr.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 d8bb3e6956c1 ctree.h
--- a/ctree.h	Fri Aug 24 14:11:28 2007 -0400
+++ b/ctree.h	Mon Aug 27 16:34:40 2007 -0400
@@ -222,6 +222,7 @@ struct btrfs_dir_item {
 	struct btrfs_disk_key location;
 	__le16 flags;
 	__le16 name_len;
+	__le16 data_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)
 {
@@ -634,6 +634,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->name_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,
@@ -1164,6 +1174,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_key *location, u8 type);
+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,
@@ -1238,4 +1257,11 @@ 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);
 #endif
diff -r d8bb3e6956c1 dir-item.c
--- a/dir-item.c	Fri Aug 24 14:11:28 2007 -0400
+++ b/dir-item.c	Mon Aug 27 16:34:22 2007 -0400
@@ -57,6 +57,51 @@ static struct btrfs_dir_item *insert_wit
 	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, struct btrfs_key *location, u8 type)
+{
+	int ret = 0;
+	struct btrfs_path *path;
+	struct btrfs_dir_item *dir_item;
+	char *name_ptr, *data_ptr;
+	struct btrfs_key key;
+	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);
+	if (IS_ERR(dir_item)) {
+		ret = PTR_ERR(dir_item);
+		if (ret == -EEXIST)
+			printk("WOOO duplicates\n");
+		goto out;
+	}
+
+	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, data_len);
+	name_ptr = (char *)(dir_item + 1);
+	data_ptr = (char *)(name_ptr + name_len + 1);
+	
+	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
 			  *root, const char *name, int name_len, u64 dir,
 			  struct btrfs_key *location, u8 type)
@@ -89,6 +134,7 @@ int btrfs_insert_dir_item(struct btrfs_t
 	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);
@@ -114,6 +160,7 @@ second_insert:
 	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]);
@@ -185,6 +232,43 @@ btrfs_lookup_dir_index_item(struct btrfs
 		return ERR_PTR(ret);
 	if (ret > 0)
 		return ERR_PTR(-ENOENT);
+	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);
 }
 
diff -r d8bb3e6956c1 inode.c
--- a/inode.c	Fri Aug 24 14:11:28 2007 -0400
+++ b/inode.c	Tue Aug 28 11:42:41 2007 -0400
@@ -2533,6 +2533,10 @@ static struct inode_operations btrfs_dir
 	.symlink	= btrfs_symlink,
 	.setattr	= btrfs_setattr,
 	.mknod		= btrfs_mknod,
+	.setxattr	= btrfs_setxattr,
+	.getxattr	= btrfs_getxattr,
+	.listxattr	= btrfs_listxattr,
+	.removexattr	= btrfs_removexattr,
 };
 
 static struct inode_operations btrfs_dir_ro_inode_operations = {
@@ -2567,6 +2571,10 @@ static struct inode_operations btrfs_fil
 	.truncate	= btrfs_truncate,
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,
+	.setxattr       = btrfs_setxattr,
+	.getxattr       = btrfs_getxattr,
+	.listxattr      = btrfs_listxattr,
+	.removexattr    = btrfs_removexattr,
 };
 
 static struct inode_operations btrfs_special_inode_operations = {



More information about the Btrfs-devel mailing list