diff options
author | Christoph Hellwig <hch@lst.de> | 2008-08-28 06:21:16 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:07 -0400 |
commit | eaa47d8612783807ef9703ebc9bf0d0f0455bf62 (patch) | |
tree | aae589fac6573e2974935b357bfa687dbab2e718 /fs | |
parent | eab922ec8907b8c506e799785e7e2d16eabe50e4 (diff) |
btrfs: optmize listxattr
The ->list handler is really not useful at all, because we always call
btrfs_xattr_generic_list anyway. After this is done
find_btrfs_xattr_handler becomes unused, and it becomes obvious that the
temporary name buffer allocation isn't needed but we can directly copy
into the supplied buffer.
Tested with various getfattr -d calls on varying xattr lists.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/acl.c | 2 | ||||
-rw-r--r-- | fs/btrfs/xattr.c | 82 | ||||
-rw-r--r-- | fs/btrfs/xattr.h | 8 |
3 files changed, 11 insertions, 81 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index b95147ef1c77..2f865311460c 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -320,14 +320,12 @@ int btrfs_acl_chmod(struct inode *inode) | |||
320 | 320 | ||
321 | struct xattr_handler btrfs_xattr_acl_default_handler = { | 321 | struct xattr_handler btrfs_xattr_acl_default_handler = { |
322 | .prefix = POSIX_ACL_XATTR_DEFAULT, | 322 | .prefix = POSIX_ACL_XATTR_DEFAULT, |
323 | .list = btrfs_xattr_generic_list, | ||
324 | .get = btrfs_xattr_acl_default_get, | 323 | .get = btrfs_xattr_acl_default_get, |
325 | .set = btrfs_xattr_acl_default_set, | 324 | .set = btrfs_xattr_acl_default_set, |
326 | }; | 325 | }; |
327 | 326 | ||
328 | struct xattr_handler btrfs_xattr_acl_access_handler = { | 327 | struct xattr_handler btrfs_xattr_acl_access_handler = { |
329 | .prefix = POSIX_ACL_XATTR_ACCESS, | 328 | .prefix = POSIX_ACL_XATTR_ACCESS, |
330 | .list = btrfs_xattr_generic_list, | ||
331 | .get = btrfs_xattr_acl_access_get, | 329 | .get = btrfs_xattr_acl_access_get, |
332 | .set = btrfs_xattr_acl_access_set, | 330 | .set = btrfs_xattr_acl_access_set, |
333 | }; | 331 | }; |
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 | */ | ||
60 | static 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 | ||
121 | size_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 | |||
134 | ssize_t btrfs_xattr_get(struct inode *inode, int name_index, | 92 | ssize_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 | ||
413 | struct xattr_handler btrfs_xattr_security_handler = { | 357 | struct 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 | ||
420 | struct xattr_handler btrfs_xattr_system_handler = { | 363 | struct 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 | ||
427 | struct xattr_handler btrfs_xattr_user_handler = { | 369 | struct 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 | ||
434 | struct xattr_handler btrfs_xattr_trusted_handler = { | 375 | struct 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 | }; |
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index b2e47e3f2442..825e55bd4960 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h | |||
@@ -47,12 +47,4 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, const char *name, | |||
47 | int btrfs_xattr_set(struct inode *inode, int name_index, const char *name, | 47 | int btrfs_xattr_set(struct inode *inode, int name_index, const char *name, |
48 | const void *value, size_t size, int flags); | 48 | const void *value, size_t size, int flags); |
49 | 49 | ||
50 | /* | ||
51 | * the only reason this is public is for acl.c. There may be a point where | ||
52 | * acl.c doesn't need it, and if thats the case we need to remove it and make | ||
53 | * it static in xattr.c | ||
54 | */ | ||
55 | size_t btrfs_xattr_generic_list(struct inode *inode, char *list, | ||
56 | size_t list_size, const char *name, | ||
57 | size_t name_len); | ||
58 | #endif /* __XATTR__ */ | 50 | #endif /* __XATTR__ */ |