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.c718
1 files changed, 160 insertions, 558 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index df151a859186..f7cdc28aff41 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);
@@ -196,6 +194,46 @@ xfs_attr_get(
196 return(error); 194 return(error);
197} 195}
198 196
197/*
198 * Calculate how many blocks we need for the new attribute,
199 */
200int
201xfs_attr_calc_size(
202 struct xfs_inode *ip,
203 int namelen,
204 int valuelen,
205 int *local)
206{
207 struct xfs_mount *mp = ip->i_mount;
208 int size;
209 int nblks;
210
211 /*
212 * Determine space new attribute will use, and if it would be
213 * "local" or "remote" (note: local != inline).
214 */
215 size = xfs_attr_leaf_newentsize(namelen, valuelen,
216 mp->m_sb.sb_blocksize, local);
217
218 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
219 if (*local) {
220 if (size > (mp->m_sb.sb_blocksize >> 1)) {
221 /* Double split possible */
222 nblks *= 2;
223 }
224 } else {
225 /*
226 * Out of line attribute, cannot double split, but
227 * make room for the attribute value itself.
228 */
229 uint dblocks = XFS_B_TO_FSB(mp, valuelen);
230 nblks += dblocks;
231 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
232 }
233
234 return nblks;
235}
236
199STATIC int 237STATIC int
200xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, 238xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
201 char *value, int valuelen, int flags) 239 char *value, int valuelen, int flags)
@@ -204,10 +242,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
204 xfs_fsblock_t firstblock; 242 xfs_fsblock_t firstblock;
205 xfs_bmap_free_t flist; 243 xfs_bmap_free_t flist;
206 int error, err2, committed; 244 int error, err2, committed;
207 int local, size;
208 uint nblks;
209 xfs_mount_t *mp = dp->i_mount; 245 xfs_mount_t *mp = dp->i_mount;
210 int rsvd = (flags & ATTR_ROOT) != 0; 246 int rsvd = (flags & ATTR_ROOT) != 0;
247 int local;
211 248
212 /* 249 /*
213 * Attach the dquots to the inode. 250 * Attach the dquots to the inode.
@@ -241,33 +278,10 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
241 args.firstblock = &firstblock; 278 args.firstblock = &firstblock;
242 args.flist = &flist; 279 args.flist = &flist;
243 args.whichfork = XFS_ATTR_FORK; 280 args.whichfork = XFS_ATTR_FORK;
244 args.addname = 1; 281 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
245 args.oknoent = 1;
246
247 /*
248 * Determine space new attribute will use, and if it would be
249 * "local" or "remote" (note: local != inline).
250 */
251 size = xfs_attr_leaf_newentsize(name->len, valuelen,
252 mp->m_sb.sb_blocksize, &local);
253
254 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
255 if (local) {
256 if (size > (mp->m_sb.sb_blocksize >> 1)) {
257 /* Double split possible */
258 nblks <<= 1;
259 }
260 } else {
261 uint dblocks = XFS_B_TO_FSB(mp, valuelen);
262 /* Out of line attribute, cannot double split, but make
263 * room for the attribute value itself.
264 */
265 nblks += dblocks;
266 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
267 }
268 282
269 /* Size is now blocks for attribute data */ 283 /* Size is now blocks for attribute data */
270 args.total = nblks; 284 args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
271 285
272 /* 286 /*
273 * Start our first transaction of the day. 287 * Start our first transaction of the day.
@@ -289,18 +303,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
289 if (rsvd) 303 if (rsvd)
290 args.trans->t_flags |= XFS_TRANS_RESERVE; 304 args.trans->t_flags |= XFS_TRANS_RESERVE;
291 305
292 if ((error = xfs_trans_reserve(args.trans, (uint) nblks, 306 if ((error = xfs_trans_reserve(args.trans, args.total,
293 XFS_ATTRSET_LOG_RES(mp, nblks), 307 XFS_ATTRSET_LOG_RES(mp, args.total), 0,
294 0, XFS_TRANS_PERM_LOG_RES, 308 XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
295 XFS_ATTRSET_LOG_COUNT))) {
296 xfs_trans_cancel(args.trans, 0); 309 xfs_trans_cancel(args.trans, 0);
297 return(error); 310 return(error);
298 } 311 }
299 xfs_ilock(dp, XFS_ILOCK_EXCL); 312 xfs_ilock(dp, XFS_ILOCK_EXCL);
300 313
301 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, 314 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0,
302 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : 315 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
303 XFS_QMOPT_RES_REGBLKS); 316 XFS_QMOPT_RES_REGBLKS);
304 if (error) { 317 if (error) {
305 xfs_iunlock(dp, XFS_ILOCK_EXCL); 318 xfs_iunlock(dp, XFS_ILOCK_EXCL);
306 xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); 319 xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
@@ -387,7 +400,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
387 * Commit the leaf transformation. We'll need another (linked) 400 * Commit the leaf transformation. We'll need another (linked)
388 * transaction to add the new attribute to the leaf. 401 * transaction to add the new attribute to the leaf.
389 */ 402 */
390 if ((error = xfs_attr_rolltrans(&args.trans, dp))) 403
404 error = xfs_trans_roll(&args.trans, dp);
405 if (error)
391 goto out; 406 goto out;
392 407
393 } 408 }
@@ -529,9 +544,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
529 /* 544 /*
530 * Decide on what work routines to call based on the inode size. 545 * Decide on what work routines to call based on the inode size.
531 */ 546 */
532 if (XFS_IFORK_Q(dp) == 0 || 547 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); 548 error = XFS_ERROR(ENOATTR);
536 goto out; 549 goto out;
537 } 550 }
@@ -601,29 +614,33 @@ xfs_attr_remove(
601 return error; 614 return error;
602 615
603 xfs_ilock(dp, XFS_ILOCK_SHARED); 616 xfs_ilock(dp, XFS_ILOCK_SHARED);
604 if (XFS_IFORK_Q(dp) == 0 || 617 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); 618 xfs_iunlock(dp, XFS_ILOCK_SHARED);
608 return(XFS_ERROR(ENOATTR)); 619 return XFS_ERROR(ENOATTR);
609 } 620 }
610 xfs_iunlock(dp, XFS_ILOCK_SHARED); 621 xfs_iunlock(dp, XFS_ILOCK_SHARED);
611 622
612 return xfs_attr_remove_int(dp, &xname, flags); 623 return xfs_attr_remove_int(dp, &xname, flags);
613} 624}
614 625
615STATIC int 626int
616xfs_attr_list_int(xfs_attr_list_context_t *context) 627xfs_attr_list_int(xfs_attr_list_context_t *context)
617{ 628{
618 int error; 629 int error;
619 xfs_inode_t *dp = context->dp; 630 xfs_inode_t *dp = context->dp;
620 631
632 XFS_STATS_INC(xs_attr_list);
633
634 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
635 return EIO;
636
637 xfs_ilock(dp, XFS_ILOCK_SHARED);
638 xfs_attr_trace_l_c("syscall start", context);
639
621 /* 640 /*
622 * Decide on what work routines to call based on the inode size. 641 * Decide on what work routines to call based on the inode size.
623 */ 642 */
624 if (XFS_IFORK_Q(dp) == 0 || 643 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; 644 error = 0;
628 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 645 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
629 error = xfs_attr_shortform_list(context); 646 error = xfs_attr_shortform_list(context);
@@ -632,6 +649,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
632 } else { 649 } else {
633 error = xfs_attr_node_list(context); 650 error = xfs_attr_node_list(context);
634 } 651 }
652
653 xfs_iunlock(dp, XFS_ILOCK_SHARED);
654 xfs_attr_trace_l_c("syscall end", context);
655
635 return error; 656 return error;
636} 657}
637 658
@@ -648,74 +669,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
648 */ 669 */
649/*ARGSUSED*/ 670/*ARGSUSED*/
650STATIC int 671STATIC int
651xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, 672xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags,
652 char *name, int namelen, 673 char *name, int namelen,
653 int valuelen, char *value) 674 int valuelen, char *value)
654{ 675{
676 struct attrlist *alist = (struct attrlist *)context->alist;
655 attrlist_ent_t *aep; 677 attrlist_ent_t *aep;
656 int arraytop; 678 int arraytop;
657 679
658 ASSERT(!(context->flags & ATTR_KERNOVAL)); 680 ASSERT(!(context->flags & ATTR_KERNOVAL));
659 ASSERT(context->count >= 0); 681 ASSERT(context->count >= 0);
660 ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); 682 ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
661 ASSERT(context->firstu >= sizeof(*context->alist)); 683 ASSERT(context->firstu >= sizeof(*alist));
662 ASSERT(context->firstu <= context->bufsize); 684 ASSERT(context->firstu <= context->bufsize);
663 685
664 arraytop = sizeof(*context->alist) + 686 /*
665 context->count * sizeof(context->alist->al_offset[0]); 687 * Only list entries in the right namespace.
688 */
689 if (((context->flags & ATTR_SECURE) == 0) !=
690 ((flags & XFS_ATTR_SECURE) == 0))
691 return 0;
692 if (((context->flags & ATTR_ROOT) == 0) !=
693 ((flags & XFS_ATTR_ROOT) == 0))
694 return 0;
695
696 arraytop = sizeof(*alist) +
697 context->count * sizeof(alist->al_offset[0]);
666 context->firstu -= ATTR_ENTSIZE(namelen); 698 context->firstu -= ATTR_ENTSIZE(namelen);
667 if (context->firstu < arraytop) { 699 if (context->firstu < arraytop) {
668 xfs_attr_trace_l_c("buffer full", context); 700 xfs_attr_trace_l_c("buffer full", context);
669 context->alist->al_more = 1; 701 alist->al_more = 1;
670 context->seen_enough = 1; 702 context->seen_enough = 1;
671 return 1; 703 return 1;
672 } 704 }
673 705
674 aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); 706 aep = (attrlist_ent_t *)&context->alist[context->firstu];
675 aep->a_valuelen = valuelen; 707 aep->a_valuelen = valuelen;
676 memcpy(aep->a_name, name, namelen); 708 memcpy(aep->a_name, name, namelen);
677 aep->a_name[ namelen ] = 0; 709 aep->a_name[namelen] = 0;
678 context->alist->al_offset[ context->count++ ] = context->firstu; 710 alist->al_offset[context->count++] = context->firstu;
679 context->alist->al_count = context->count; 711 alist->al_count = context->count;
680 xfs_attr_trace_l_c("add", context); 712 xfs_attr_trace_l_c("add", context);
681 return 0; 713 return 0;
682} 714}
683 715
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/* 716/*
720 * Generate a list of extended attribute names and optionally 717 * Generate a list of extended attribute names and optionally
721 * also value lengths. Positive return value follows the XFS 718 * also value lengths. Positive return value follows the XFS
@@ -732,10 +729,9 @@ xfs_attr_list(
732 attrlist_cursor_kern_t *cursor) 729 attrlist_cursor_kern_t *cursor)
733{ 730{
734 xfs_attr_list_context_t context; 731 xfs_attr_list_context_t context;
732 struct attrlist *alist;
735 int error; 733 int error;
736 734
737 XFS_STATS_INC(xs_attr_list);
738
739 /* 735 /*
740 * Validate the cursor. 736 * Validate the cursor.
741 */ 737 */
@@ -756,52 +752,23 @@ xfs_attr_list(
756 /* 752 /*
757 * Initialize the output buffer. 753 * Initialize the output buffer.
758 */ 754 */
755 memset(&context, 0, sizeof(context));
759 context.dp = dp; 756 context.dp = dp;
760 context.cursor = cursor; 757 context.cursor = cursor;
761 context.count = 0;
762 context.dupcnt = 0;
763 context.resynch = 1; 758 context.resynch = 1;
764 context.flags = flags; 759 context.flags = flags;
765 context.seen_enough = 0; 760 context.alist = buffer;
766 context.alist = (attrlist_t *)buffer; 761 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
767 context.put_value = 0; 762 context.firstu = context.bufsize;
768 763 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
785 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
786 return EIO;
787 764
788 xfs_ilock(dp, XFS_ILOCK_SHARED); 765 alist = (struct attrlist *)context.alist;
789 xfs_attr_trace_l_c("syscall start", &context); 766 alist->al_count = 0;
767 alist->al_more = 0;
768 alist->al_offset[0] = context.bufsize;
790 769
791 error = xfs_attr_list_int(&context); 770 error = xfs_attr_list_int(&context);
792 771 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; 772 return error;
806} 773}
807 774
@@ -816,12 +783,10 @@ xfs_attr_inactive(xfs_inode_t *dp)
816 ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); 783 ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
817 784
818 xfs_ilock(dp, XFS_ILOCK_SHARED); 785 xfs_ilock(dp, XFS_ILOCK_SHARED);
819 if ((XFS_IFORK_Q(dp) == 0) || 786 if (!xfs_inode_hasattr(dp) ||
820 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 787 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); 788 xfs_iunlock(dp, XFS_ILOCK_SHARED);
824 return(0); 789 return 0;
825 } 790 }
826 xfs_iunlock(dp, XFS_ILOCK_SHARED); 791 xfs_iunlock(dp, XFS_ILOCK_SHARED);
827 792
@@ -854,10 +819,8 @@ xfs_attr_inactive(xfs_inode_t *dp)
854 /* 819 /*
855 * Decide on what work routines to call based on the inode size. 820 * Decide on what work routines to call based on the inode size.
856 */ 821 */
857 if ((XFS_IFORK_Q(dp) == 0) || 822 if (!xfs_inode_hasattr(dp) ||
858 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 823 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; 824 error = 0;
862 goto out; 825 goto out;
863 } 826 }
@@ -974,7 +937,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
974 xfs_da_brelse(args->trans, bp); 937 xfs_da_brelse(args->trans, bp);
975 return(retval); 938 return(retval);
976 } 939 }
977 args->rename = 1; /* an atomic rename */ 940 args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */
978 args->blkno2 = args->blkno; /* set 2nd entry info*/ 941 args->blkno2 = args->blkno; /* set 2nd entry info*/
979 args->index2 = args->index; 942 args->index2 = args->index;
980 args->rmtblkno2 = args->rmtblkno; 943 args->rmtblkno2 = args->rmtblkno;
@@ -1019,7 +982,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1019 * Commit the current trans (including the inode) and start 982 * Commit the current trans (including the inode) and start
1020 * a new one. 983 * a new one.
1021 */ 984 */
1022 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 985 error = xfs_trans_roll(&args->trans, dp);
986 if (error)
1023 return (error); 987 return (error);
1024 988
1025 /* 989 /*
@@ -1033,7 +997,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1033 * Commit the transaction that added the attr name so that 997 * Commit the transaction that added the attr name so that
1034 * later routines can manage their own transactions. 998 * later routines can manage their own transactions.
1035 */ 999 */
1036 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1000 error = xfs_trans_roll(&args->trans, dp);
1001 if (error)
1037 return (error); 1002 return (error);
1038 1003
1039 /* 1004 /*
@@ -1054,7 +1019,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1054 * so that one disappears and one appears atomically. Then we 1019 * so that one disappears and one appears atomically. Then we
1055 * must remove the "old" attribute/value pair. 1020 * must remove the "old" attribute/value pair.
1056 */ 1021 */
1057 if (args->rename) { 1022 if (args->op_flags & XFS_DA_OP_RENAME) {
1058 /* 1023 /*
1059 * In a separate transaction, set the incomplete flag on the 1024 * In a separate transaction, set the incomplete flag on the
1060 * "old" attr and clear the incomplete flag on the "new" attr. 1025 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -1122,7 +1087,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1122 /* 1087 /*
1123 * Commit the remove and start the next trans in series. 1088 * Commit the remove and start the next trans in series.
1124 */ 1089 */
1125 error = xfs_attr_rolltrans(&args->trans, dp); 1090 error = xfs_trans_roll(&args->trans, dp);
1126 1091
1127 } else if (args->rmtblkno > 0) { 1092 } else if (args->rmtblkno > 0) {
1128 /* 1093 /*
@@ -1307,7 +1272,7 @@ restart:
1307 } else if (retval == EEXIST) { 1272 } else if (retval == EEXIST) {
1308 if (args->flags & ATTR_CREATE) 1273 if (args->flags & ATTR_CREATE)
1309 goto out; 1274 goto out;
1310 args->rename = 1; /* atomic rename op */ 1275 args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */
1311 args->blkno2 = args->blkno; /* set 2nd entry info*/ 1276 args->blkno2 = args->blkno; /* set 2nd entry info*/
1312 args->index2 = args->index; 1277 args->index2 = args->index;
1313 args->rmtblkno2 = args->rmtblkno; 1278 args->rmtblkno2 = args->rmtblkno;
@@ -1353,7 +1318,8 @@ restart:
1353 * Commit the node conversion and start the next 1318 * Commit the node conversion and start the next
1354 * trans in the chain. 1319 * trans in the chain.
1355 */ 1320 */
1356 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1321 error = xfs_trans_roll(&args->trans, dp);
1322 if (error)
1357 goto out; 1323 goto out;
1358 1324
1359 goto restart; 1325 goto restart;
@@ -1404,7 +1370,8 @@ restart:
1404 * Commit the leaf addition or btree split and start the next 1370 * Commit the leaf addition or btree split and start the next
1405 * trans in the chain. 1371 * trans in the chain.
1406 */ 1372 */
1407 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1373 error = xfs_trans_roll(&args->trans, dp);
1374 if (error)
1408 goto out; 1375 goto out;
1409 1376
1410 /* 1377 /*
@@ -1425,7 +1392,7 @@ restart:
1425 * so that one disappears and one appears atomically. Then we 1392 * so that one disappears and one appears atomically. Then we
1426 * must remove the "old" attribute/value pair. 1393 * must remove the "old" attribute/value pair.
1427 */ 1394 */
1428 if (args->rename) { 1395 if (args->op_flags & XFS_DA_OP_RENAME) {
1429 /* 1396 /*
1430 * In a separate transaction, set the incomplete flag on the 1397 * In a separate transaction, set the incomplete flag on the
1431 * "old" attr and clear the incomplete flag on the "new" attr. 1398 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -1504,7 +1471,8 @@ restart:
1504 /* 1471 /*
1505 * Commit and start the next trans in the chain. 1472 * Commit and start the next trans in the chain.
1506 */ 1473 */
1507 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1474 error = xfs_trans_roll(&args->trans, dp);
1475 if (error)
1508 goto out; 1476 goto out;
1509 1477
1510 } else if (args->rmtblkno > 0) { 1478 } else if (args->rmtblkno > 0) {
@@ -1636,7 +1604,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
1636 /* 1604 /*
1637 * Commit the Btree join operation and start a new trans. 1605 * Commit the Btree join operation and start a new trans.
1638 */ 1606 */
1639 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1607 error = xfs_trans_roll(&args->trans, dp);
1608 if (error)
1640 goto out; 1609 goto out;
1641 } 1610 }
1642 1611
@@ -2137,7 +2106,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
2137 /* 2106 /*
2138 * Start the next trans in the chain. 2107 * Start the next trans in the chain.
2139 */ 2108 */
2140 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 2109 error = xfs_trans_roll(&args->trans, dp);
2110 if (error)
2141 return (error); 2111 return (error);
2142 } 2112 }
2143 2113
@@ -2287,7 +2257,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2287 /* 2257 /*
2288 * Close out trans and start the next one in the chain. 2258 * Close out trans and start the next one in the chain.
2289 */ 2259 */
2290 if ((error = xfs_attr_rolltrans(&args->trans, args->dp))) 2260 error = xfs_trans_roll(&args->trans, args->dp);
2261 if (error)
2291 return (error); 2262 return (error);
2292 } 2263 }
2293 return(0); 2264 return(0);
@@ -2300,23 +2271,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2300void 2271void
2301xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) 2272xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context)
2302{ 2273{
2303 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, 2274 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, 2275 (__psunsigned_t)NULL,
2321 (__psunsigned_t)NULL, 2276 (__psunsigned_t)NULL,
2322 (__psunsigned_t)NULL); 2277 (__psunsigned_t)NULL);
@@ -2329,23 +2284,7 @@ void
2329xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, 2284xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
2330 struct xfs_da_intnode *node) 2285 struct xfs_da_intnode *node)
2331{ 2286{
2332 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, 2287 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), 2288 (__psunsigned_t)be16_to_cpu(node->hdr.count),
2350 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), 2289 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval),
2351 (__psunsigned_t)be32_to_cpu(node->btree[ 2290 (__psunsigned_t)be32_to_cpu(node->btree[
@@ -2359,23 +2298,7 @@ void
2359xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, 2298xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
2360 struct xfs_da_node_entry *btree) 2299 struct xfs_da_node_entry *btree)
2361{ 2300{
2362 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, 2301 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), 2302 (__psunsigned_t)be32_to_cpu(btree->hashval),
2380 (__psunsigned_t)be32_to_cpu(btree->before), 2303 (__psunsigned_t)be32_to_cpu(btree->before),
2381 (__psunsigned_t)NULL); 2304 (__psunsigned_t)NULL);
@@ -2388,23 +2311,7 @@ void
2388xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, 2311xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2389 struct xfs_attr_leafblock *leaf) 2312 struct xfs_attr_leafblock *leaf)
2390{ 2313{
2391 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, 2314 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), 2315 (__psunsigned_t)be16_to_cpu(leaf->hdr.count),
2409 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), 2316 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval),
2410 (__psunsigned_t)be32_to_cpu(leaf->entries[ 2317 (__psunsigned_t)be32_to_cpu(leaf->entries[
@@ -2417,329 +2324,24 @@ xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2417 */ 2324 */
2418void 2325void
2419xfs_attr_trace_enter(int type, char *where, 2326xfs_attr_trace_enter(int type, char *where,
2420 __psunsigned_t a2, __psunsigned_t a3, 2327 struct xfs_attr_list_context *context,
2421 __psunsigned_t a4, __psunsigned_t a5, 2328 __psunsigned_t a13, __psunsigned_t a14,
2422 __psunsigned_t a6, __psunsigned_t a7, 2329 __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{ 2330{
2428 ASSERT(xfs_attr_trace_buf); 2331 ASSERT(xfs_attr_trace_buf);
2429 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), 2332 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type),
2430 (void *)where, 2333 (void *)((__psunsigned_t)where),
2431 (void *)a2, (void *)a3, (void *)a4, 2334 (void *)((__psunsigned_t)context->dp),
2432 (void *)a5, (void *)a6, (void *)a7, 2335 (void *)((__psunsigned_t)context->cursor->hashval),
2433 (void *)a8, (void *)a9, (void *)a10, 2336 (void *)((__psunsigned_t)context->cursor->blkno),
2434 (void *)a11, (void *)a12, (void *)a13, 2337 (void *)((__psunsigned_t)context->cursor->offset),
2435 (void *)a14, (void *)a15); 2338 (void *)((__psunsigned_t)context->alist),
2339 (void *)((__psunsigned_t)context->bufsize),
2340 (void *)((__psunsigned_t)context->count),
2341 (void *)((__psunsigned_t)context->firstu),
2342 NULL,
2343 (void *)((__psunsigned_t)context->dupcnt),
2344 (void *)((__psunsigned_t)context->flags),
2345 (void *)a13, (void *)a14, (void *)a15);
2436} 2346}
2437#endif /* XFS_ATTR_TRACE */ 2347#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 };