aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/xattr.c
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-10-27 18:18:29 -0400
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:34:18 -0500
commit178eeac354ea28828d5e94a3a7b51368c171d6a5 (patch)
tree8e3d7b2c923ea2260344dbe76d0b128031ba93c9 /fs/ocfs2/xattr.c
parente2356a3f02cfdbce735465a2b40b6dc72a764c26 (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.c114
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 */
2655static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, 2657static 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 */
2726static int ocfs2_xattr_update_xattr_search(struct inode *inode, 2726static 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
2764static int ocfs2_xattr_create_index_block(struct inode *inode, 2746static 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