diff options
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 351 |
1 files changed, 155 insertions, 196 deletions
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 |