diff options
author | Josef Bacik <jbacik@redhat.com> | 2007-11-16 11:45:54 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 5103e947b9b7ac18ddb21a04ee3486e94c6504d7 (patch) | |
tree | 5d7c0c9ce1d57b988165f87c7bae304cb339589c /fs/btrfs/dir-item.c | |
parent | 0591fb56fb732c7bf500d1446d0bf927046d7002 (diff) |
xattr support for btrfs
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/dir-item.c')
-rw-r--r-- | fs/btrfs/dir-item.c | 100 |
1 files changed, 94 insertions, 6 deletions
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 514a1dc337a8..ddbe12ae0d63 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -43,8 +43,6 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle | |||
43 | return ERR_PTR(-EEXIST); | 43 | return ERR_PTR(-EEXIST); |
44 | ret = btrfs_extend_item(trans, root, path, data_size); | 44 | ret = btrfs_extend_item(trans, root, path, data_size); |
45 | WARN_ON(ret > 0); | 45 | WARN_ON(ret > 0); |
46 | if (ret) | ||
47 | return ERR_PTR(ret); | ||
48 | } | 46 | } |
49 | if (ret < 0) | 47 | if (ret < 0) |
50 | return ERR_PTR(ret); | 48 | return ERR_PTR(ret); |
@@ -57,6 +55,57 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle | |||
57 | return (struct btrfs_dir_item *)ptr; | 55 | return (struct btrfs_dir_item *)ptr; |
58 | } | 56 | } |
59 | 57 | ||
58 | int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, | ||
59 | struct btrfs_root *root, const char *name, | ||
60 | u16 name_len, const void *data, u16 data_len, | ||
61 | u64 dir) | ||
62 | { | ||
63 | int ret = 0; | ||
64 | struct btrfs_path *path; | ||
65 | struct btrfs_dir_item *dir_item; | ||
66 | unsigned long name_ptr, data_ptr; | ||
67 | struct btrfs_key key, location; | ||
68 | struct btrfs_disk_key disk_key; | ||
69 | struct extent_buffer *leaf; | ||
70 | u32 data_size; | ||
71 | |||
72 | key.objectid = dir; | ||
73 | btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); | ||
74 | ret = btrfs_name_hash(name, name_len, &key.offset); | ||
75 | BUG_ON(ret); | ||
76 | path = btrfs_alloc_path(); | ||
77 | if (!path) | ||
78 | return -ENOMEM; | ||
79 | |||
80 | data_size = sizeof(*dir_item) + name_len + data_len; | ||
81 | dir_item = insert_with_overflow(trans, root, path, &key, data_size, | ||
82 | name, name_len); | ||
83 | /* | ||
84 | * FIXME: at some point we should handle xattr's that are larger than | ||
85 | * what we can fit in our leaf. We set location to NULL b/c we arent | ||
86 | * pointing at anything else, that will change if we store the xattr | ||
87 | * data in a separate inode. | ||
88 | */ | ||
89 | BUG_ON(IS_ERR(dir_item)); | ||
90 | memset(&location, 0, sizeof(location)); | ||
91 | |||
92 | leaf = path->nodes[0]; | ||
93 | btrfs_cpu_key_to_disk(&disk_key, &location); | ||
94 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); | ||
95 | btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR); | ||
96 | btrfs_set_dir_name_len(leaf, dir_item, name_len); | ||
97 | btrfs_set_dir_data_len(leaf, dir_item, data_len); | ||
98 | name_ptr = (unsigned long)(dir_item + 1); | ||
99 | data_ptr = (unsigned long)((char *)name_ptr + name_len); | ||
100 | |||
101 | write_extent_buffer(leaf, name, name_ptr, name_len); | ||
102 | write_extent_buffer(leaf, data, data_ptr, data_len); | ||
103 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
104 | |||
105 | btrfs_free_path(path); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
60 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 109 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
61 | *root, const char *name, int name_len, u64 dir, | 110 | *root, const char *name, int name_len, u64 dir, |
62 | struct btrfs_key *location, u8 type) | 111 | struct btrfs_key *location, u8 type) |
@@ -90,7 +139,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
90 | btrfs_cpu_key_to_disk(&disk_key, location); | 139 | btrfs_cpu_key_to_disk(&disk_key, location); |
91 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); | 140 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); |
92 | btrfs_set_dir_type(leaf, dir_item, type); | 141 | btrfs_set_dir_type(leaf, dir_item, type); |
93 | btrfs_set_dir_flags(leaf, dir_item, 0); | 142 | btrfs_set_dir_data_len(leaf, dir_item, 0); |
94 | btrfs_set_dir_name_len(leaf, dir_item, name_len); | 143 | btrfs_set_dir_name_len(leaf, dir_item, name_len); |
95 | name_ptr = (unsigned long)(dir_item + 1); | 144 | name_ptr = (unsigned long)(dir_item + 1); |
96 | 145 | ||
@@ -117,7 +166,7 @@ second_insert: | |||
117 | btrfs_cpu_key_to_disk(&disk_key, location); | 166 | btrfs_cpu_key_to_disk(&disk_key, location); |
118 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); | 167 | btrfs_set_dir_item_key(leaf, dir_item, &disk_key); |
119 | btrfs_set_dir_type(leaf, dir_item, type); | 168 | btrfs_set_dir_type(leaf, dir_item, type); |
120 | btrfs_set_dir_flags(leaf, dir_item, 0); | 169 | btrfs_set_dir_data_len(leaf, dir_item, 0); |
121 | btrfs_set_dir_name_len(leaf, dir_item, name_len); | 170 | btrfs_set_dir_name_len(leaf, dir_item, name_len); |
122 | name_ptr = (unsigned long)(dir_item + 1); | 171 | name_ptr = (unsigned long)(dir_item + 1); |
123 | write_extent_buffer(leaf, name, name_ptr, name_len); | 172 | write_extent_buffer(leaf, name, name_ptr, name_len); |
@@ -194,6 +243,43 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | |||
194 | return btrfs_match_dir_item_name(root, path, name, name_len); | 243 | return btrfs_match_dir_item_name(root, path, name, name_len); |
195 | } | 244 | } |
196 | 245 | ||
246 | struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, | ||
247 | struct btrfs_root *root, | ||
248 | struct btrfs_path *path, u64 dir, | ||
249 | const char *name, u16 name_len, | ||
250 | int mod) | ||
251 | { | ||
252 | int ret; | ||
253 | struct btrfs_key key; | ||
254 | int ins_len = mod < 0 ? -1 : 0; | ||
255 | int cow = mod != 0; | ||
256 | struct btrfs_key found_key; | ||
257 | struct extent_buffer *leaf; | ||
258 | |||
259 | key.objectid = dir; | ||
260 | btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); | ||
261 | ret = btrfs_name_hash(name, name_len, &key.offset); | ||
262 | BUG_ON(ret); | ||
263 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | ||
264 | if (ret < 0) | ||
265 | return ERR_PTR(ret); | ||
266 | if (ret > 0) { | ||
267 | if (path->slots[0] == 0) | ||
268 | return NULL; | ||
269 | path->slots[0]--; | ||
270 | } | ||
271 | |||
272 | leaf = path->nodes[0]; | ||
273 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
274 | |||
275 | if (found_key.objectid != dir || | ||
276 | btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY || | ||
277 | found_key.offset != key.offset) | ||
278 | return NULL; | ||
279 | |||
280 | return btrfs_match_dir_item_name(root, path, name, name_len); | ||
281 | } | ||
282 | |||
197 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | 283 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, |
198 | struct btrfs_path *path, | 284 | struct btrfs_path *path, |
199 | const char *name, int name_len) | 285 | const char *name, int name_len) |
@@ -210,7 +296,8 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | |||
210 | total_len = btrfs_item_size_nr(leaf, path->slots[0]); | 296 | total_len = btrfs_item_size_nr(leaf, path->slots[0]); |
211 | while(cur < total_len) { | 297 | while(cur < total_len) { |
212 | this_len = sizeof(*dir_item) + | 298 | this_len = sizeof(*dir_item) + |
213 | btrfs_dir_name_len(leaf, dir_item); | 299 | btrfs_dir_name_len(leaf, dir_item) + |
300 | btrfs_dir_data_len(leaf, dir_item); | ||
214 | name_ptr = (unsigned long)(dir_item + 1); | 301 | name_ptr = (unsigned long)(dir_item + 1); |
215 | 302 | ||
216 | if (btrfs_dir_name_len(leaf, dir_item) == name_len && | 303 | if (btrfs_dir_name_len(leaf, dir_item) == name_len && |
@@ -236,7 +323,8 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
236 | int ret = 0; | 323 | int ret = 0; |
237 | 324 | ||
238 | leaf = path->nodes[0]; | 325 | leaf = path->nodes[0]; |
239 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di); | 326 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) + |
327 | btrfs_dir_data_len(leaf, di); | ||
240 | item_len = btrfs_item_size_nr(leaf, path->slots[0]); | 328 | item_len = btrfs_item_size_nr(leaf, path->slots[0]); |
241 | if (sub_item_len == item_len) { | 329 | if (sub_item_len == item_len) { |
242 | ret = btrfs_del_item(trans, root, path); | 330 | ret = btrfs_del_item(trans, root, path); |