diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_attr.c | 181 | ||||
-rw-r--r-- | fs/xfs/xfs_attr.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 351 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_leaf.h | 41 |
4 files changed, 334 insertions, 247 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 1a2101043275..9ada7bdbae52 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -91,7 +91,6 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); | |||
91 | /* | 91 | /* |
92 | * Routines to manipulate out-of-line attribute values. | 92 | * Routines to manipulate out-of-line attribute values. |
93 | */ | 93 | */ |
94 | STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args); | ||
95 | STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args); | 94 | STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args); |
96 | STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); | 95 | STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); |
97 | 96 | ||
@@ -180,7 +179,7 @@ xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp, | |||
180 | return(error); | 179 | return(error); |
181 | } | 180 | } |
182 | 181 | ||
183 | STATIC int | 182 | int |
184 | xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, | 183 | xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, |
185 | char *value, int valuelen, int flags) | 184 | char *value, int valuelen, int flags) |
186 | { | 185 | { |
@@ -440,7 +439,7 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f | |||
440 | * Generic handler routine to remove a name from an attribute list. | 439 | * Generic handler routine to remove a name from an attribute list. |
441 | * Transitions attribute list from Btree to shortform as necessary. | 440 | * Transitions attribute list from Btree to shortform as necessary. |
442 | */ | 441 | */ |
443 | STATIC int | 442 | int |
444 | xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags) | 443 | xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags) |
445 | { | 444 | { |
446 | xfs_da_args_t args; | 445 | xfs_da_args_t args; |
@@ -591,6 +590,110 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred) | |||
591 | return xfs_attr_remove_int(dp, name, namelen, flags); | 590 | return xfs_attr_remove_int(dp, name, namelen, flags); |
592 | } | 591 | } |
593 | 592 | ||
593 | int /* error */ | ||
594 | xfs_attr_list_int(xfs_attr_list_context_t *context) | ||
595 | { | ||
596 | int error; | ||
597 | xfs_inode_t *dp = context->dp; | ||
598 | |||
599 | /* | ||
600 | * Decide on what work routines to call based on the inode size. | ||
601 | */ | ||
602 | if (XFS_IFORK_Q(dp) == 0 || | ||
603 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
604 | dp->i_d.di_anextents == 0)) { | ||
605 | error = 0; | ||
606 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | ||
607 | error = xfs_attr_shortform_list(context); | ||
608 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | ||
609 | error = xfs_attr_leaf_list(context); | ||
610 | } else { | ||
611 | error = xfs_attr_node_list(context); | ||
612 | } | ||
613 | return error; | ||
614 | } | ||
615 | |||
616 | #define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \ | ||
617 | (((struct attrlist_ent *) 0)->a_name - (char *) 0) | ||
618 | #define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \ | ||
619 | ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \ | ||
620 | & ~(sizeof(u_int32_t)-1)) | ||
621 | |||
622 | /* | ||
623 | * Format an attribute and copy it out to the user's buffer. | ||
624 | * Take care to check values and protect against them changing later, | ||
625 | * we may be reading them directly out of a user buffer. | ||
626 | */ | ||
627 | /*ARGSUSED*/ | ||
628 | STATIC int | ||
629 | xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
630 | char *name, int namelen, | ||
631 | int valuelen, char *value) | ||
632 | { | ||
633 | attrlist_ent_t *aep; | ||
634 | int arraytop; | ||
635 | |||
636 | ASSERT(!(context->flags & ATTR_KERNOVAL)); | ||
637 | ASSERT(context->count >= 0); | ||
638 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); | ||
639 | ASSERT(context->firstu >= sizeof(*context->alist)); | ||
640 | ASSERT(context->firstu <= context->bufsize); | ||
641 | |||
642 | arraytop = sizeof(*context->alist) + | ||
643 | context->count * sizeof(context->alist->al_offset[0]); | ||
644 | context->firstu -= ATTR_ENTSIZE(namelen); | ||
645 | if (context->firstu < arraytop) { | ||
646 | xfs_attr_trace_l_c("buffer full", context); | ||
647 | context->alist->al_more = 1; | ||
648 | context->seen_enough = 1; | ||
649 | return 1; | ||
650 | } | ||
651 | |||
652 | aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); | ||
653 | aep->a_valuelen = valuelen; | ||
654 | memcpy(aep->a_name, name, namelen); | ||
655 | aep->a_name[ namelen ] = 0; | ||
656 | context->alist->al_offset[ context->count++ ] = context->firstu; | ||
657 | context->alist->al_count = context->count; | ||
658 | xfs_attr_trace_l_c("add", context); | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | STATIC int | ||
663 | xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
664 | char *name, int namelen, | ||
665 | int valuelen, char *value) | ||
666 | { | ||
667 | char *offset; | ||
668 | int arraytop; | ||
669 | |||
670 | ASSERT(context->count >= 0); | ||
671 | |||
672 | arraytop = context->count + namesp->attr_namelen + namelen + 1; | ||
673 | if (arraytop > context->firstu) { | ||
674 | context->count = -1; /* insufficient space */ | ||
675 | return 1; | ||
676 | } | ||
677 | offset = (char *)context->alist + context->count; | ||
678 | strncpy(offset, namesp->attr_name, namesp->attr_namelen); | ||
679 | offset += namesp->attr_namelen; | ||
680 | strncpy(offset, name, namelen); /* real name */ | ||
681 | offset += namelen; | ||
682 | *offset = '\0'; | ||
683 | context->count += namesp->attr_namelen + namelen + 1; | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | /*ARGSUSED*/ | ||
688 | STATIC int | ||
689 | xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
690 | char *name, int namelen, | ||
691 | int valuelen, char *value) | ||
692 | { | ||
693 | context->count += namesp->attr_namelen + namelen + 1; | ||
694 | return 0; | ||
695 | } | ||
696 | |||
594 | /* | 697 | /* |
595 | * Generate a list of extended attribute names and optionally | 698 | * Generate a list of extended attribute names and optionally |
596 | * also value lengths. Positive return value follows the XFS | 699 | * also value lengths. Positive return value follows the XFS |
@@ -615,13 +718,13 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags, | |||
615 | return(XFS_ERROR(EINVAL)); | 718 | return(XFS_ERROR(EINVAL)); |
616 | if ((cursor->initted == 0) && | 719 | if ((cursor->initted == 0) && |
617 | (cursor->hashval || cursor->blkno || cursor->offset)) | 720 | (cursor->hashval || cursor->blkno || cursor->offset)) |
618 | return(XFS_ERROR(EINVAL)); | 721 | return XFS_ERROR(EINVAL); |
619 | 722 | ||
620 | /* | 723 | /* |
621 | * Check for a properly aligned buffer. | 724 | * Check for a properly aligned buffer. |
622 | */ | 725 | */ |
623 | if (((long)buffer) & (sizeof(int)-1)) | 726 | if (((long)buffer) & (sizeof(int)-1)) |
624 | return(XFS_ERROR(EFAULT)); | 727 | return XFS_ERROR(EFAULT); |
625 | if (flags & ATTR_KERNOVAL) | 728 | if (flags & ATTR_KERNOVAL) |
626 | bufsize = 0; | 729 | bufsize = 0; |
627 | 730 | ||
@@ -634,53 +737,47 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags, | |||
634 | context.dupcnt = 0; | 737 | context.dupcnt = 0; |
635 | context.resynch = 1; | 738 | context.resynch = 1; |
636 | context.flags = flags; | 739 | context.flags = flags; |
637 | if (!(flags & ATTR_KERNAMELS)) { | 740 | context.seen_enough = 0; |
741 | context.alist = (attrlist_t *)buffer; | ||
742 | context.put_value = 0; | ||
743 | |||
744 | if (flags & ATTR_KERNAMELS) { | ||
745 | context.bufsize = bufsize; | ||
746 | context.firstu = context.bufsize; | ||
747 | if (flags & ATTR_KERNOVAL) | ||
748 | context.put_listent = xfs_attr_kern_list_sizes; | ||
749 | else | ||
750 | context.put_listent = xfs_attr_kern_list; | ||
751 | } else { | ||
638 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ | 752 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ |
639 | context.firstu = context.bufsize; | 753 | context.firstu = context.bufsize; |
640 | context.alist = (attrlist_t *)buffer; | ||
641 | context.alist->al_count = 0; | 754 | context.alist->al_count = 0; |
642 | context.alist->al_more = 0; | 755 | context.alist->al_more = 0; |
643 | context.alist->al_offset[0] = context.bufsize; | 756 | context.alist->al_offset[0] = context.bufsize; |
644 | } | 757 | context.put_listent = xfs_attr_put_listent; |
645 | else { | ||
646 | context.bufsize = bufsize; | ||
647 | context.firstu = context.bufsize; | ||
648 | context.alist = (attrlist_t *)buffer; | ||
649 | } | 758 | } |
650 | 759 | ||
651 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 760 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
652 | return (EIO); | 761 | return EIO; |
653 | 762 | ||
654 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 763 | xfs_ilock(dp, XFS_ILOCK_SHARED); |
655 | /* | ||
656 | * Decide on what work routines to call based on the inode size. | ||
657 | */ | ||
658 | xfs_attr_trace_l_c("syscall start", &context); | 764 | xfs_attr_trace_l_c("syscall start", &context); |
659 | if (XFS_IFORK_Q(dp) == 0 || | 765 | |
660 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | 766 | error = xfs_attr_list_int(&context); |
661 | dp->i_d.di_anextents == 0)) { | 767 | |
662 | error = 0; | ||
663 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | ||
664 | error = xfs_attr_shortform_list(&context); | ||
665 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | ||
666 | error = xfs_attr_leaf_list(&context); | ||
667 | } else { | ||
668 | error = xfs_attr_node_list(&context); | ||
669 | } | ||
670 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 768 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
671 | xfs_attr_trace_l_c("syscall end", &context); | 769 | xfs_attr_trace_l_c("syscall end", &context); |
672 | 770 | ||
673 | if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) { | 771 | if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) { |
674 | ASSERT(error >= 0); | 772 | /* must return negated buffer size or the error */ |
675 | } | ||
676 | else { /* must return negated buffer size or the error */ | ||
677 | if (context.count < 0) | 773 | if (context.count < 0) |
678 | error = XFS_ERROR(ERANGE); | 774 | error = XFS_ERROR(ERANGE); |
679 | else | 775 | else |
680 | error = -context.count; | 776 | error = -context.count; |
681 | } | 777 | } else |
778 | ASSERT(error >= 0); | ||
682 | 779 | ||
683 | return(error); | 780 | return error; |
684 | } | 781 | } |
685 | 782 | ||
686 | int /* error */ | 783 | int /* error */ |
@@ -1122,19 +1219,19 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context) | |||
1122 | context->cursor->blkno = 0; | 1219 | context->cursor->blkno = 0; |
1123 | error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK); | 1220 | error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK); |
1124 | if (error) | 1221 | if (error) |
1125 | return(error); | 1222 | return XFS_ERROR(error); |
1126 | ASSERT(bp != NULL); | 1223 | ASSERT(bp != NULL); |
1127 | leaf = bp->data; | 1224 | leaf = bp->data; |
1128 | if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) { | 1225 | if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) { |
1129 | XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, | 1226 | XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, |
1130 | context->dp->i_mount, leaf); | 1227 | context->dp->i_mount, leaf); |
1131 | xfs_da_brelse(NULL, bp); | 1228 | xfs_da_brelse(NULL, bp); |
1132 | return(XFS_ERROR(EFSCORRUPTED)); | 1229 | return XFS_ERROR(EFSCORRUPTED); |
1133 | } | 1230 | } |
1134 | 1231 | ||
1135 | (void)xfs_attr_leaf_list_int(bp, context); | 1232 | error = xfs_attr_leaf_list_int(bp, context); |
1136 | xfs_da_brelse(NULL, bp); | 1233 | xfs_da_brelse(NULL, bp); |
1137 | return(0); | 1234 | return XFS_ERROR(error); |
1138 | } | 1235 | } |
1139 | 1236 | ||
1140 | 1237 | ||
@@ -1858,8 +1955,12 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1858 | return(XFS_ERROR(EFSCORRUPTED)); | 1955 | return(XFS_ERROR(EFSCORRUPTED)); |
1859 | } | 1956 | } |
1860 | error = xfs_attr_leaf_list_int(bp, context); | 1957 | error = xfs_attr_leaf_list_int(bp, context); |
1861 | if (error || !leaf->hdr.info.forw) | 1958 | if (error) { |
1862 | break; /* not really an error, buffer full or EOF */ | 1959 | xfs_da_brelse(NULL, bp); |
1960 | return error; | ||
1961 | } | ||
1962 | if (context->seen_enough || leaf->hdr.info.forw == 0) | ||
1963 | break; | ||
1863 | cursor->blkno = be32_to_cpu(leaf->hdr.info.forw); | 1964 | cursor->blkno = be32_to_cpu(leaf->hdr.info.forw); |
1864 | xfs_da_brelse(NULL, bp); | 1965 | xfs_da_brelse(NULL, bp); |
1865 | error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, | 1966 | error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, |
@@ -1886,7 +1987,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1886 | * Read the value associated with an attribute from the out-of-line buffer | 1987 | * Read the value associated with an attribute from the out-of-line buffer |
1887 | * that we stored it in. | 1988 | * that we stored it in. |
1888 | */ | 1989 | */ |
1889 | STATIC int | 1990 | int |
1890 | xfs_attr_rmtval_get(xfs_da_args_t *args) | 1991 | xfs_attr_rmtval_get(xfs_da_args_t *args) |
1891 | { | 1992 | { |
1892 | xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE]; | 1993 | xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE]; |
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index 981633f6c077..783977d3ea71 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | struct cred; | 38 | struct cred; |
39 | struct bhv_vnode; | 39 | struct bhv_vnode; |
40 | struct xfs_attr_list_context; | ||
40 | 41 | ||
41 | typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int); | 42 | typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int); |
42 | typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int); | 43 | typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int); |
@@ -160,13 +161,16 @@ struct xfs_da_args; | |||
160 | */ | 161 | */ |
161 | int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *); | 162 | int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *); |
162 | int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *); | 163 | int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *); |
164 | int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int); | ||
163 | int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *); | 165 | int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *); |
164 | int xfs_attr_list(bhv_desc_t *, char *, int, int, | 166 | int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int); |
165 | struct attrlist_cursor_kern *, struct cred *); | 167 | int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *); |
168 | int xfs_attr_list_int(struct xfs_attr_list_context *); | ||
166 | int xfs_attr_inactive(struct xfs_inode *dp); | 169 | int xfs_attr_inactive(struct xfs_inode *dp); |
167 | 170 | ||
168 | int xfs_attr_shortform_getvalue(struct xfs_da_args *); | 171 | int xfs_attr_shortform_getvalue(struct xfs_da_args *); |
169 | int xfs_attr_fetch(struct xfs_inode *, const char *, int, | 172 | int xfs_attr_fetch(struct xfs_inode *, const char *, int, |
170 | char *, int *, int, struct cred *); | 173 | char *, int *, int, struct cred *); |
174 | int xfs_attr_rmtval_get(struct xfs_da_args *args); | ||
171 | 175 | ||
172 | #endif /* __XFS_ATTR_H__ */ | 176 | #endif /* __XFS_ATTR_H__ */ |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 9455051f0120..9719bbef122c 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -89,9 +89,46 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf, | |||
89 | int dst_start, int move_count, | 89 | int dst_start, int move_count, |
90 | xfs_mount_t *mp); | 90 | xfs_mount_t *mp); |
91 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); | 91 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); |
92 | STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context, | 92 | |
93 | attrnames_t *, char *name, int namelen, | 93 | /*======================================================================== |
94 | int valuelen); | 94 | * Namespace helper routines |
95 | *========================================================================*/ | ||
96 | |||
97 | STATIC inline attrnames_t * | ||
98 | xfs_attr_flags_namesp(int flags) | ||
99 | { | ||
100 | return ((flags & XFS_ATTR_SECURE) ? &attr_secure: | ||
101 | ((flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user)); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * If namespace bits don't match return 0. | ||
106 | * If all match then return 1. | ||
107 | */ | ||
108 | STATIC inline int | ||
109 | xfs_attr_namesp_match(int arg_flags, int ondisk_flags) | ||
110 | { | ||
111 | return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * If namespace bits don't match and we don't have an override for it | ||
116 | * then return 0. | ||
117 | * If all match or are overridable then return 1. | ||
118 | */ | ||
119 | STATIC inline int | ||
120 | xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags) | ||
121 | { | ||
122 | if (((arg_flags & ATTR_SECURE) == 0) != | ||
123 | ((ondisk_flags & XFS_ATTR_SECURE) == 0) && | ||
124 | !(arg_flags & ATTR_KERNORMALS)) | ||
125 | return 0; | ||
126 | if (((arg_flags & ATTR_ROOT) == 0) != | ||
127 | ((ondisk_flags & XFS_ATTR_ROOT) == 0) && | ||
128 | !(arg_flags & ATTR_KERNROOTLS)) | ||
129 | return 0; | ||
130 | return 1; | ||
131 | } | ||
95 | 132 | ||
96 | 133 | ||
97 | /*======================================================================== | 134 | /*======================================================================== |
@@ -228,11 +265,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) | |||
228 | continue; | 265 | continue; |
229 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) | 266 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
230 | continue; | 267 | continue; |
231 | if (((args->flags & ATTR_SECURE) != 0) != | 268 | if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
232 | ((sfe->flags & XFS_ATTR_SECURE) != 0)) | ||
233 | continue; | ||
234 | if (((args->flags & ATTR_ROOT) != 0) != | ||
235 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | ||
236 | continue; | 269 | continue; |
237 | ASSERT(0); | 270 | ASSERT(0); |
238 | #endif | 271 | #endif |
@@ -246,8 +279,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) | |||
246 | 279 | ||
247 | sfe->namelen = args->namelen; | 280 | sfe->namelen = args->namelen; |
248 | sfe->valuelen = args->valuelen; | 281 | sfe->valuelen = args->valuelen; |
249 | sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : | 282 | sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); |
250 | ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); | ||
251 | memcpy(sfe->nameval, args->name, args->namelen); | 283 | memcpy(sfe->nameval, args->name, args->namelen); |
252 | memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); | 284 | memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); |
253 | sf->hdr.count++; | 285 | sf->hdr.count++; |
@@ -282,11 +314,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
282 | continue; | 314 | continue; |
283 | if (memcmp(sfe->nameval, args->name, args->namelen) != 0) | 315 | if (memcmp(sfe->nameval, args->name, args->namelen) != 0) |
284 | continue; | 316 | continue; |
285 | if (((args->flags & ATTR_SECURE) != 0) != | 317 | if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
286 | ((sfe->flags & XFS_ATTR_SECURE) != 0)) | ||
287 | continue; | ||
288 | if (((args->flags & ATTR_ROOT) != 0) != | ||
289 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | ||
290 | continue; | 318 | continue; |
291 | break; | 319 | break; |
292 | } | 320 | } |
@@ -363,11 +391,7 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) | |||
363 | continue; | 391 | continue; |
364 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) | 392 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
365 | continue; | 393 | continue; |
366 | if (((args->flags & ATTR_SECURE) != 0) != | 394 | if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
367 | ((sfe->flags & XFS_ATTR_SECURE) != 0)) | ||
368 | continue; | ||
369 | if (((args->flags & ATTR_ROOT) != 0) != | ||
370 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | ||
371 | continue; | 395 | continue; |
372 | return(XFS_ERROR(EEXIST)); | 396 | return(XFS_ERROR(EEXIST)); |
373 | } | 397 | } |
@@ -394,11 +418,7 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args) | |||
394 | continue; | 418 | continue; |
395 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) | 419 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
396 | continue; | 420 | continue; |
397 | if (((args->flags & ATTR_SECURE) != 0) != | 421 | if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
398 | ((sfe->flags & XFS_ATTR_SECURE) != 0)) | ||
399 | continue; | ||
400 | if (((args->flags & ATTR_ROOT) != 0) != | ||
401 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | ||
402 | continue; | 422 | continue; |
403 | if (args->flags & ATTR_KERNOVAL) { | 423 | if (args->flags & ATTR_KERNOVAL) { |
404 | args->valuelen = sfe->valuelen; | 424 | args->valuelen = sfe->valuelen; |
@@ -485,8 +505,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) | |||
485 | nargs.valuelen = sfe->valuelen; | 505 | nargs.valuelen = sfe->valuelen; |
486 | nargs.hashval = xfs_da_hashname((char *)sfe->nameval, | 506 | nargs.hashval = xfs_da_hashname((char *)sfe->nameval, |
487 | sfe->namelen); | 507 | sfe->namelen); |
488 | nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : | 508 | nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); |
489 | ((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); | ||
490 | error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ | 509 | error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ |
491 | ASSERT(error == ENOATTR); | 510 | ASSERT(error == ENOATTR); |
492 | error = xfs_attr_leaf_add(bp, &nargs); | 511 | error = xfs_attr_leaf_add(bp, &nargs); |
@@ -520,6 +539,10 @@ xfs_attr_shortform_compare(const void *a, const void *b) | |||
520 | } | 539 | } |
521 | } | 540 | } |
522 | 541 | ||
542 | |||
543 | #define XFS_ISRESET_CURSOR(cursor) \ | ||
544 | (!((cursor)->initted) && !((cursor)->hashval) && \ | ||
545 | !((cursor)->blkno) && !((cursor)->offset)) | ||
523 | /* | 546 | /* |
524 | * Copy out entries of shortform attribute lists for attr_list(). | 547 | * Copy out entries of shortform attribute lists for attr_list(). |
525 | * Shortform attribute lists are not stored in hashval sorted order. | 548 | * Shortform attribute lists are not stored in hashval sorted order. |
@@ -537,6 +560,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
537 | xfs_attr_sf_entry_t *sfe; | 560 | xfs_attr_sf_entry_t *sfe; |
538 | xfs_inode_t *dp; | 561 | xfs_inode_t *dp; |
539 | int sbsize, nsbuf, count, i; | 562 | int sbsize, nsbuf, count, i; |
563 | int error; | ||
540 | 564 | ||
541 | ASSERT(context != NULL); | 565 | ASSERT(context != NULL); |
542 | dp = context->dp; | 566 | dp = context->dp; |
@@ -552,46 +576,51 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
552 | xfs_attr_trace_l_c("sf start", context); | 576 | xfs_attr_trace_l_c("sf start", context); |
553 | 577 | ||
554 | /* | 578 | /* |
555 | * If the buffer is large enough, do not bother with sorting. | 579 | * If the buffer is large enough and the cursor is at the start, |
580 | * do not bother with sorting since we will return everything in | ||
581 | * one buffer and another call using the cursor won't need to be | ||
582 | * made. | ||
556 | * Note the generous fudge factor of 16 overhead bytes per entry. | 583 | * Note the generous fudge factor of 16 overhead bytes per entry. |
584 | * If bufsize is zero then put_listent must be a search function | ||
585 | * and can just scan through what we have. | ||
557 | */ | 586 | */ |
558 | if ((dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize) { | 587 | if (context->bufsize == 0 || |
588 | (XFS_ISRESET_CURSOR(cursor) && | ||
589 | (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) { | ||
559 | for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { | 590 | for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { |
560 | attrnames_t *namesp; | 591 | attrnames_t *namesp; |
561 | 592 | ||
562 | if (((context->flags & ATTR_SECURE) != 0) != | 593 | if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) { |
563 | ((sfe->flags & XFS_ATTR_SECURE) != 0) && | ||
564 | !(context->flags & ATTR_KERNORMALS)) { | ||
565 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); | ||
566 | continue; | ||
567 | } | ||
568 | if (((context->flags & ATTR_ROOT) != 0) != | ||
569 | ((sfe->flags & XFS_ATTR_ROOT) != 0) && | ||
570 | !(context->flags & ATTR_KERNROOTLS)) { | ||
571 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); | 594 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); |
572 | continue; | 595 | continue; |
573 | } | 596 | } |
574 | namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure: | 597 | namesp = xfs_attr_flags_namesp(sfe->flags); |
575 | ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : | 598 | error = context->put_listent(context, |
576 | &attr_user); | 599 | namesp, |
577 | if (context->flags & ATTR_KERNOVAL) { | 600 | (char *)sfe->nameval, |
578 | ASSERT(context->flags & ATTR_KERNAMELS); | 601 | (int)sfe->namelen, |
579 | context->count += namesp->attr_namelen + | 602 | (int)sfe->valuelen, |
580 | sfe->namelen + 1; | 603 | (char*)&sfe->nameval[sfe->namelen]); |
581 | } | 604 | |
582 | else { | 605 | /* |
583 | if (xfs_attr_put_listent(context, namesp, | 606 | * Either search callback finished early or |
584 | (char *)sfe->nameval, | 607 | * didn't fit it all in the buffer after all. |
585 | (int)sfe->namelen, | 608 | */ |
586 | (int)sfe->valuelen)) | 609 | if (context->seen_enough) |
587 | break; | 610 | break; |
588 | } | 611 | |
612 | if (error) | ||
613 | return error; | ||
589 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); | 614 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); |
590 | } | 615 | } |
591 | xfs_attr_trace_l_c("sf big-gulp", context); | 616 | xfs_attr_trace_l_c("sf big-gulp", context); |
592 | return(0); | 617 | return(0); |
593 | } | 618 | } |
594 | 619 | ||
620 | /* do no more for a search callback */ | ||
621 | if (context->bufsize == 0) | ||
622 | return 0; | ||
623 | |||
595 | /* | 624 | /* |
596 | * It didn't all fit, so we have to sort everything on hashval. | 625 | * It didn't all fit, so we have to sort everything on hashval. |
597 | */ | 626 | */ |
@@ -614,15 +643,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
614 | kmem_free(sbuf, sbsize); | 643 | kmem_free(sbuf, sbsize); |
615 | return XFS_ERROR(EFSCORRUPTED); | 644 | return XFS_ERROR(EFSCORRUPTED); |
616 | } | 645 | } |
617 | if (((context->flags & ATTR_SECURE) != 0) != | 646 | if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) { |
618 | ((sfe->flags & XFS_ATTR_SECURE) != 0) && | ||
619 | !(context->flags & ATTR_KERNORMALS)) { | ||
620 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); | ||
621 | continue; | ||
622 | } | ||
623 | if (((context->flags & ATTR_ROOT) != 0) != | ||
624 | ((sfe->flags & XFS_ATTR_ROOT) != 0) && | ||
625 | !(context->flags & ATTR_KERNROOTLS)) { | ||
626 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); | 647 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe); |
627 | continue; | 648 | continue; |
628 | } | 649 | } |
@@ -671,24 +692,22 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
671 | for ( ; i < nsbuf; i++, sbp++) { | 692 | for ( ; i < nsbuf; i++, sbp++) { |
672 | attrnames_t *namesp; | 693 | attrnames_t *namesp; |
673 | 694 | ||
674 | namesp = (sbp->flags & XFS_ATTR_SECURE) ? &attr_secure : | 695 | namesp = xfs_attr_flags_namesp(sbp->flags); |
675 | ((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted : | ||
676 | &attr_user); | ||
677 | 696 | ||
678 | if (cursor->hashval != sbp->hash) { | 697 | if (cursor->hashval != sbp->hash) { |
679 | cursor->hashval = sbp->hash; | 698 | cursor->hashval = sbp->hash; |
680 | cursor->offset = 0; | 699 | cursor->offset = 0; |
681 | } | 700 | } |
682 | if (context->flags & ATTR_KERNOVAL) { | 701 | error = context->put_listent(context, |
683 | ASSERT(context->flags & ATTR_KERNAMELS); | 702 | namesp, |
684 | context->count += namesp->attr_namelen + | 703 | sbp->name, |
685 | sbp->namelen + 1; | 704 | sbp->namelen, |
686 | } else { | 705 | sbp->valuelen, |
687 | if (xfs_attr_put_listent(context, namesp, | 706 | &sbp->name[sbp->namelen]); |
688 | sbp->name, sbp->namelen, | 707 | if (error) |
689 | sbp->valuelen)) | 708 | return error; |
690 | break; | 709 | if (context->seen_enough) |
691 | } | 710 | break; |
692 | cursor->offset++; | 711 | cursor->offset++; |
693 | } | 712 | } |
694 | 713 | ||
@@ -810,8 +829,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) | |||
810 | nargs.value = (char *)&name_loc->nameval[nargs.namelen]; | 829 | nargs.value = (char *)&name_loc->nameval[nargs.namelen]; |
811 | nargs.valuelen = be16_to_cpu(name_loc->valuelen); | 830 | nargs.valuelen = be16_to_cpu(name_loc->valuelen); |
812 | nargs.hashval = be32_to_cpu(entry->hashval); | 831 | nargs.hashval = be32_to_cpu(entry->hashval); |
813 | nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : | 832 | nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags); |
814 | ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); | ||
815 | xfs_attr_shortform_add(&nargs, forkoff); | 833 | xfs_attr_shortform_add(&nargs, forkoff); |
816 | } | 834 | } |
817 | error = 0; | 835 | error = 0; |
@@ -1098,8 +1116,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) | |||
1098 | be16_to_cpu(map->size)); | 1116 | be16_to_cpu(map->size)); |
1099 | entry->hashval = cpu_to_be32(args->hashval); | 1117 | entry->hashval = cpu_to_be32(args->hashval); |
1100 | entry->flags = tmp ? XFS_ATTR_LOCAL : 0; | 1118 | entry->flags = tmp ? XFS_ATTR_LOCAL : 0; |
1101 | entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : | 1119 | entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); |
1102 | ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); | ||
1103 | if (args->rename) { | 1120 | if (args->rename) { |
1104 | entry->flags |= XFS_ATTR_INCOMPLETE; | 1121 | entry->flags |= XFS_ATTR_INCOMPLETE; |
1105 | if ((args->blkno2 == args->blkno) && | 1122 | if ((args->blkno2 == args->blkno) && |
@@ -1926,7 +1943,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
1926 | else | 1943 | else |
1927 | break; | 1944 | break; |
1928 | } | 1945 | } |
1929 | ASSERT((probe >= 0) && | 1946 | ASSERT((probe >= 0) && |
1930 | (!leaf->hdr.count | 1947 | (!leaf->hdr.count |
1931 | || (probe < be16_to_cpu(leaf->hdr.count)))); | 1948 | || (probe < be16_to_cpu(leaf->hdr.count)))); |
1932 | ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); | 1949 | ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); |
@@ -1971,14 +1988,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
1971 | name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe); | 1988 | name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe); |
1972 | if (name_loc->namelen != args->namelen) | 1989 | if (name_loc->namelen != args->namelen) |
1973 | continue; | 1990 | continue; |
1974 | if (memcmp(args->name, (char *)name_loc->nameval, | 1991 | if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) |
1975 | args->namelen) != 0) | ||
1976 | continue; | 1992 | continue; |
1977 | if (((args->flags & ATTR_SECURE) != 0) != | 1993 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
1978 | ((entry->flags & XFS_ATTR_SECURE) != 0)) | ||
1979 | continue; | ||
1980 | if (((args->flags & ATTR_ROOT) != 0) != | ||
1981 | ((entry->flags & XFS_ATTR_ROOT) != 0)) | ||
1982 | continue; | 1994 | continue; |
1983 | args->index = probe; | 1995 | args->index = probe; |
1984 | return(XFS_ERROR(EEXIST)); | 1996 | return(XFS_ERROR(EEXIST)); |
@@ -1989,11 +2001,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
1989 | if (memcmp(args->name, (char *)name_rmt->name, | 2001 | if (memcmp(args->name, (char *)name_rmt->name, |
1990 | args->namelen) != 0) | 2002 | args->namelen) != 0) |
1991 | continue; | 2003 | continue; |
1992 | if (((args->flags & ATTR_SECURE) != 0) != | 2004 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
1993 | ((entry->flags & XFS_ATTR_SECURE) != 0)) | ||
1994 | continue; | ||
1995 | if (((args->flags & ATTR_ROOT) != 0) != | ||
1996 | ((entry->flags & XFS_ATTR_ROOT) != 0)) | ||
1997 | continue; | 2005 | continue; |
1998 | args->index = probe; | 2006 | args->index = probe; |
1999 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); | 2007 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
@@ -2312,8 +2320,6 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) | |||
2312 | attrlist_cursor_kern_t *cursor; | 2320 | attrlist_cursor_kern_t *cursor; |
2313 | xfs_attr_leafblock_t *leaf; | 2321 | xfs_attr_leafblock_t *leaf; |
2314 | xfs_attr_leaf_entry_t *entry; | 2322 | xfs_attr_leaf_entry_t *entry; |
2315 | xfs_attr_leaf_name_local_t *name_loc; | ||
2316 | xfs_attr_leaf_name_remote_t *name_rmt; | ||
2317 | int retval, i; | 2323 | int retval, i; |
2318 | 2324 | ||
2319 | ASSERT(bp != NULL); | 2325 | ASSERT(bp != NULL); |
@@ -2355,9 +2361,8 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) | |||
2355 | * We have found our place, start copying out the new attributes. | 2361 | * We have found our place, start copying out the new attributes. |
2356 | */ | 2362 | */ |
2357 | retval = 0; | 2363 | retval = 0; |
2358 | for ( ; (i < be16_to_cpu(leaf->hdr.count)) | 2364 | for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) { |
2359 | && (retval == 0); entry++, i++) { | 2365 | attrnames_t *namesp; |
2360 | attrnames_t *namesp; | ||
2361 | 2366 | ||
2362 | if (be32_to_cpu(entry->hashval) != cursor->hashval) { | 2367 | if (be32_to_cpu(entry->hashval) != cursor->hashval) { |
2363 | cursor->hashval = be32_to_cpu(entry->hashval); | 2368 | cursor->hashval = be32_to_cpu(entry->hashval); |
@@ -2366,115 +2371,69 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) | |||
2366 | 2371 | ||
2367 | if (entry->flags & XFS_ATTR_INCOMPLETE) | 2372 | if (entry->flags & XFS_ATTR_INCOMPLETE) |
2368 | continue; /* skip incomplete entries */ | 2373 | continue; /* skip incomplete entries */ |
2369 | if (((context->flags & ATTR_SECURE) != 0) != | 2374 | if (!xfs_attr_namesp_match_overrides(context->flags, entry->flags)) |
2370 | ((entry->flags & XFS_ATTR_SECURE) != 0) && | 2375 | continue; |
2371 | !(context->flags & ATTR_KERNORMALS)) | 2376 | |
2372 | continue; /* skip non-matching entries */ | 2377 | namesp = xfs_attr_flags_namesp(entry->flags); |
2373 | if (((context->flags & ATTR_ROOT) != 0) != | ||
2374 | ((entry->flags & XFS_ATTR_ROOT) != 0) && | ||
2375 | !(context->flags & ATTR_KERNROOTLS)) | ||
2376 | continue; /* skip non-matching entries */ | ||
2377 | |||
2378 | namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure : | ||
2379 | ((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : | ||
2380 | &attr_user); | ||
2381 | 2378 | ||
2382 | if (entry->flags & XFS_ATTR_LOCAL) { | 2379 | if (entry->flags & XFS_ATTR_LOCAL) { |
2383 | name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); | 2380 | xfs_attr_leaf_name_local_t *name_loc = |
2384 | if (context->flags & ATTR_KERNOVAL) { | 2381 | XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); |
2385 | ASSERT(context->flags & ATTR_KERNAMELS); | 2382 | |
2386 | context->count += namesp->attr_namelen + | 2383 | retval = context->put_listent(context, |
2387 | (int)name_loc->namelen + 1; | 2384 | namesp, |
2388 | } else { | 2385 | (char *)name_loc->nameval, |
2389 | retval = xfs_attr_put_listent(context, namesp, | 2386 | (int)name_loc->namelen, |
2390 | (char *)name_loc->nameval, | 2387 | be16_to_cpu(name_loc->valuelen), |
2391 | (int)name_loc->namelen, | 2388 | (char *)&name_loc->nameval[name_loc->namelen]); |
2392 | be16_to_cpu(name_loc->valuelen)); | 2389 | if (retval) |
2393 | } | 2390 | return retval; |
2394 | } else { | 2391 | } else { |
2395 | name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i); | 2392 | xfs_attr_leaf_name_remote_t *name_rmt = |
2396 | if (context->flags & ATTR_KERNOVAL) { | 2393 | XFS_ATTR_LEAF_NAME_REMOTE(leaf, i); |
2397 | ASSERT(context->flags & ATTR_KERNAMELS); | 2394 | |
2398 | context->count += namesp->attr_namelen + | 2395 | int valuelen = be32_to_cpu(name_rmt->valuelen); |
2399 | (int)name_rmt->namelen + 1; | 2396 | |
2400 | } else { | 2397 | if (context->put_value) { |
2401 | retval = xfs_attr_put_listent(context, namesp, | 2398 | xfs_da_args_t args; |
2402 | (char *)name_rmt->name, | 2399 | |
2403 | (int)name_rmt->namelen, | 2400 | memset((char *)&args, 0, sizeof(args)); |
2404 | be32_to_cpu(name_rmt->valuelen)); | 2401 | args.dp = context->dp; |
2402 | args.whichfork = XFS_ATTR_FORK; | ||
2403 | args.valuelen = valuelen; | ||
2404 | args.value = kmem_alloc(valuelen, KM_SLEEP); | ||
2405 | args.rmtblkno = be32_to_cpu(name_rmt->valueblk); | ||
2406 | args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen); | ||
2407 | retval = xfs_attr_rmtval_get(&args); | ||
2408 | if (retval) | ||
2409 | return retval; | ||
2410 | retval = context->put_listent(context, | ||
2411 | namesp, | ||
2412 | (char *)name_rmt->name, | ||
2413 | (int)name_rmt->namelen, | ||
2414 | valuelen, | ||
2415 | (char*)args.value); | ||
2416 | kmem_free(args.value, valuelen); | ||
2405 | } | 2417 | } |
2418 | else { | ||
2419 | retval = context->put_listent(context, | ||
2420 | namesp, | ||
2421 | (char *)name_rmt->name, | ||
2422 | (int)name_rmt->namelen, | ||
2423 | valuelen, | ||
2424 | NULL); | ||
2425 | } | ||
2426 | if (retval) | ||
2427 | return retval; | ||
2406 | } | 2428 | } |
2407 | if (retval == 0) { | 2429 | if (context->seen_enough) |
2408 | cursor->offset++; | 2430 | break; |
2409 | } | 2431 | cursor->offset++; |
2410 | } | 2432 | } |
2411 | xfs_attr_trace_l_cl("blk end", context, leaf); | 2433 | xfs_attr_trace_l_cl("blk end", context, leaf); |
2412 | return(retval); | 2434 | return(retval); |
2413 | } | 2435 | } |
2414 | 2436 | ||
2415 | #define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \ | ||
2416 | (((struct attrlist_ent *) 0)->a_name - (char *) 0) | ||
2417 | #define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \ | ||
2418 | ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \ | ||
2419 | & ~(sizeof(u_int32_t)-1)) | ||
2420 | |||
2421 | /* | ||
2422 | * Format an attribute and copy it out to the user's buffer. | ||
2423 | * Take care to check values and protect against them changing later, | ||
2424 | * we may be reading them directly out of a user buffer. | ||
2425 | */ | ||
2426 | /*ARGSUSED*/ | ||
2427 | STATIC int | ||
2428 | xfs_attr_put_listent(xfs_attr_list_context_t *context, | ||
2429 | attrnames_t *namesp, char *name, int namelen, int valuelen) | ||
2430 | { | ||
2431 | attrlist_ent_t *aep; | ||
2432 | int arraytop; | ||
2433 | |||
2434 | ASSERT(!(context->flags & ATTR_KERNOVAL)); | ||
2435 | if (context->flags & ATTR_KERNAMELS) { | ||
2436 | char *offset; | ||
2437 | |||
2438 | ASSERT(context->count >= 0); | ||
2439 | |||
2440 | arraytop = context->count + namesp->attr_namelen + namelen + 1; | ||
2441 | if (arraytop > context->firstu) { | ||
2442 | context->count = -1; /* insufficient space */ | ||
2443 | return(1); | ||
2444 | } | ||
2445 | offset = (char *)context->alist + context->count; | ||
2446 | strncpy(offset, namesp->attr_name, namesp->attr_namelen); | ||
2447 | offset += namesp->attr_namelen; | ||
2448 | strncpy(offset, name, namelen); /* real name */ | ||
2449 | offset += namelen; | ||
2450 | *offset = '\0'; | ||
2451 | context->count += namesp->attr_namelen + namelen + 1; | ||
2452 | return(0); | ||
2453 | } | ||
2454 | |||
2455 | ASSERT(context->count >= 0); | ||
2456 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); | ||
2457 | ASSERT(context->firstu >= sizeof(*context->alist)); | ||
2458 | ASSERT(context->firstu <= context->bufsize); | ||
2459 | |||
2460 | arraytop = sizeof(*context->alist) + | ||
2461 | context->count * sizeof(context->alist->al_offset[0]); | ||
2462 | context->firstu -= ATTR_ENTSIZE(namelen); | ||
2463 | if (context->firstu < arraytop) { | ||
2464 | xfs_attr_trace_l_c("buffer full", context); | ||
2465 | context->alist->al_more = 1; | ||
2466 | return(1); | ||
2467 | } | ||
2468 | |||
2469 | aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); | ||
2470 | aep->a_valuelen = valuelen; | ||
2471 | memcpy(aep->a_name, name, namelen); | ||
2472 | aep->a_name[ namelen ] = 0; | ||
2473 | context->alist->al_offset[ context->count++ ] = context->firstu; | ||
2474 | context->alist->al_count = context->count; | ||
2475 | xfs_attr_trace_l_c("add", context); | ||
2476 | return(0); | ||
2477 | } | ||
2478 | 2437 | ||
2479 | /*======================================================================== | 2438 | /*======================================================================== |
2480 | * Manage the INCOMPLETE flag in a leaf entry | 2439 | * Manage the INCOMPLETE flag in a leaf entry |
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 51c3ee156b2f..040f732ce1e2 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h | |||
@@ -130,6 +130,19 @@ typedef struct xfs_attr_leafblock { | |||
130 | #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) | 130 | #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * Conversion macros for converting namespace bits from argument flags | ||
134 | * to ondisk flags. | ||
135 | */ | ||
136 | #define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE) | ||
137 | #define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) | ||
138 | #define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK) | ||
139 | #define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK) | ||
140 | #define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\ | ||
141 | ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0)) | ||
142 | #define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\ | ||
143 | ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0)) | ||
144 | |||
145 | /* | ||
133 | * Alignment for namelist and valuelist entries (since they are mixed | 146 | * Alignment for namelist and valuelist entries (since they are mixed |
134 | * there can be only one alignment value) | 147 | * there can be only one alignment value) |
135 | */ | 148 | */ |
@@ -196,16 +209,26 @@ static inline int xfs_attr_leaf_entsize_local_max(int bsize) | |||
196 | * Structure used to pass context around among the routines. | 209 | * Structure used to pass context around among the routines. |
197 | *========================================================================*/ | 210 | *========================================================================*/ |
198 | 211 | ||
212 | |||
213 | struct xfs_attr_list_context; | ||
214 | |||
215 | typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, struct attrnames *, | ||
216 | char *, int, int, char *); | ||
217 | |||
199 | typedef struct xfs_attr_list_context { | 218 | typedef struct xfs_attr_list_context { |
200 | struct xfs_inode *dp; /* inode */ | 219 | struct xfs_inode *dp; /* inode */ |
201 | struct attrlist_cursor_kern *cursor;/* position in list */ | 220 | struct attrlist_cursor_kern *cursor; /* position in list */ |
202 | struct attrlist *alist; /* output buffer */ | 221 | struct attrlist *alist; /* output buffer */ |
203 | int count; /* num used entries */ | 222 | int seen_enough; /* T/F: seen enough of list? */ |
204 | int dupcnt; /* count dup hashvals seen */ | 223 | int count; /* num used entries */ |
205 | int bufsize;/* total buffer size */ | 224 | int dupcnt; /* count dup hashvals seen */ |
206 | int firstu; /* first used byte in buffer */ | 225 | int bufsize; /* total buffer size */ |
207 | int flags; /* from VOP call */ | 226 | int firstu; /* first used byte in buffer */ |
208 | int resynch;/* T/F: resynch with cursor */ | 227 | int flags; /* from VOP call */ |
228 | int resynch; /* T/F: resynch with cursor */ | ||
229 | int put_value; /* T/F: need value for listent */ | ||
230 | put_listent_func_t put_listent; /* list output fmt function */ | ||
231 | int index; /* index into output buffer */ | ||
209 | } xfs_attr_list_context_t; | 232 | } xfs_attr_list_context_t; |
210 | 233 | ||
211 | /* | 234 | /* |