[Btrfs-devel] [PATCH 2/4] supporting code to add xattr support
Josef Bacik
jbacik at redhat.com
Wed Nov 7 18:06:54 PST 2007
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);
More information about the Btrfs-devel
mailing list