aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r--fs/xfs/xfs_attr.c608
1 files changed, 92 insertions, 516 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index df151a859186..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"
@@ -57,11 +55,6 @@
57 * Provide the external interfaces to manage attribute lists. 55 * Provide the external interfaces to manage attribute lists.
58 */ 56 */
59 57
60#define ATTR_SYSCOUNT 2
61static struct attrnames posix_acl_access;
62static struct attrnames posix_acl_default;
63static struct attrnames *attr_system_names[ATTR_SYSCOUNT];
64
65/*======================================================================== 58/*========================================================================
66 * Function prototypes for the kernel. 59 * Function prototypes for the kernel.
67 *========================================================================*/ 60 *========================================================================*/
@@ -116,6 +109,17 @@ xfs_attr_name_to_xname(
116 return 0; 109 return 0;
117} 110}
118 111
112STATIC int
113xfs_inode_hasattr(
114 struct xfs_inode *ip)
115{
116 if (!XFS_IFORK_Q(ip) ||
117 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
118 ip->i_d.di_anextents == 0))
119 return 0;
120 return 1;
121}
122
119/*======================================================================== 123/*========================================================================
120 * Overall external interface routines. 124 * Overall external interface routines.
121 *========================================================================*/ 125 *========================================================================*/
@@ -127,10 +131,8 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
127 xfs_da_args_t args; 131 xfs_da_args_t args;
128 int error; 132 int error;
129 133
130 if ((XFS_IFORK_Q(ip) == 0) || 134 if (!xfs_inode_hasattr(ip))
131 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 135 return ENOATTR;
132 ip->i_d.di_anextents == 0))
133 return(ENOATTR);
134 136
135 /* 137 /*
136 * Fill in the arg structure for this request. 138 * Fill in the arg structure for this request.
@@ -148,11 +150,7 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
148 /* 150 /*
149 * Decide on what work routines to call based on the inode size. 151 * Decide on what work routines to call based on the inode size.
150 */ 152 */
151 if (XFS_IFORK_Q(ip) == 0 || 153 if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
152 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
153 ip->i_d.di_anextents == 0)) {
154 error = XFS_ERROR(ENOATTR);
155 } else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
156 error = xfs_attr_shortform_getvalue(&args); 154 error = xfs_attr_shortform_getvalue(&args);
157 } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { 155 } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
158 error = xfs_attr_leaf_get(&args); 156 error = xfs_attr_leaf_get(&args);
@@ -241,8 +239,7 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
241 args.firstblock = &firstblock; 239 args.firstblock = &firstblock;
242 args.flist = &flist; 240 args.flist = &flist;
243 args.whichfork = XFS_ATTR_FORK; 241 args.whichfork = XFS_ATTR_FORK;
244 args.addname = 1; 242 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
245 args.oknoent = 1;
246 243
247 /* 244 /*
248 * Determine space new attribute will use, and if it would be 245 * Determine space new attribute will use, and if it would be
@@ -529,9 +526,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
529 /* 526 /*
530 * Decide on what work routines to call based on the inode size. 527 * Decide on what work routines to call based on the inode size.
531 */ 528 */
532 if (XFS_IFORK_Q(dp) == 0 || 529 if (!xfs_inode_hasattr(dp)) {
533 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
534 dp->i_d.di_anextents == 0)) {
535 error = XFS_ERROR(ENOATTR); 530 error = XFS_ERROR(ENOATTR);
536 goto out; 531 goto out;
537 } 532 }
@@ -601,29 +596,33 @@ xfs_attr_remove(
601 return error; 596 return error;
602 597
603 xfs_ilock(dp, XFS_ILOCK_SHARED); 598 xfs_ilock(dp, XFS_ILOCK_SHARED);
604 if (XFS_IFORK_Q(dp) == 0 || 599 if (!xfs_inode_hasattr(dp)) {
605 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
606 dp->i_d.di_anextents == 0)) {
607 xfs_iunlock(dp, XFS_ILOCK_SHARED); 600 xfs_iunlock(dp, XFS_ILOCK_SHARED);
608 return(XFS_ERROR(ENOATTR)); 601 return XFS_ERROR(ENOATTR);
609 } 602 }
610 xfs_iunlock(dp, XFS_ILOCK_SHARED); 603 xfs_iunlock(dp, XFS_ILOCK_SHARED);
611 604
612 return xfs_attr_remove_int(dp, &xname, flags); 605 return xfs_attr_remove_int(dp, &xname, flags);
613} 606}
614 607
615STATIC int 608int
616xfs_attr_list_int(xfs_attr_list_context_t *context) 609xfs_attr_list_int(xfs_attr_list_context_t *context)
617{ 610{
618 int error; 611 int error;
619 xfs_inode_t *dp = context->dp; 612 xfs_inode_t *dp = context->dp;
620 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
621 /* 622 /*
622 * 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.
623 */ 624 */
624 if (XFS_IFORK_Q(dp) == 0 || 625 if (!xfs_inode_hasattr(dp)) {
625 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
626 dp->i_d.di_anextents == 0)) {
627 error = 0; 626 error = 0;
628 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 627 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
629 error = xfs_attr_shortform_list(context); 628 error = xfs_attr_shortform_list(context);
@@ -632,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
632 } else { 631 } else {
633 error = xfs_attr_node_list(context); 632 error = xfs_attr_node_list(context);
634 } 633 }
634
635 xfs_iunlock(dp, XFS_ILOCK_SHARED);
636 xfs_attr_trace_l_c("syscall end", context);
637
635 return error; 638 return error;
636} 639}
637 640
@@ -648,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
648 */ 651 */
649/*ARGSUSED*/ 652/*ARGSUSED*/
650STATIC int 653STATIC int
651xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, 654xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags,
652 char *name, int namelen, 655 char *name, int namelen,
653 int valuelen, char *value) 656 int valuelen, char *value)
654{ 657{
658 struct attrlist *alist = (struct attrlist *)context->alist;
655 attrlist_ent_t *aep; 659 attrlist_ent_t *aep;
656 int arraytop; 660 int arraytop;
657 661
658 ASSERT(!(context->flags & ATTR_KERNOVAL)); 662 ASSERT(!(context->flags & ATTR_KERNOVAL));
659 ASSERT(context->count >= 0); 663 ASSERT(context->count >= 0);
660 ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); 664 ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
661 ASSERT(context->firstu >= sizeof(*context->alist)); 665 ASSERT(context->firstu >= sizeof(*alist));
662 ASSERT(context->firstu <= context->bufsize); 666 ASSERT(context->firstu <= context->bufsize);
663 667
664 arraytop = sizeof(*context->alist) + 668 /*
665 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]);
666 context->firstu -= ATTR_ENTSIZE(namelen); 680 context->firstu -= ATTR_ENTSIZE(namelen);
667 if (context->firstu < arraytop) { 681 if (context->firstu < arraytop) {
668 xfs_attr_trace_l_c("buffer full", context); 682 xfs_attr_trace_l_c("buffer full", context);
669 context->alist->al_more = 1; 683 alist->al_more = 1;
670 context->seen_enough = 1; 684 context->seen_enough = 1;
671 return 1; 685 return 1;
672 } 686 }
673 687
674 aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); 688 aep = (attrlist_ent_t *)&context->alist[context->firstu];
675 aep->a_valuelen = valuelen; 689 aep->a_valuelen = valuelen;
676 memcpy(aep->a_name, name, namelen); 690 memcpy(aep->a_name, name, namelen);
677 aep->a_name[ namelen ] = 0; 691 aep->a_name[namelen] = 0;
678 context->alist->al_offset[ context->count++ ] = context->firstu; 692 alist->al_offset[context->count++] = context->firstu;
679 context->alist->al_count = context->count; 693 alist->al_count = context->count;
680 xfs_attr_trace_l_c("add", context); 694 xfs_attr_trace_l_c("add", context);
681 return 0; 695 return 0;
682} 696}
683 697
684STATIC int
685xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
686 char *name, int namelen,
687 int valuelen, char *value)
688{
689 char *offset;
690 int arraytop;
691
692 ASSERT(context->count >= 0);
693
694 arraytop = context->count + namesp->attr_namelen + namelen + 1;
695 if (arraytop > context->firstu) {
696 context->count = -1; /* insufficient space */
697 return 1;
698 }
699 offset = (char *)context->alist + context->count;
700 strncpy(offset, namesp->attr_name, namesp->attr_namelen);
701 offset += namesp->attr_namelen;
702 strncpy(offset, name, namelen); /* real name */
703 offset += namelen;
704 *offset = '\0';
705 context->count += namesp->attr_namelen + namelen + 1;
706 return 0;
707}
708
709/*ARGSUSED*/
710STATIC int
711xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
712 char *name, int namelen,
713 int valuelen, char *value)
714{
715 context->count += namesp->attr_namelen + namelen + 1;
716 return 0;
717}
718
719/* 698/*
720 * Generate a list of extended attribute names and optionally 699 * Generate a list of extended attribute names and optionally
721 * also value lengths. Positive return value follows the XFS 700 * also value lengths. Positive return value follows the XFS
@@ -732,10 +711,9 @@ xfs_attr_list(
732 attrlist_cursor_kern_t *cursor) 711 attrlist_cursor_kern_t *cursor)
733{ 712{
734 xfs_attr_list_context_t context; 713 xfs_attr_list_context_t context;
714 struct attrlist *alist;
735 int error; 715 int error;
736 716
737 XFS_STATS_INC(xs_attr_list);
738
739 /* 717 /*
740 * Validate the cursor. 718 * Validate the cursor.
741 */ 719 */
@@ -756,52 +734,23 @@ xfs_attr_list(
756 /* 734 /*
757 * Initialize the output buffer. 735 * Initialize the output buffer.
758 */ 736 */
737 memset(&context, 0, sizeof(context));
759 context.dp = dp; 738 context.dp = dp;
760 context.cursor = cursor; 739 context.cursor = cursor;
761 context.count = 0;
762 context.dupcnt = 0;
763 context.resynch = 1; 740 context.resynch = 1;
764 context.flags = flags; 741 context.flags = flags;
765 context.seen_enough = 0; 742 context.alist = buffer;
766 context.alist = (attrlist_t *)buffer; 743 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
767 context.put_value = 0; 744 context.firstu = context.bufsize;
768 745 context.put_listent = xfs_attr_put_listent;
769 if (flags & ATTR_KERNAMELS) {
770 context.bufsize = bufsize;
771 context.firstu = context.bufsize;
772 if (flags & ATTR_KERNOVAL)
773 context.put_listent = xfs_attr_kern_list_sizes;
774 else
775 context.put_listent = xfs_attr_kern_list;
776 } else {
777 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
778 context.firstu = context.bufsize;
779 context.alist->al_count = 0;
780 context.alist->al_more = 0;
781 context.alist->al_offset[0] = context.bufsize;
782 context.put_listent = xfs_attr_put_listent;
783 }
784 746
785 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 747 alist = (struct attrlist *)context.alist;
786 return EIO; 748 alist->al_count = 0;
787 749 alist->al_more = 0;
788 xfs_ilock(dp, XFS_ILOCK_SHARED); 750 alist->al_offset[0] = context.bufsize;
789 xfs_attr_trace_l_c("syscall start", &context);
790 751
791 error = xfs_attr_list_int(&context); 752 error = xfs_attr_list_int(&context);
792 753 ASSERT(error >= 0);
793 xfs_iunlock(dp, XFS_ILOCK_SHARED);
794 xfs_attr_trace_l_c("syscall end", &context);
795
796 if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
797 /* must return negated buffer size or the error */
798 if (context.count < 0)
799 error = XFS_ERROR(ERANGE);
800 else
801 error = -context.count;
802 } else
803 ASSERT(error >= 0);
804
805 return error; 754 return error;
806} 755}
807 756
@@ -816,12 +765,10 @@ xfs_attr_inactive(xfs_inode_t *dp)
816 ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); 765 ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
817 766
818 xfs_ilock(dp, XFS_ILOCK_SHARED); 767 xfs_ilock(dp, XFS_ILOCK_SHARED);
819 if ((XFS_IFORK_Q(dp) == 0) || 768 if (!xfs_inode_hasattr(dp) ||
820 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 769 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
821 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
822 dp->i_d.di_anextents == 0)) {
823 xfs_iunlock(dp, XFS_ILOCK_SHARED); 770 xfs_iunlock(dp, XFS_ILOCK_SHARED);
824 return(0); 771 return 0;
825 } 772 }
826 xfs_iunlock(dp, XFS_ILOCK_SHARED); 773 xfs_iunlock(dp, XFS_ILOCK_SHARED);
827 774
@@ -854,10 +801,8 @@ xfs_attr_inactive(xfs_inode_t *dp)
854 /* 801 /*
855 * Decide on what work routines to call based on the inode size. 802 * Decide on what work routines to call based on the inode size.
856 */ 803 */
857 if ((XFS_IFORK_Q(dp) == 0) || 804 if (!xfs_inode_hasattr(dp) ||
858 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 805 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
859 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
860 dp->i_d.di_anextents == 0)) {
861 error = 0; 806 error = 0;
862 goto out; 807 goto out;
863 } 808 }
@@ -974,7 +919,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
974 xfs_da_brelse(args->trans, bp); 919 xfs_da_brelse(args->trans, bp);
975 return(retval); 920 return(retval);
976 } 921 }
977 args->rename = 1; /* an atomic rename */ 922 args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */
978 args->blkno2 = args->blkno; /* set 2nd entry info*/ 923 args->blkno2 = args->blkno; /* set 2nd entry info*/
979 args->index2 = args->index; 924 args->index2 = args->index;
980 args->rmtblkno2 = args->rmtblkno; 925 args->rmtblkno2 = args->rmtblkno;
@@ -1054,7 +999,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1054 * so that one disappears and one appears atomically. Then we 999 * so that one disappears and one appears atomically. Then we
1055 * must remove the "old" attribute/value pair. 1000 * must remove the "old" attribute/value pair.
1056 */ 1001 */
1057 if (args->rename) { 1002 if (args->op_flags & XFS_DA_OP_RENAME) {
1058 /* 1003 /*
1059 * In a separate transaction, set the incomplete flag on the 1004 * In a separate transaction, set the incomplete flag on the
1060 * "old" attr and clear the incomplete flag on the "new" attr. 1005 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -1307,7 +1252,7 @@ restart:
1307 } else if (retval == EEXIST) { 1252 } else if (retval == EEXIST) {
1308 if (args->flags & ATTR_CREATE) 1253 if (args->flags & ATTR_CREATE)
1309 goto out; 1254 goto out;
1310 args->rename = 1; /* atomic rename op */ 1255 args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */
1311 args->blkno2 = args->blkno; /* set 2nd entry info*/ 1256 args->blkno2 = args->blkno; /* set 2nd entry info*/
1312 args->index2 = args->index; 1257 args->index2 = args->index;
1313 args->rmtblkno2 = args->rmtblkno; 1258 args->rmtblkno2 = args->rmtblkno;
@@ -1425,7 +1370,7 @@ restart:
1425 * so that one disappears and one appears atomically. Then we 1370 * so that one disappears and one appears atomically. Then we
1426 * must remove the "old" attribute/value pair. 1371 * must remove the "old" attribute/value pair.
1427 */ 1372 */
1428 if (args->rename) { 1373 if (args->op_flags & XFS_DA_OP_RENAME) {
1429 /* 1374 /*
1430 * In a separate transaction, set the incomplete flag on the 1375 * In a separate transaction, set the incomplete flag on the
1431 * "old" attr and clear the incomplete flag on the "new" attr. 1376 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -2300,23 +2245,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2300void 2245void
2301xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) 2246xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context)
2302{ 2247{
2303 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, 2248 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, context,
2304 (__psunsigned_t)context->dp,
2305 (__psunsigned_t)context->cursor->hashval,
2306 (__psunsigned_t)context->cursor->blkno,
2307 (__psunsigned_t)context->cursor->offset,
2308 (__psunsigned_t)context->alist,
2309 (__psunsigned_t)context->bufsize,
2310 (__psunsigned_t)context->count,
2311 (__psunsigned_t)context->firstu,
2312 (__psunsigned_t)
2313 ((context->count > 0) &&
2314 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2315 ? (ATTR_ENTRY(context->alist,
2316 context->count-1)->a_valuelen)
2317 : 0,
2318 (__psunsigned_t)context->dupcnt,
2319 (__psunsigned_t)context->flags,
2320 (__psunsigned_t)NULL, 2249 (__psunsigned_t)NULL,
2321 (__psunsigned_t)NULL, 2250 (__psunsigned_t)NULL,
2322 (__psunsigned_t)NULL); 2251 (__psunsigned_t)NULL);
@@ -2329,23 +2258,7 @@ void
2329xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, 2258xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
2330 struct xfs_da_intnode *node) 2259 struct xfs_da_intnode *node)
2331{ 2260{
2332 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, 2261 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, context,
2333 (__psunsigned_t)context->dp,
2334 (__psunsigned_t)context->cursor->hashval,
2335 (__psunsigned_t)context->cursor->blkno,
2336 (__psunsigned_t)context->cursor->offset,
2337 (__psunsigned_t)context->alist,
2338 (__psunsigned_t)context->bufsize,
2339 (__psunsigned_t)context->count,
2340 (__psunsigned_t)context->firstu,
2341 (__psunsigned_t)
2342 ((context->count > 0) &&
2343 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2344 ? (ATTR_ENTRY(context->alist,
2345 context->count-1)->a_valuelen)
2346 : 0,
2347 (__psunsigned_t)context->dupcnt,
2348 (__psunsigned_t)context->flags,
2349 (__psunsigned_t)be16_to_cpu(node->hdr.count), 2262 (__psunsigned_t)be16_to_cpu(node->hdr.count),
2350 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), 2263 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval),
2351 (__psunsigned_t)be32_to_cpu(node->btree[ 2264 (__psunsigned_t)be32_to_cpu(node->btree[
@@ -2359,23 +2272,7 @@ void
2359xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, 2272xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
2360 struct xfs_da_node_entry *btree) 2273 struct xfs_da_node_entry *btree)
2361{ 2274{
2362 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, 2275 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, context,
2363 (__psunsigned_t)context->dp,
2364 (__psunsigned_t)context->cursor->hashval,
2365 (__psunsigned_t)context->cursor->blkno,
2366 (__psunsigned_t)context->cursor->offset,
2367 (__psunsigned_t)context->alist,
2368 (__psunsigned_t)context->bufsize,
2369 (__psunsigned_t)context->count,
2370 (__psunsigned_t)context->firstu,
2371 (__psunsigned_t)
2372 ((context->count > 0) &&
2373 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2374 ? (ATTR_ENTRY(context->alist,
2375 context->count-1)->a_valuelen)
2376 : 0,
2377 (__psunsigned_t)context->dupcnt,
2378 (__psunsigned_t)context->flags,
2379 (__psunsigned_t)be32_to_cpu(btree->hashval), 2276 (__psunsigned_t)be32_to_cpu(btree->hashval),
2380 (__psunsigned_t)be32_to_cpu(btree->before), 2277 (__psunsigned_t)be32_to_cpu(btree->before),
2381 (__psunsigned_t)NULL); 2278 (__psunsigned_t)NULL);
@@ -2388,23 +2285,7 @@ void
2388xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, 2285xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2389 struct xfs_attr_leafblock *leaf) 2286 struct xfs_attr_leafblock *leaf)
2390{ 2287{
2391 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, 2288 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, context,
2392 (__psunsigned_t)context->dp,
2393 (__psunsigned_t)context->cursor->hashval,
2394 (__psunsigned_t)context->cursor->blkno,
2395 (__psunsigned_t)context->cursor->offset,
2396 (__psunsigned_t)context->alist,
2397 (__psunsigned_t)context->bufsize,
2398 (__psunsigned_t)context->count,
2399 (__psunsigned_t)context->firstu,
2400 (__psunsigned_t)
2401 ((context->count > 0) &&
2402 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2403 ? (ATTR_ENTRY(context->alist,
2404 context->count-1)->a_valuelen)
2405 : 0,
2406 (__psunsigned_t)context->dupcnt,
2407 (__psunsigned_t)context->flags,
2408 (__psunsigned_t)be16_to_cpu(leaf->hdr.count), 2289 (__psunsigned_t)be16_to_cpu(leaf->hdr.count),
2409 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), 2290 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval),
2410 (__psunsigned_t)be32_to_cpu(leaf->entries[ 2291 (__psunsigned_t)be32_to_cpu(leaf->entries[
@@ -2417,329 +2298,24 @@ xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2417 */ 2298 */
2418void 2299void
2419xfs_attr_trace_enter(int type, char *where, 2300xfs_attr_trace_enter(int type, char *where,
2420 __psunsigned_t a2, __psunsigned_t a3, 2301 struct xfs_attr_list_context *context,
2421 __psunsigned_t a4, __psunsigned_t a5, 2302 __psunsigned_t a13, __psunsigned_t a14,
2422 __psunsigned_t a6, __psunsigned_t a7, 2303 __psunsigned_t a15)
2423 __psunsigned_t a8, __psunsigned_t a9,
2424 __psunsigned_t a10, __psunsigned_t a11,
2425 __psunsigned_t a12, __psunsigned_t a13,
2426 __psunsigned_t a14, __psunsigned_t a15)
2427{ 2304{
2428 ASSERT(xfs_attr_trace_buf); 2305 ASSERT(xfs_attr_trace_buf);
2429 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), 2306 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type),
2430 (void *)where, 2307 (void *)((__psunsigned_t)where),
2431 (void *)a2, (void *)a3, (void *)a4, 2308 (void *)((__psunsigned_t)context->dp),
2432 (void *)a5, (void *)a6, (void *)a7, 2309 (void *)((__psunsigned_t)context->cursor->hashval),
2433 (void *)a8, (void *)a9, (void *)a10, 2310 (void *)((__psunsigned_t)context->cursor->blkno),
2434 (void *)a11, (void *)a12, (void *)a13, 2311 (void *)((__psunsigned_t)context->cursor->offset),
2435 (void *)a14, (void *)a15); 2312 (void *)((__psunsigned_t)context->alist),
2313 (void *)((__psunsigned_t)context->bufsize),
2314 (void *)((__psunsigned_t)context->count),
2315 (void *)((__psunsigned_t)context->firstu),
2316 NULL,
2317 (void *)((__psunsigned_t)context->dupcnt),
2318 (void *)((__psunsigned_t)context->flags),
2319 (void *)a13, (void *)a14, (void *)a15);
2436} 2320}
2437#endif /* XFS_ATTR_TRACE */ 2321#endif /* XFS_ATTR_TRACE */
2438
2439
2440/*========================================================================
2441 * System (pseudo) namespace attribute interface routines.
2442 *========================================================================*/
2443
2444STATIC int
2445posix_acl_access_set(
2446 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2447{
2448 return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
2449}
2450
2451STATIC int
2452posix_acl_access_remove(
2453 bhv_vnode_t *vp, char *name, int xflags)
2454{
2455 return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
2456}
2457
2458STATIC int
2459posix_acl_access_get(
2460 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2461{
2462 return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
2463}
2464
2465STATIC int
2466posix_acl_access_exists(
2467 bhv_vnode_t *vp)
2468{
2469 return xfs_acl_vhasacl_access(vp);
2470}
2471
2472STATIC int
2473posix_acl_default_set(
2474 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2475{
2476 return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
2477}
2478
2479STATIC int
2480posix_acl_default_get(
2481 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2482{
2483 return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
2484}
2485
2486STATIC int
2487posix_acl_default_remove(
2488 bhv_vnode_t *vp, char *name, int xflags)
2489{
2490 return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
2491}
2492
2493STATIC int
2494posix_acl_default_exists(
2495 bhv_vnode_t *vp)
2496{
2497 return xfs_acl_vhasacl_default(vp);
2498}
2499
2500static struct attrnames posix_acl_access = {
2501 .attr_name = "posix_acl_access",
2502 .attr_namelen = sizeof("posix_acl_access") - 1,
2503 .attr_get = posix_acl_access_get,
2504 .attr_set = posix_acl_access_set,
2505 .attr_remove = posix_acl_access_remove,
2506 .attr_exists = posix_acl_access_exists,
2507};
2508
2509static struct attrnames posix_acl_default = {
2510 .attr_name = "posix_acl_default",
2511 .attr_namelen = sizeof("posix_acl_default") - 1,
2512 .attr_get = posix_acl_default_get,
2513 .attr_set = posix_acl_default_set,
2514 .attr_remove = posix_acl_default_remove,
2515 .attr_exists = posix_acl_default_exists,
2516};
2517
2518static struct attrnames *attr_system_names[] =
2519 { &posix_acl_access, &posix_acl_default };
2520
2521
2522/*========================================================================
2523 * Namespace-prefix-style attribute name interface routines.
2524 *========================================================================*/
2525
2526STATIC int
2527attr_generic_set(
2528 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2529{
2530 return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags);
2531}
2532
2533STATIC int
2534attr_generic_get(
2535 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2536{
2537 int error, asize = size;
2538
2539 error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags);
2540 if (!error)
2541 return asize;
2542 return -error;
2543}
2544
2545STATIC int
2546attr_generic_remove(
2547 bhv_vnode_t *vp, char *name, int xflags)
2548{
2549 return -xfs_attr_remove(xfs_vtoi(vp), name, xflags);
2550}
2551
2552STATIC int
2553attr_generic_listadd(
2554 attrnames_t *prefix,
2555 attrnames_t *namesp,
2556 void *data,
2557 size_t size,
2558 ssize_t *result)
2559{
2560 char *p = data + *result;
2561
2562 *result += prefix->attr_namelen;
2563 *result += namesp->attr_namelen + 1;
2564 if (!size)
2565 return 0;
2566 if (*result > size)
2567 return -ERANGE;
2568 strcpy(p, prefix->attr_name);
2569 p += prefix->attr_namelen;
2570 strcpy(p, namesp->attr_name);
2571 p += namesp->attr_namelen + 1;
2572 return 0;
2573}
2574
2575STATIC int
2576attr_system_list(
2577 bhv_vnode_t *vp,
2578 void *data,
2579 size_t size,
2580 ssize_t *result)
2581{
2582 attrnames_t *namesp;
2583 int i, error = 0;
2584
2585 for (i = 0; i < ATTR_SYSCOUNT; i++) {
2586 namesp = attr_system_names[i];
2587 if (!namesp->attr_exists || !namesp->attr_exists(vp))
2588 continue;
2589 error = attr_generic_listadd(&attr_system, namesp,
2590 data, size, result);
2591 if (error)
2592 break;
2593 }
2594 return error;
2595}
2596
2597int
2598attr_generic_list(
2599 bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result)
2600{
2601 attrlist_cursor_kern_t cursor = { 0 };
2602 int error;
2603
2604 error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor);
2605 if (error > 0)
2606 return -error;
2607 *result = -error;
2608 return attr_system_list(vp, data, size, result);
2609}
2610
2611attrnames_t *
2612attr_lookup_namespace(
2613 char *name,
2614 struct attrnames **names,
2615 int nnames)
2616{
2617 int i;
2618
2619 for (i = 0; i < nnames; i++)
2620 if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
2621 return names[i];
2622 return NULL;
2623}
2624
2625/*
2626 * Some checks to prevent people abusing EAs to get over quota:
2627 * - Don't allow modifying user EAs on devices/symlinks;
2628 * - Don't allow modifying user EAs if sticky bit set;
2629 */
2630STATIC int
2631attr_user_capable(
2632 bhv_vnode_t *vp,
2633 cred_t *cred)
2634{
2635 struct inode *inode = vn_to_inode(vp);
2636
2637 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
2638 return -EPERM;
2639 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
2640 !capable(CAP_SYS_ADMIN))
2641 return -EPERM;
2642 if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
2643 (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
2644 return -EPERM;
2645 return 0;
2646}
2647
2648STATIC int
2649attr_trusted_capable(
2650 bhv_vnode_t *vp,
2651 cred_t *cred)
2652{
2653 struct inode *inode = vn_to_inode(vp);
2654
2655 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
2656 return -EPERM;
2657 if (!capable(CAP_SYS_ADMIN))
2658 return -EPERM;
2659 return 0;
2660}
2661
2662STATIC int
2663attr_system_set(
2664 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2665{
2666 attrnames_t *namesp;
2667 int error;
2668
2669 if (xflags & ATTR_CREATE)
2670 return -EINVAL;
2671
2672 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2673 if (!namesp)
2674 return -EOPNOTSUPP;
2675 error = namesp->attr_set(vp, name, data, size, xflags);
2676 if (!error)
2677 error = vn_revalidate(vp);
2678 return error;
2679}
2680
2681STATIC int
2682attr_system_get(
2683 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2684{
2685 attrnames_t *namesp;
2686
2687 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2688 if (!namesp)
2689 return -EOPNOTSUPP;
2690 return namesp->attr_get(vp, name, data, size, xflags);
2691}
2692
2693STATIC int
2694attr_system_remove(
2695 bhv_vnode_t *vp, char *name, int xflags)
2696{
2697 attrnames_t *namesp;
2698
2699 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2700 if (!namesp)
2701 return -EOPNOTSUPP;
2702 return namesp->attr_remove(vp, name, xflags);
2703}
2704
2705struct attrnames attr_system = {
2706 .attr_name = "system.",
2707 .attr_namelen = sizeof("system.") - 1,
2708 .attr_flag = ATTR_SYSTEM,
2709 .attr_get = attr_system_get,
2710 .attr_set = attr_system_set,
2711 .attr_remove = attr_system_remove,
2712 .attr_capable = (attrcapable_t)fs_noerr,
2713};
2714
2715struct attrnames attr_trusted = {
2716 .attr_name = "trusted.",
2717 .attr_namelen = sizeof("trusted.") - 1,
2718 .attr_flag = ATTR_ROOT,
2719 .attr_get = attr_generic_get,
2720 .attr_set = attr_generic_set,
2721 .attr_remove = attr_generic_remove,
2722 .attr_capable = attr_trusted_capable,
2723};
2724
2725struct attrnames attr_secure = {
2726 .attr_name = "security.",
2727 .attr_namelen = sizeof("security.") - 1,
2728 .attr_flag = ATTR_SECURE,
2729 .attr_get = attr_generic_get,
2730 .attr_set = attr_generic_set,
2731 .attr_remove = attr_generic_remove,
2732 .attr_capable = (attrcapable_t)fs_noerr,
2733};
2734
2735struct attrnames attr_user = {
2736 .attr_name = "user.",
2737 .attr_namelen = sizeof("user.") - 1,
2738 .attr_get = attr_generic_get,
2739 .attr_set = attr_generic_set,
2740 .attr_remove = attr_generic_remove,
2741 .attr_capable = attr_user_capable,
2742};
2743
2744struct attrnames *attr_namespaces[] =
2745 { &attr_system, &attr_trusted, &attr_secure, &attr_user };