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 |
