aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr_leaf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r--fs/xfs/xfs_attr_leaf.c300
1 files changed, 0 insertions, 300 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index e6497d0c2a72..90c033e41eb9 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -752,182 +752,6 @@ out:
752 return(error); 752 return(error);
753} 753}
754 754
755STATIC int
756xfs_attr_shortform_compare(const void *a, const void *b)
757{
758 xfs_attr_sf_sort_t *sa, *sb;
759
760 sa = (xfs_attr_sf_sort_t *)a;
761 sb = (xfs_attr_sf_sort_t *)b;
762 if (sa->hash < sb->hash) {
763 return(-1);
764 } else if (sa->hash > sb->hash) {
765 return(1);
766 } else {
767 return(sa->entno - sb->entno);
768 }
769}
770
771
772#define XFS_ISRESET_CURSOR(cursor) \
773 (!((cursor)->initted) && !((cursor)->hashval) && \
774 !((cursor)->blkno) && !((cursor)->offset))
775/*
776 * Copy out entries of shortform attribute lists for attr_list().
777 * Shortform attribute lists are not stored in hashval sorted order.
778 * If the output buffer is not large enough to hold them all, then we
779 * we have to calculate each entries' hashvalue and sort them before
780 * we can begin returning them to the user.
781 */
782/*ARGSUSED*/
783int
784xfs_attr_shortform_list(xfs_attr_list_context_t *context)
785{
786 attrlist_cursor_kern_t *cursor;
787 xfs_attr_sf_sort_t *sbuf, *sbp;
788 xfs_attr_shortform_t *sf;
789 xfs_attr_sf_entry_t *sfe;
790 xfs_inode_t *dp;
791 int sbsize, nsbuf, count, i;
792 int error;
793
794 ASSERT(context != NULL);
795 dp = context->dp;
796 ASSERT(dp != NULL);
797 ASSERT(dp->i_afp != NULL);
798 sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
799 ASSERT(sf != NULL);
800 if (!sf->hdr.count)
801 return(0);
802 cursor = context->cursor;
803 ASSERT(cursor != NULL);
804
805 trace_xfs_attr_list_sf(context);
806
807 /*
808 * If the buffer is large enough and the cursor is at the start,
809 * do not bother with sorting since we will return everything in
810 * one buffer and another call using the cursor won't need to be
811 * made.
812 * Note the generous fudge factor of 16 overhead bytes per entry.
813 * If bufsize is zero then put_listent must be a search function
814 * and can just scan through what we have.
815 */
816 if (context->bufsize == 0 ||
817 (XFS_ISRESET_CURSOR(cursor) &&
818 (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
819 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
820 error = context->put_listent(context,
821 sfe->flags,
822 sfe->nameval,
823 (int)sfe->namelen,
824 (int)sfe->valuelen,
825 &sfe->nameval[sfe->namelen]);
826
827 /*
828 * Either search callback finished early or
829 * didn't fit it all in the buffer after all.
830 */
831 if (context->seen_enough)
832 break;
833
834 if (error)
835 return error;
836 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
837 }
838 trace_xfs_attr_list_sf_all(context);
839 return(0);
840 }
841
842 /* do no more for a search callback */
843 if (context->bufsize == 0)
844 return 0;
845
846 /*
847 * It didn't all fit, so we have to sort everything on hashval.
848 */
849 sbsize = sf->hdr.count * sizeof(*sbuf);
850 sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP | KM_NOFS);
851
852 /*
853 * Scan the attribute list for the rest of the entries, storing
854 * the relevant info from only those that match into a buffer.
855 */
856 nsbuf = 0;
857 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
858 if (unlikely(
859 ((char *)sfe < (char *)sf) ||
860 ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
861 XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
862 XFS_ERRLEVEL_LOW,
863 context->dp->i_mount, sfe);
864 kmem_free(sbuf);
865 return XFS_ERROR(EFSCORRUPTED);
866 }
867
868 sbp->entno = i;
869 sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen);
870 sbp->name = sfe->nameval;
871 sbp->namelen = sfe->namelen;
872 /* These are bytes, and both on-disk, don't endian-flip */
873 sbp->valuelen = sfe->valuelen;
874 sbp->flags = sfe->flags;
875 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
876 sbp++;
877 nsbuf++;
878 }
879
880 /*
881 * Sort the entries on hash then entno.
882 */
883 xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
884
885 /*
886 * Re-find our place IN THE SORTED LIST.
887 */
888 count = 0;
889 cursor->initted = 1;
890 cursor->blkno = 0;
891 for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {
892 if (sbp->hash == cursor->hashval) {
893 if (cursor->offset == count) {
894 break;
895 }
896 count++;
897 } else if (sbp->hash > cursor->hashval) {
898 break;
899 }
900 }
901 if (i == nsbuf) {
902 kmem_free(sbuf);
903 return(0);
904 }
905
906 /*
907 * Loop putting entries into the user buffer.
908 */
909 for ( ; i < nsbuf; i++, sbp++) {
910 if (cursor->hashval != sbp->hash) {
911 cursor->hashval = sbp->hash;
912 cursor->offset = 0;
913 }
914 error = context->put_listent(context,
915 sbp->flags,
916 sbp->name,
917 sbp->namelen,
918 sbp->valuelen,
919 &sbp->name[sbp->namelen]);
920 if (error)
921 return error;
922 if (context->seen_enough)
923 break;
924 cursor->offset++;
925 }
926
927 kmem_free(sbuf);
928 return(0);
929}
930
931/* 755/*
932 * Check a leaf attribute block to see if all the entries would fit into 756 * Check a leaf attribute block to see if all the entries would fit into
933 * a shortform attribute list. 757 * a shortform attribute list.
@@ -2644,130 +2468,6 @@ xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local)
2644 return size; 2468 return size;
2645} 2469}
2646 2470
2647/*
2648 * Copy out attribute list entries for attr_list(), for leaf attribute lists.
2649 */
2650int
2651xfs_attr3_leaf_list_int(
2652 struct xfs_buf *bp,
2653 struct xfs_attr_list_context *context)
2654{
2655 struct attrlist_cursor_kern *cursor;
2656 struct xfs_attr_leafblock *leaf;
2657 struct xfs_attr3_icleaf_hdr ichdr;
2658 struct xfs_attr_leaf_entry *entries;
2659 struct xfs_attr_leaf_entry *entry;
2660 int retval;
2661 int i;
2662
2663 trace_xfs_attr_list_leaf(context);
2664
2665 leaf = bp->b_addr;
2666 xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
2667 entries = xfs_attr3_leaf_entryp(leaf);
2668
2669 cursor = context->cursor;
2670 cursor->initted = 1;
2671
2672 /*
2673 * Re-find our place in the leaf block if this is a new syscall.
2674 */
2675 if (context->resynch) {
2676 entry = &entries[0];
2677 for (i = 0; i < ichdr.count; entry++, i++) {
2678 if (be32_to_cpu(entry->hashval) == cursor->hashval) {
2679 if (cursor->offset == context->dupcnt) {
2680 context->dupcnt = 0;
2681 break;
2682 }
2683 context->dupcnt++;
2684 } else if (be32_to_cpu(entry->hashval) >
2685 cursor->hashval) {
2686 context->dupcnt = 0;
2687 break;
2688 }
2689 }
2690 if (i == ichdr.count) {
2691 trace_xfs_attr_list_notfound(context);
2692 return 0;
2693 }
2694 } else {
2695 entry = &entries[0];
2696 i = 0;
2697 }
2698 context->resynch = 0;
2699
2700 /*
2701 * We have found our place, start copying out the new attributes.
2702 */
2703 retval = 0;
2704 for (; i < ichdr.count; entry++, i++) {
2705 if (be32_to_cpu(entry->hashval) != cursor->hashval) {
2706 cursor->hashval = be32_to_cpu(entry->hashval);
2707 cursor->offset = 0;
2708 }
2709
2710 if (entry->flags & XFS_ATTR_INCOMPLETE)
2711 continue; /* skip incomplete entries */
2712
2713 if (entry->flags & XFS_ATTR_LOCAL) {
2714 xfs_attr_leaf_name_local_t *name_loc =
2715 xfs_attr3_leaf_name_local(leaf, i);
2716
2717 retval = context->put_listent(context,
2718 entry->flags,
2719 name_loc->nameval,
2720 (int)name_loc->namelen,
2721 be16_to_cpu(name_loc->valuelen),
2722 &name_loc->nameval[name_loc->namelen]);
2723 if (retval)
2724 return retval;
2725 } else {
2726 xfs_attr_leaf_name_remote_t *name_rmt =
2727 xfs_attr3_leaf_name_remote(leaf, i);
2728
2729 int valuelen = be32_to_cpu(name_rmt->valuelen);
2730
2731 if (context->put_value) {
2732 xfs_da_args_t args;
2733
2734 memset((char *)&args, 0, sizeof(args));
2735 args.dp = context->dp;
2736 args.whichfork = XFS_ATTR_FORK;
2737 args.valuelen = valuelen;
2738 args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS);
2739 args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
2740 args.rmtblkcnt = xfs_attr3_rmt_blocks(
2741 args.dp->i_mount, valuelen);
2742 retval = xfs_attr_rmtval_get(&args);
2743 if (retval)
2744 return retval;
2745 retval = context->put_listent(context,
2746 entry->flags,
2747 name_rmt->name,
2748 (int)name_rmt->namelen,
2749 valuelen,
2750 args.value);
2751 kmem_free(args.value);
2752 } else {
2753 retval = context->put_listent(context,
2754 entry->flags,
2755 name_rmt->name,
2756 (int)name_rmt->namelen,
2757 valuelen,
2758 NULL);
2759 }
2760 if (retval)
2761 return retval;
2762 }
2763 if (context->seen_enough)
2764 break;
2765 cursor->offset++;
2766 }
2767 trace_xfs_attr_list_leaf_end(context);
2768 return retval;
2769}
2770
2771 2471
2772/*======================================================================== 2472/*========================================================================
2773 * Manage the INCOMPLETE flag in a leaf entry 2473 * Manage the INCOMPLETE flag in a leaf entry