diff options
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r-- | fs/xfs/xfs_attr.c | 139 |
1 files changed, 45 insertions, 94 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 49fac8d6db12..78de80e3caa2 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -16,8 +16,6 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/capability.h> | ||
20 | |||
21 | #include "xfs.h" | 19 | #include "xfs.h" |
22 | #include "xfs_fs.h" | 20 | #include "xfs_fs.h" |
23 | #include "xfs_types.h" | 21 | #include "xfs_types.h" |
@@ -607,12 +605,20 @@ xfs_attr_remove( | |||
607 | return xfs_attr_remove_int(dp, &xname, flags); | 605 | return xfs_attr_remove_int(dp, &xname, flags); |
608 | } | 606 | } |
609 | 607 | ||
610 | STATIC int | 608 | int |
611 | xfs_attr_list_int(xfs_attr_list_context_t *context) | 609 | xfs_attr_list_int(xfs_attr_list_context_t *context) |
612 | { | 610 | { |
613 | int error; | 611 | int error; |
614 | xfs_inode_t *dp = context->dp; | 612 | xfs_inode_t *dp = context->dp; |
615 | 613 | ||
614 | XFS_STATS_INC(xs_attr_list); | ||
615 | |||
616 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
617 | return EIO; | ||
618 | |||
619 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
620 | xfs_attr_trace_l_c("syscall start", context); | ||
621 | |||
616 | /* | 622 | /* |
617 | * Decide on what work routines to call based on the inode size. | 623 | * Decide on what work routines to call based on the inode size. |
618 | */ | 624 | */ |
@@ -625,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context) | |||
625 | } else { | 631 | } else { |
626 | error = xfs_attr_node_list(context); | 632 | error = xfs_attr_node_list(context); |
627 | } | 633 | } |
634 | |||
635 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
636 | xfs_attr_trace_l_c("syscall end", context); | ||
637 | |||
628 | return error; | 638 | return error; |
629 | } | 639 | } |
630 | 640 | ||
@@ -641,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context) | |||
641 | */ | 651 | */ |
642 | /*ARGSUSED*/ | 652 | /*ARGSUSED*/ |
643 | STATIC int | 653 | STATIC int |
644 | xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, | 654 | xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags, |
645 | char *name, int namelen, | 655 | char *name, int namelen, |
646 | int valuelen, char *value) | 656 | int valuelen, char *value) |
647 | { | 657 | { |
658 | struct attrlist *alist = (struct attrlist *)context->alist; | ||
648 | attrlist_ent_t *aep; | 659 | attrlist_ent_t *aep; |
649 | int arraytop; | 660 | int arraytop; |
650 | 661 | ||
651 | ASSERT(!(context->flags & ATTR_KERNOVAL)); | 662 | ASSERT(!(context->flags & ATTR_KERNOVAL)); |
652 | ASSERT(context->count >= 0); | 663 | ASSERT(context->count >= 0); |
653 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); | 664 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); |
654 | ASSERT(context->firstu >= sizeof(*context->alist)); | 665 | ASSERT(context->firstu >= sizeof(*alist)); |
655 | ASSERT(context->firstu <= context->bufsize); | 666 | ASSERT(context->firstu <= context->bufsize); |
656 | 667 | ||
657 | arraytop = sizeof(*context->alist) + | 668 | /* |
658 | context->count * sizeof(context->alist->al_offset[0]); | 669 | * Only list entries in the right namespace. |
670 | */ | ||
671 | if (((context->flags & ATTR_SECURE) == 0) != | ||
672 | ((flags & XFS_ATTR_SECURE) == 0)) | ||
673 | return 0; | ||
674 | if (((context->flags & ATTR_ROOT) == 0) != | ||
675 | ((flags & XFS_ATTR_ROOT) == 0)) | ||
676 | return 0; | ||
677 | |||
678 | arraytop = sizeof(*alist) + | ||
679 | context->count * sizeof(alist->al_offset[0]); | ||
659 | context->firstu -= ATTR_ENTSIZE(namelen); | 680 | context->firstu -= ATTR_ENTSIZE(namelen); |
660 | if (context->firstu < arraytop) { | 681 | if (context->firstu < arraytop) { |
661 | xfs_attr_trace_l_c("buffer full", context); | 682 | xfs_attr_trace_l_c("buffer full", context); |
662 | context->alist->al_more = 1; | 683 | alist->al_more = 1; |
663 | context->seen_enough = 1; | 684 | context->seen_enough = 1; |
664 | return 1; | 685 | return 1; |
665 | } | 686 | } |
666 | 687 | ||
667 | aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); | 688 | aep = (attrlist_ent_t *)&context->alist[context->firstu]; |
668 | aep->a_valuelen = valuelen; | 689 | aep->a_valuelen = valuelen; |
669 | memcpy(aep->a_name, name, namelen); | 690 | memcpy(aep->a_name, name, namelen); |
670 | aep->a_name[ namelen ] = 0; | 691 | aep->a_name[namelen] = 0; |
671 | context->alist->al_offset[ context->count++ ] = context->firstu; | 692 | alist->al_offset[context->count++] = context->firstu; |
672 | context->alist->al_count = context->count; | 693 | alist->al_count = context->count; |
673 | xfs_attr_trace_l_c("add", context); | 694 | xfs_attr_trace_l_c("add", context); |
674 | return 0; | 695 | return 0; |
675 | } | 696 | } |
676 | 697 | ||
677 | STATIC int | ||
678 | xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
679 | char *name, int namelen, | ||
680 | int valuelen, char *value) | ||
681 | { | ||
682 | char *offset; | ||
683 | int arraytop; | ||
684 | |||
685 | ASSERT(context->count >= 0); | ||
686 | |||
687 | arraytop = context->count + namesp->attr_namelen + namelen + 1; | ||
688 | if (arraytop > context->firstu) { | ||
689 | context->count = -1; /* insufficient space */ | ||
690 | return 1; | ||
691 | } | ||
692 | offset = (char *)context->alist + context->count; | ||
693 | strncpy(offset, namesp->attr_name, namesp->attr_namelen); | ||
694 | offset += namesp->attr_namelen; | ||
695 | strncpy(offset, name, namelen); /* real name */ | ||
696 | offset += namelen; | ||
697 | *offset = '\0'; | ||
698 | context->count += namesp->attr_namelen + namelen + 1; | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | /*ARGSUSED*/ | ||
703 | STATIC int | ||
704 | xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
705 | char *name, int namelen, | ||
706 | int valuelen, char *value) | ||
707 | { | ||
708 | context->count += namesp->attr_namelen + namelen + 1; | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | /* | 698 | /* |
713 | * Generate a list of extended attribute names and optionally | 699 | * Generate a list of extended attribute names and optionally |
714 | * also value lengths. Positive return value follows the XFS | 700 | * also value lengths. Positive return value follows the XFS |
@@ -725,10 +711,9 @@ xfs_attr_list( | |||
725 | attrlist_cursor_kern_t *cursor) | 711 | attrlist_cursor_kern_t *cursor) |
726 | { | 712 | { |
727 | xfs_attr_list_context_t context; | 713 | xfs_attr_list_context_t context; |
714 | struct attrlist *alist; | ||
728 | int error; | 715 | int error; |
729 | 716 | ||
730 | XFS_STATS_INC(xs_attr_list); | ||
731 | |||
732 | /* | 717 | /* |
733 | * Validate the cursor. | 718 | * Validate the cursor. |
734 | */ | 719 | */ |
@@ -749,52 +734,23 @@ xfs_attr_list( | |||
749 | /* | 734 | /* |
750 | * Initialize the output buffer. | 735 | * Initialize the output buffer. |
751 | */ | 736 | */ |
737 | memset(&context, 0, sizeof(context)); | ||
752 | context.dp = dp; | 738 | context.dp = dp; |
753 | context.cursor = cursor; | 739 | context.cursor = cursor; |
754 | context.count = 0; | ||
755 | context.dupcnt = 0; | ||
756 | context.resynch = 1; | 740 | context.resynch = 1; |
757 | context.flags = flags; | 741 | context.flags = flags; |
758 | context.seen_enough = 0; | 742 | context.alist = buffer; |
759 | context.alist = (attrlist_t *)buffer; | 743 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ |
760 | context.put_value = 0; | 744 | context.firstu = context.bufsize; |
761 | 745 | context.put_listent = xfs_attr_put_listent; | |
762 | if (flags & ATTR_KERNAMELS) { | ||
763 | context.bufsize = bufsize; | ||
764 | context.firstu = context.bufsize; | ||
765 | if (flags & ATTR_KERNOVAL) | ||
766 | context.put_listent = xfs_attr_kern_list_sizes; | ||
767 | else | ||
768 | context.put_listent = xfs_attr_kern_list; | ||
769 | } else { | ||
770 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ | ||
771 | context.firstu = context.bufsize; | ||
772 | context.alist->al_count = 0; | ||
773 | context.alist->al_more = 0; | ||
774 | context.alist->al_offset[0] = context.bufsize; | ||
775 | context.put_listent = xfs_attr_put_listent; | ||
776 | } | ||
777 | |||
778 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
779 | return EIO; | ||
780 | 746 | ||
781 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 747 | alist = (struct attrlist *)context.alist; |
782 | xfs_attr_trace_l_c("syscall start", &context); | 748 | alist->al_count = 0; |
749 | alist->al_more = 0; | ||
750 | alist->al_offset[0] = context.bufsize; | ||
783 | 751 | ||
784 | error = xfs_attr_list_int(&context); | 752 | error = xfs_attr_list_int(&context); |
785 | 753 | ASSERT(error >= 0); | |
786 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
787 | xfs_attr_trace_l_c("syscall end", &context); | ||
788 | |||
789 | if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) { | ||
790 | /* must return negated buffer size or the error */ | ||
791 | if (context.count < 0) | ||
792 | error = XFS_ERROR(ERANGE); | ||
793 | else | ||
794 | error = -context.count; | ||
795 | } else | ||
796 | ASSERT(error >= 0); | ||
797 | |||
798 | return error; | 754 | return error; |
799 | } | 755 | } |
800 | 756 | ||
@@ -2357,12 +2313,7 @@ xfs_attr_trace_enter(int type, char *where, | |||
2357 | (void *)((__psunsigned_t)context->bufsize), | 2313 | (void *)((__psunsigned_t)context->bufsize), |
2358 | (void *)((__psunsigned_t)context->count), | 2314 | (void *)((__psunsigned_t)context->count), |
2359 | (void *)((__psunsigned_t)context->firstu), | 2315 | (void *)((__psunsigned_t)context->firstu), |
2360 | (void *)((__psunsigned_t) | 2316 | NULL, |
2361 | (((context->count > 0) && | ||
2362 | !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) | ||
2363 | ? (ATTR_ENTRY(context->alist, | ||
2364 | context->count-1)->a_valuelen) | ||
2365 | : 0)), | ||
2366 | (void *)((__psunsigned_t)context->dupcnt), | 2317 | (void *)((__psunsigned_t)context->dupcnt), |
2367 | (void *)((__psunsigned_t)context->flags), | 2318 | (void *)((__psunsigned_t)context->flags), |
2368 | (void *)a13, (void *)a14, (void *)a15); | 2319 | (void *)a13, (void *)a14, (void *)a15); |