diff options
author | Eric Biggers <ebiggers3@gmail.com> | 2014-10-12 12:59:58 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-12 17:09:10 -0400 |
commit | 8cc431165d8fbda43634dd15ab17f76a151c39a8 (patch) | |
tree | 9f75709e432ec0beed0923e935b3d63d45b4b3e7 /fs/xattr.c | |
parent | 50b220bbe7092bbfe4406adfe3a216337a64655d (diff) |
vfs: Deduplicate code shared by xattr system calls operating on paths
The following pairs of system calls dealing with extended attributes only
differ in their behavior on whether the symbolic link is followed (when
the named file is a symbolic link):
- setxattr() and lsetxattr()
- getxattr() and lgetxattr()
- listxattr() and llistxattr()
- removexattr() and lremovexattr()
Despite this, the implementations all had duplicated code, so this commit
redirects each of the above pairs of system calls to a corresponding
function to which different lookup flags (LOOKUP_FOLLOW or 0) are passed.
For me this reduced the stripped size of xattr.o from 8824 to 8248 bytes.
Signed-off-by: Eric Biggers <ebiggers3@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 116 |
1 files changed, 39 insertions, 77 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index c69e6d43a0d2..64e83efb742d 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -364,13 +364,12 @@ out: | |||
364 | return error; | 364 | return error; |
365 | } | 365 | } |
366 | 366 | ||
367 | SYSCALL_DEFINE5(setxattr, const char __user *, pathname, | 367 | static int path_setxattr(const char __user *pathname, |
368 | const char __user *, name, const void __user *, value, | 368 | const char __user *name, const void __user *value, |
369 | size_t, size, int, flags) | 369 | size_t size, int flags, unsigned int lookup_flags) |
370 | { | 370 | { |
371 | struct path path; | 371 | struct path path; |
372 | int error; | 372 | int error; |
373 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
374 | retry: | 373 | retry: |
375 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | 374 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
376 | if (error) | 375 | if (error) |
@@ -388,28 +387,18 @@ retry: | |||
388 | return error; | 387 | return error; |
389 | } | 388 | } |
390 | 389 | ||
390 | SYSCALL_DEFINE5(setxattr, const char __user *, pathname, | ||
391 | const char __user *, name, const void __user *, value, | ||
392 | size_t, size, int, flags) | ||
393 | { | ||
394 | return path_setxattr(pathname, name, value, size, flags, LOOKUP_FOLLOW); | ||
395 | } | ||
396 | |||
391 | SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname, | 397 | SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname, |
392 | const char __user *, name, const void __user *, value, | 398 | const char __user *, name, const void __user *, value, |
393 | size_t, size, int, flags) | 399 | size_t, size, int, flags) |
394 | { | 400 | { |
395 | struct path path; | 401 | return path_setxattr(pathname, name, value, size, flags, 0); |
396 | int error; | ||
397 | unsigned int lookup_flags = 0; | ||
398 | retry: | ||
399 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | ||
400 | if (error) | ||
401 | return error; | ||
402 | error = mnt_want_write(path.mnt); | ||
403 | if (!error) { | ||
404 | error = setxattr(path.dentry, name, value, size, flags); | ||
405 | mnt_drop_write(path.mnt); | ||
406 | } | ||
407 | path_put(&path); | ||
408 | if (retry_estale(error, lookup_flags)) { | ||
409 | lookup_flags |= LOOKUP_REVAL; | ||
410 | goto retry; | ||
411 | } | ||
412 | return error; | ||
413 | } | 402 | } |
414 | 403 | ||
415 | SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | 404 | SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, |
@@ -481,12 +470,12 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, | |||
481 | return error; | 470 | return error; |
482 | } | 471 | } |
483 | 472 | ||
484 | SYSCALL_DEFINE4(getxattr, const char __user *, pathname, | 473 | static ssize_t path_getxattr(const char __user *pathname, |
485 | const char __user *, name, void __user *, value, size_t, size) | 474 | const char __user *name, void __user *value, |
475 | size_t size, unsigned int lookup_flags) | ||
486 | { | 476 | { |
487 | struct path path; | 477 | struct path path; |
488 | ssize_t error; | 478 | ssize_t error; |
489 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
490 | retry: | 479 | retry: |
491 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | 480 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
492 | if (error) | 481 | if (error) |
@@ -500,23 +489,16 @@ retry: | |||
500 | return error; | 489 | return error; |
501 | } | 490 | } |
502 | 491 | ||
492 | SYSCALL_DEFINE4(getxattr, const char __user *, pathname, | ||
493 | const char __user *, name, void __user *, value, size_t, size) | ||
494 | { | ||
495 | return path_getxattr(pathname, name, value, size, LOOKUP_FOLLOW); | ||
496 | } | ||
497 | |||
503 | SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname, | 498 | SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname, |
504 | const char __user *, name, void __user *, value, size_t, size) | 499 | const char __user *, name, void __user *, value, size_t, size) |
505 | { | 500 | { |
506 | struct path path; | 501 | return path_getxattr(pathname, name, value, size, 0); |
507 | ssize_t error; | ||
508 | unsigned int lookup_flags = 0; | ||
509 | retry: | ||
510 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | ||
511 | if (error) | ||
512 | return error; | ||
513 | error = getxattr(path.dentry, name, value, size); | ||
514 | path_put(&path); | ||
515 | if (retry_estale(error, lookup_flags)) { | ||
516 | lookup_flags |= LOOKUP_REVAL; | ||
517 | goto retry; | ||
518 | } | ||
519 | return error; | ||
520 | } | 502 | } |
521 | 503 | ||
522 | SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, | 504 | SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, |
@@ -571,12 +553,11 @@ listxattr(struct dentry *d, char __user *list, size_t size) | |||
571 | return error; | 553 | return error; |
572 | } | 554 | } |
573 | 555 | ||
574 | SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list, | 556 | static ssize_t path_listxattr(const char __user *pathname, char __user *list, |
575 | size_t, size) | 557 | size_t size, unsigned int lookup_flags) |
576 | { | 558 | { |
577 | struct path path; | 559 | struct path path; |
578 | ssize_t error; | 560 | ssize_t error; |
579 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
580 | retry: | 561 | retry: |
581 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | 562 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
582 | if (error) | 563 | if (error) |
@@ -590,23 +571,16 @@ retry: | |||
590 | return error; | 571 | return error; |
591 | } | 572 | } |
592 | 573 | ||
574 | SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list, | ||
575 | size_t, size) | ||
576 | { | ||
577 | return path_listxattr(pathname, list, size, LOOKUP_FOLLOW); | ||
578 | } | ||
579 | |||
593 | SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list, | 580 | SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list, |
594 | size_t, size) | 581 | size_t, size) |
595 | { | 582 | { |
596 | struct path path; | 583 | return path_listxattr(pathname, list, size, 0); |
597 | ssize_t error; | ||
598 | unsigned int lookup_flags = 0; | ||
599 | retry: | ||
600 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | ||
601 | if (error) | ||
602 | return error; | ||
603 | error = listxattr(path.dentry, list, size); | ||
604 | path_put(&path); | ||
605 | if (retry_estale(error, lookup_flags)) { | ||
606 | lookup_flags |= LOOKUP_REVAL; | ||
607 | goto retry; | ||
608 | } | ||
609 | return error; | ||
610 | } | 584 | } |
611 | 585 | ||
612 | SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) | 586 | SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) |
@@ -640,12 +614,11 @@ removexattr(struct dentry *d, const char __user *name) | |||
640 | return vfs_removexattr(d, kname); | 614 | return vfs_removexattr(d, kname); |
641 | } | 615 | } |
642 | 616 | ||
643 | SYSCALL_DEFINE2(removexattr, const char __user *, pathname, | 617 | static int path_removexattr(const char __user *pathname, |
644 | const char __user *, name) | 618 | const char __user *name, unsigned int lookup_flags) |
645 | { | 619 | { |
646 | struct path path; | 620 | struct path path; |
647 | int error; | 621 | int error; |
648 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
649 | retry: | 622 | retry: |
650 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | 623 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
651 | if (error) | 624 | if (error) |
@@ -663,27 +636,16 @@ retry: | |||
663 | return error; | 636 | return error; |
664 | } | 637 | } |
665 | 638 | ||
639 | SYSCALL_DEFINE2(removexattr, const char __user *, pathname, | ||
640 | const char __user *, name) | ||
641 | { | ||
642 | return path_removexattr(pathname, name, LOOKUP_FOLLOW); | ||
643 | } | ||
644 | |||
666 | SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname, | 645 | SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname, |
667 | const char __user *, name) | 646 | const char __user *, name) |
668 | { | 647 | { |
669 | struct path path; | 648 | return path_removexattr(pathname, name, 0); |
670 | int error; | ||
671 | unsigned int lookup_flags = 0; | ||
672 | retry: | ||
673 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | ||
674 | if (error) | ||
675 | return error; | ||
676 | error = mnt_want_write(path.mnt); | ||
677 | if (!error) { | ||
678 | error = removexattr(path.dentry, name); | ||
679 | mnt_drop_write(path.mnt); | ||
680 | } | ||
681 | path_put(&path); | ||
682 | if (retry_estale(error, lookup_flags)) { | ||
683 | lookup_flags |= LOOKUP_REVAL; | ||
684 | goto retry; | ||
685 | } | ||
686 | return error; | ||
687 | } | 649 | } |
688 | 650 | ||
689 | SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | 651 | SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) |