aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r--fs/btrfs/xattr.c82
1 files changed, 11 insertions, 71 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 121c9550314f..fdfece41dd16 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -51,35 +51,6 @@ struct xattr_handler *btrfs_xattr_handlers[] = {
51}; 51};
52 52
53/* 53/*
54 * @param name - the xattr name
55 * @return - the xattr_handler for the xattr, NULL if its not found
56 *
57 * use this with listxattr where we don't already know the type of xattr we
58 * have
59 */
60static struct xattr_handler *find_btrfs_xattr_handler(struct extent_buffer *l,
61 unsigned long name_ptr,
62 u16 name_len)
63{
64 struct xattr_handler *handler = NULL;
65 int i = 0;
66
67 for (handler = btrfs_xattr_handlers[i]; handler != NULL; i++,
68 handler = btrfs_xattr_handlers[i]) {
69 u16 prefix_len = strlen(handler->prefix);
70
71 if (name_len < prefix_len)
72 continue;
73
74 if (memcmp_extent_buffer(l, handler->prefix, name_ptr,
75 prefix_len) == 0)
76 break;
77 }
78
79 return handler;
80}
81
82/*
83 * @param name_index - the index for the xattr handler 54 * @param name_index - the index for the xattr handler
84 * @return the xattr_handler if we found it, NULL otherwise 55 * @return the xattr_handler if we found it, NULL otherwise
85 * 56 *
@@ -118,19 +89,6 @@ static inline char *get_name(const char *name, int name_index)
118 return ret; 89 return ret;
119} 90}
120 91
121size_t btrfs_xattr_generic_list(struct inode *inode, char *list,
122 size_t list_size, const char *name,
123 size_t name_len)
124{
125 if (list && (name_len+1) <= list_size) {
126 memcpy(list, name, name_len);
127 list[name_len] = '\0';
128 } else
129 return -ERANGE;
130
131 return name_len+1;
132}
133
134ssize_t btrfs_xattr_get(struct inode *inode, int name_index, 92ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
135 const char *attr_name, void *buffer, size_t size) 93 const char *attr_name, void *buffer, size_t size)
136{ 94{
@@ -278,11 +236,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
278 struct btrfs_item *item; 236 struct btrfs_item *item;
279 struct extent_buffer *leaf; 237 struct extent_buffer *leaf;
280 struct btrfs_dir_item *di; 238 struct btrfs_dir_item *di;
281 struct xattr_handler *handler;
282 int ret = 0, slot, advance; 239 int ret = 0, slot, advance;
283 size_t total_size = 0, size_left = size, written; 240 size_t total_size = 0, size_left = size;
284 unsigned long name_ptr; 241 unsigned long name_ptr;
285 char *name; 242 size_t name_len;
286 u32 nritems; 243 u32 nritems;
287 244
288 /* 245 /*
@@ -344,37 +301,24 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
344 301
345 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 302 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
346 303
347 total_size += btrfs_dir_name_len(leaf, di)+1; 304 name_len = btrfs_dir_name_len(leaf, di);
305 total_size += name_len + 1;
348 306
349 /* we are just looking for how big our buffer needs to be */ 307 /* we are just looking for how big our buffer needs to be */
350 if (!size) 308 if (!size)
351 continue; 309 continue;
352 310
353 /* find our handler for this xattr */ 311 if (!buffer || (name_len + 1) > size_left) {
354 name_ptr = (unsigned long)(di + 1);
355 handler = find_btrfs_xattr_handler(leaf, name_ptr,
356 btrfs_dir_name_len(leaf, di));
357 if (!handler) {
358 printk(KERN_ERR "btrfs: unsupported xattr found\n");
359 continue;
360 }
361
362 name = kmalloc(btrfs_dir_name_len(leaf, di), GFP_KERNEL);
363 read_extent_buffer(leaf, name, name_ptr,
364 btrfs_dir_name_len(leaf, di));
365
366 /* call the list function associated with this xattr */
367 written = handler->list(inode, buffer, size_left, name,
368 btrfs_dir_name_len(leaf, di));
369 kfree(name);
370
371 if (written < 0) {
372 ret = -ERANGE; 312 ret = -ERANGE;
373 break; 313 break;
374 } 314 }
375 315
376 size_left -= written; 316 name_ptr = (unsigned long)(di + 1);
377 buffer += written; 317 read_extent_buffer(leaf, buffer, name_ptr, name_len);
318 buffer[name_len] = '\0';
319
320 size_left -= name_len + 1;
321 buffer += name_len + 1;
378 } 322 }
379 ret = total_size; 323 ret = total_size;
380 324
@@ -412,28 +356,24 @@ BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED);
412 356
413struct xattr_handler btrfs_xattr_security_handler = { 357struct xattr_handler btrfs_xattr_security_handler = {
414 .prefix = XATTR_SECURITY_PREFIX, 358 .prefix = XATTR_SECURITY_PREFIX,
415 .list = btrfs_xattr_generic_list,
416 .get = btrfs_xattr_security_get, 359 .get = btrfs_xattr_security_get,
417 .set = btrfs_xattr_security_set, 360 .set = btrfs_xattr_security_set,
418}; 361};
419 362
420struct xattr_handler btrfs_xattr_system_handler = { 363struct xattr_handler btrfs_xattr_system_handler = {
421 .prefix = XATTR_SYSTEM_PREFIX, 364 .prefix = XATTR_SYSTEM_PREFIX,
422 .list = btrfs_xattr_generic_list,
423 .get = btrfs_xattr_system_get, 365 .get = btrfs_xattr_system_get,
424 .set = btrfs_xattr_system_set, 366 .set = btrfs_xattr_system_set,
425}; 367};
426 368
427struct xattr_handler btrfs_xattr_user_handler = { 369struct xattr_handler btrfs_xattr_user_handler = {
428 .prefix = XATTR_USER_PREFIX, 370 .prefix = XATTR_USER_PREFIX,
429 .list = btrfs_xattr_generic_list,
430 .get = btrfs_xattr_user_get, 371 .get = btrfs_xattr_user_get,
431 .set = btrfs_xattr_user_set, 372 .set = btrfs_xattr_user_set,
432}; 373};
433 374
434struct xattr_handler btrfs_xattr_trusted_handler = { 375struct xattr_handler btrfs_xattr_trusted_handler = {
435 .prefix = XATTR_TRUSTED_PREFIX, 376 .prefix = XATTR_TRUSTED_PREFIX,
436 .list = btrfs_xattr_generic_list,
437 .get = btrfs_xattr_trusted_get, 377 .get = btrfs_xattr_trusted_get,
438 .set = btrfs_xattr_trusted_set, 378 .set = btrfs_xattr_trusted_set,
439}; 379};