diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-10-27 18:18:29 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:18 -0500 |
commit | 178eeac354ea28828d5e94a3a7b51368c171d6a5 (patch) | |
tree | 8e3d7b2c923ea2260344dbe76d0b128031ba93c9 /fs/ocfs2/xattr.c | |
parent | e2356a3f02cfdbce735465a2b40b6dc72a764c26 (diff) |
ocfs2: Use buckets in ocfs2_xattr_create_index_block().
Use the ocfs2_xattr_bucket abstraction in
ocfs2_xattr_create_index_block() and its helpers. We get more efficient
reads, a lot less buffer_head munging, and nicer code to boot. While
we're at it, ocfs2_xattr_update_xattr_search() becomes void.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 114 |
1 files changed, 32 insertions, 82 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 46986c635eb8..76969b922002 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -2649,32 +2649,34 @@ static void swap_xe(void *a, void *b, int size) | |||
2649 | /* | 2649 | /* |
2650 | * When the ocfs2_xattr_block is filled up, new bucket will be created | 2650 | * When the ocfs2_xattr_block is filled up, new bucket will be created |
2651 | * and all the xattr entries will be moved to the new bucket. | 2651 | * and all the xattr entries will be moved to the new bucket. |
2652 | * The header goes at the start of the bucket, and the names+values are | ||
2653 | * filled from the end. This is why *target starts as the last buffer. | ||
2652 | * Note: we need to sort the entries since they are not saved in order | 2654 | * Note: we need to sort the entries since they are not saved in order |
2653 | * in the ocfs2_xattr_block. | 2655 | * in the ocfs2_xattr_block. |
2654 | */ | 2656 | */ |
2655 | static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | 2657 | static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, |
2656 | struct buffer_head *xb_bh, | 2658 | struct buffer_head *xb_bh, |
2657 | struct buffer_head *xh_bh, | 2659 | struct ocfs2_xattr_bucket *bucket) |
2658 | struct buffer_head *data_bh) | ||
2659 | { | 2660 | { |
2660 | int i, blocksize = inode->i_sb->s_blocksize; | 2661 | int i, blocksize = inode->i_sb->s_blocksize; |
2662 | int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
2661 | u16 offset, size, off_change; | 2663 | u16 offset, size, off_change; |
2662 | struct ocfs2_xattr_entry *xe; | 2664 | struct ocfs2_xattr_entry *xe; |
2663 | struct ocfs2_xattr_block *xb = | 2665 | struct ocfs2_xattr_block *xb = |
2664 | (struct ocfs2_xattr_block *)xb_bh->b_data; | 2666 | (struct ocfs2_xattr_block *)xb_bh->b_data; |
2665 | struct ocfs2_xattr_header *xb_xh = &xb->xb_attrs.xb_header; | 2667 | struct ocfs2_xattr_header *xb_xh = &xb->xb_attrs.xb_header; |
2666 | struct ocfs2_xattr_header *xh = | 2668 | struct ocfs2_xattr_header *xh = bucket_xh(bucket); |
2667 | (struct ocfs2_xattr_header *)xh_bh->b_data; | ||
2668 | u16 count = le16_to_cpu(xb_xh->xh_count); | 2669 | u16 count = le16_to_cpu(xb_xh->xh_count); |
2669 | char *target = xh_bh->b_data, *src = xb_bh->b_data; | 2670 | char *src = xb_bh->b_data; |
2671 | char *target = bucket_block(bucket, blks - 1); | ||
2670 | 2672 | ||
2671 | mlog(0, "cp xattr from block %llu to bucket %llu\n", | 2673 | mlog(0, "cp xattr from block %llu to bucket %llu\n", |
2672 | (unsigned long long)xb_bh->b_blocknr, | 2674 | (unsigned long long)xb_bh->b_blocknr, |
2673 | (unsigned long long)xh_bh->b_blocknr); | 2675 | (unsigned long long)bucket_blkno(bucket)); |
2676 | |||
2677 | for (i = 0; i < blks; i++) | ||
2678 | memset(bucket_block(bucket, i), 0, blocksize); | ||
2674 | 2679 | ||
2675 | memset(xh_bh->b_data, 0, blocksize); | ||
2676 | if (data_bh) | ||
2677 | memset(data_bh->b_data, 0, blocksize); | ||
2678 | /* | 2680 | /* |
2679 | * Since the xe_name_offset is based on ocfs2_xattr_header, | 2681 | * Since the xe_name_offset is based on ocfs2_xattr_header, |
2680 | * there is a offset change corresponding to the change of | 2682 | * there is a offset change corresponding to the change of |
@@ -2686,8 +2688,6 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |||
2686 | size = blocksize - offset; | 2688 | size = blocksize - offset; |
2687 | 2689 | ||
2688 | /* copy all the names and values. */ | 2690 | /* copy all the names and values. */ |
2689 | if (data_bh) | ||
2690 | target = data_bh->b_data; | ||
2691 | memcpy(target + offset, src + offset, size); | 2691 | memcpy(target + offset, src + offset, size); |
2692 | 2692 | ||
2693 | /* Init new header now. */ | 2693 | /* Init new header now. */ |
@@ -2697,7 +2697,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |||
2697 | xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE - size); | 2697 | xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE - size); |
2698 | 2698 | ||
2699 | /* copy all the entries. */ | 2699 | /* copy all the entries. */ |
2700 | target = xh_bh->b_data; | 2700 | target = bucket_block(bucket, 0); |
2701 | offset = offsetof(struct ocfs2_xattr_header, xh_entries); | 2701 | offset = offsetof(struct ocfs2_xattr_header, xh_entries); |
2702 | size = count * sizeof(struct ocfs2_xattr_entry); | 2702 | size = count * sizeof(struct ocfs2_xattr_entry); |
2703 | memcpy(target + offset, (char *)xb_xh + offset, size); | 2703 | memcpy(target + offset, (char *)xb_xh + offset, size); |
@@ -2723,42 +2723,24 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |||
2723 | * While if the entry is in index b-tree, "bucket" indicates the | 2723 | * While if the entry is in index b-tree, "bucket" indicates the |
2724 | * real place of the xattr. | 2724 | * real place of the xattr. |
2725 | */ | 2725 | */ |
2726 | static int ocfs2_xattr_update_xattr_search(struct inode *inode, | 2726 | static void ocfs2_xattr_update_xattr_search(struct inode *inode, |
2727 | struct ocfs2_xattr_search *xs, | 2727 | struct ocfs2_xattr_search *xs, |
2728 | struct buffer_head *old_bh, | 2728 | struct buffer_head *old_bh) |
2729 | struct buffer_head *new_bh) | ||
2730 | { | 2729 | { |
2731 | int ret = 0; | ||
2732 | char *buf = old_bh->b_data; | 2730 | char *buf = old_bh->b_data; |
2733 | struct ocfs2_xattr_block *old_xb = (struct ocfs2_xattr_block *)buf; | 2731 | struct ocfs2_xattr_block *old_xb = (struct ocfs2_xattr_block *)buf; |
2734 | struct ocfs2_xattr_header *old_xh = &old_xb->xb_attrs.xb_header; | 2732 | struct ocfs2_xattr_header *old_xh = &old_xb->xb_attrs.xb_header; |
2735 | int i, blocksize = inode->i_sb->s_blocksize; | 2733 | int i; |
2736 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
2737 | 2734 | ||
2738 | xs->bucket->bu_bhs[0] = new_bh; | ||
2739 | get_bh(new_bh); | ||
2740 | xs->header = bucket_xh(xs->bucket); | 2735 | xs->header = bucket_xh(xs->bucket); |
2741 | 2736 | xs->base = bucket_block(xs->bucket, 0); | |
2742 | xs->base = new_bh->b_data; | ||
2743 | xs->end = xs->base + inode->i_sb->s_blocksize; | 2737 | xs->end = xs->base + inode->i_sb->s_blocksize; |
2744 | 2738 | ||
2745 | if (!xs->not_found) { | 2739 | if (xs->not_found) |
2746 | if (OCFS2_XATTR_BUCKET_SIZE != blocksize) { | 2740 | return; |
2747 | ret = ocfs2_read_blocks(inode, | ||
2748 | bucket_blkno(xs->bucket) + 1, | ||
2749 | blk_per_bucket - 1, &xs->bucket->bu_bhs[1], | ||
2750 | 0); | ||
2751 | if (ret) { | ||
2752 | mlog_errno(ret); | ||
2753 | return ret; | ||
2754 | } | ||
2755 | |||
2756 | } | ||
2757 | i = xs->here - old_xh->xh_entries; | ||
2758 | xs->here = &xs->header->xh_entries[i]; | ||
2759 | } | ||
2760 | 2741 | ||
2761 | return ret; | 2742 | i = xs->here - old_xh->xh_entries; |
2743 | xs->here = &xs->header->xh_entries[i]; | ||
2762 | } | 2744 | } |
2763 | 2745 | ||
2764 | static int ocfs2_xattr_create_index_block(struct inode *inode, | 2746 | static int ocfs2_xattr_create_index_block(struct inode *inode, |
@@ -2771,18 +2753,17 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2771 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2753 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2772 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2754 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
2773 | struct ocfs2_alloc_context *data_ac; | 2755 | struct ocfs2_alloc_context *data_ac; |
2774 | struct buffer_head *xh_bh = NULL, *data_bh = NULL; | ||
2775 | struct buffer_head *xb_bh = xs->xattr_bh; | 2756 | struct buffer_head *xb_bh = xs->xattr_bh; |
2776 | struct ocfs2_xattr_block *xb = | 2757 | struct ocfs2_xattr_block *xb = |
2777 | (struct ocfs2_xattr_block *)xb_bh->b_data; | 2758 | (struct ocfs2_xattr_block *)xb_bh->b_data; |
2778 | struct ocfs2_xattr_tree_root *xr; | 2759 | struct ocfs2_xattr_tree_root *xr; |
2779 | u16 xb_flags = le16_to_cpu(xb->xb_flags); | 2760 | u16 xb_flags = le16_to_cpu(xb->xb_flags); |
2780 | u16 bpb = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
2781 | 2761 | ||
2782 | mlog(0, "create xattr index block for %llu\n", | 2762 | mlog(0, "create xattr index block for %llu\n", |
2783 | (unsigned long long)xb_bh->b_blocknr); | 2763 | (unsigned long long)xb_bh->b_blocknr); |
2784 | 2764 | ||
2785 | BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); | 2765 | BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); |
2766 | BUG_ON(!xs->bucket); | ||
2786 | 2767 | ||
2787 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); | 2768 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); |
2788 | if (ret) { | 2769 | if (ret) { |
@@ -2798,10 +2779,10 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2798 | down_write(&oi->ip_alloc_sem); | 2779 | down_write(&oi->ip_alloc_sem); |
2799 | 2780 | ||
2800 | /* | 2781 | /* |
2801 | * 3 more credits, one for xattr block update, one for the 1st block | 2782 | * We need more credits. One for the xattr block update and one |
2802 | * of the new xattr bucket and one for the value/data. | 2783 | * for each block of the new xattr bucket. |
2803 | */ | 2784 | */ |
2804 | credits += 3; | 2785 | credits += 1 + ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
2805 | handle = ocfs2_start_trans(osb, credits); | 2786 | handle = ocfs2_start_trans(osb, credits); |
2806 | if (IS_ERR(handle)) { | 2787 | if (IS_ERR(handle)) { |
2807 | ret = PTR_ERR(handle); | 2788 | ret = PTR_ERR(handle); |
@@ -2832,51 +2813,23 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2832 | mlog(0, "allocate 1 cluster from %llu to xattr block\n", | 2813 | mlog(0, "allocate 1 cluster from %llu to xattr block\n", |
2833 | (unsigned long long)blkno); | 2814 | (unsigned long long)blkno); |
2834 | 2815 | ||
2835 | xh_bh = sb_getblk(inode->i_sb, blkno); | 2816 | ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); |
2836 | if (!xh_bh) { | 2817 | if (ret) { |
2837 | ret = -EIO; | ||
2838 | mlog_errno(ret); | 2818 | mlog_errno(ret); |
2839 | goto out_commit; | 2819 | goto out_commit; |
2840 | } | 2820 | } |
2841 | 2821 | ||
2842 | ocfs2_set_new_buffer_uptodate(inode, xh_bh); | 2822 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, |
2843 | 2823 | OCFS2_JOURNAL_ACCESS_CREATE); | |
2844 | ret = ocfs2_journal_access(handle, inode, xh_bh, | ||
2845 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
2846 | if (ret) { | 2824 | if (ret) { |
2847 | mlog_errno(ret); | 2825 | mlog_errno(ret); |
2848 | goto out_commit; | 2826 | goto out_commit; |
2849 | } | 2827 | } |
2850 | 2828 | ||
2851 | if (bpb > 1) { | 2829 | ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xs->bucket); |
2852 | data_bh = sb_getblk(inode->i_sb, blkno + bpb - 1); | 2830 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); |
2853 | if (!data_bh) { | ||
2854 | ret = -EIO; | ||
2855 | mlog_errno(ret); | ||
2856 | goto out_commit; | ||
2857 | } | ||
2858 | |||
2859 | ocfs2_set_new_buffer_uptodate(inode, data_bh); | ||
2860 | |||
2861 | ret = ocfs2_journal_access(handle, inode, data_bh, | ||
2862 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
2863 | if (ret) { | ||
2864 | mlog_errno(ret); | ||
2865 | goto out_commit; | ||
2866 | } | ||
2867 | } | ||
2868 | |||
2869 | ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xh_bh, data_bh); | ||
2870 | |||
2871 | ocfs2_journal_dirty(handle, xh_bh); | ||
2872 | if (data_bh) | ||
2873 | ocfs2_journal_dirty(handle, data_bh); | ||
2874 | 2831 | ||
2875 | ret = ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh); | 2832 | ocfs2_xattr_update_xattr_search(inode, xs, xb_bh); |
2876 | if (ret) { | ||
2877 | mlog_errno(ret); | ||
2878 | goto out_commit; | ||
2879 | } | ||
2880 | 2833 | ||
2881 | /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */ | 2834 | /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */ |
2882 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - | 2835 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - |
@@ -2911,9 +2864,6 @@ out: | |||
2911 | if (data_ac) | 2864 | if (data_ac) |
2912 | ocfs2_free_alloc_context(data_ac); | 2865 | ocfs2_free_alloc_context(data_ac); |
2913 | 2866 | ||
2914 | brelse(xh_bh); | ||
2915 | brelse(data_bh); | ||
2916 | |||
2917 | return ret; | 2867 | return ret; |
2918 | } | 2868 | } |
2919 | 2869 | ||