aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2009-09-21 01:04:19 -0400
committerJoel Becker <joel.becker@oracle.com>2009-09-22 23:09:43 -0400
commit0129241e2b3b90ff83a8c774353e5612d84bd493 (patch)
treeeec03f874cbdbc4c9eab4900f2de89fd1747a5ee
parent47bca4950bc40fb54e9d41cbbc8b06cd653d2ae2 (diff)
ocfs2: Attach xattr clusters to refcount tree.
In ocfs2, when xattr's value is larger than OCFS2_XATTR_INLINE_SIZE, it will be kept outside of the blocks we store xattr entry. And they are stored in a b-tree also. So this patch try to attach all these clusters to refcount tree also. Signed-off-by: Tao Ma <tao.ma@oracle.com>
-rw-r--r--fs/ocfs2/refcounttree.c29
-rw-r--r--fs/ocfs2/refcounttree.h7
-rw-r--r--fs/ocfs2/xattr.c291
-rw-r--r--fs/ocfs2/xattr.h6
4 files changed, 329 insertions, 4 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index a5b5bef054a7..a85c01c6629d 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -3547,7 +3547,8 @@ int ocfs2_add_refcount_flag(struct inode *inode,
3547 struct ocfs2_caching_info *ref_ci, 3547 struct ocfs2_caching_info *ref_ci,
3548 struct buffer_head *ref_root_bh, 3548 struct buffer_head *ref_root_bh,
3549 u32 cpos, u32 p_cluster, u32 num_clusters, 3549 u32 cpos, u32 p_cluster, u32 num_clusters,
3550 struct ocfs2_cached_dealloc_ctxt *dealloc) 3550 struct ocfs2_cached_dealloc_ctxt *dealloc,
3551 struct ocfs2_post_refcount *post)
3551{ 3552{
3552 int ret; 3553 int ret;
3553 handle_t *handle; 3554 handle_t *handle;
@@ -3576,6 +3577,9 @@ int ocfs2_add_refcount_flag(struct inode *inode,
3576 } 3577 }
3577 } 3578 }
3578 3579
3580 if (post)
3581 credits += post->credits;
3582
3579 handle = ocfs2_start_trans(osb, credits); 3583 handle = ocfs2_start_trans(osb, credits);
3580 if (IS_ERR(handle)) { 3584 if (IS_ERR(handle)) {
3581 ret = PTR_ERR(handle); 3585 ret = PTR_ERR(handle);
@@ -3594,8 +3598,16 @@ int ocfs2_add_refcount_flag(struct inode *inode,
3594 ret = __ocfs2_increase_refcount(handle, ref_ci, ref_root_bh, 3598 ret = __ocfs2_increase_refcount(handle, ref_ci, ref_root_bh,
3595 p_cluster, num_clusters, 3599 p_cluster, num_clusters,
3596 meta_ac, dealloc); 3600 meta_ac, dealloc);
3597 if (ret) 3601 if (ret) {
3598 mlog_errno(ret); 3602 mlog_errno(ret);
3603 goto out_commit;
3604 }
3605
3606 if (post && post->func) {
3607 ret = post->func(inode, handle, post->para);
3608 if (ret)
3609 mlog_errno(ret);
3610 }
3599 3611
3600out_commit: 3612out_commit:
3601 ocfs2_commit_trans(osb, handle); 3613 ocfs2_commit_trans(osb, handle);
@@ -3688,7 +3700,7 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
3688 &ref_tree->rf_ci, 3700 &ref_tree->rf_ci,
3689 ref_root_bh, cpos, 3701 ref_root_bh, cpos,
3690 p_cluster, num_clusters, 3702 p_cluster, num_clusters,
3691 &dealloc); 3703 &dealloc, NULL);
3692 if (ret) { 3704 if (ret) {
3693 mlog_errno(ret); 3705 mlog_errno(ret);
3694 goto unlock; 3706 goto unlock;
@@ -3699,6 +3711,17 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
3699 cpos += num_clusters; 3711 cpos += num_clusters;
3700 } 3712 }
3701 3713
3714 if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) {
3715 ret = ocfs2_xattr_attach_refcount_tree(inode, di_bh,
3716 &ref_tree->rf_ci,
3717 ref_root_bh,
3718 &dealloc);
3719 if (ret) {
3720 mlog_errno(ret);
3721 goto unlock;
3722 }
3723 }
3724
3702 if (data_changed) { 3725 if (data_changed) {
3703 ret = ocfs2_change_ctime(inode, di_bh); 3726 ret = ocfs2_change_ctime(inode, di_bh);
3704 if (ret) 3727 if (ret)
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h
index d09d64b29810..7d6900c904d4 100644
--- a/fs/ocfs2/refcounttree.h
+++ b/fs/ocfs2/refcounttree.h
@@ -83,4 +83,11 @@ int ocfs2_refcount_cow_xattr(struct inode *inode,
83 struct buffer_head *ref_root_bh, 83 struct buffer_head *ref_root_bh,
84 u32 cpos, u32 write_len, 84 u32 cpos, u32 write_len,
85 struct ocfs2_post_refcount *post); 85 struct ocfs2_post_refcount *post);
86int ocfs2_add_refcount_flag(struct inode *inode,
87 struct ocfs2_extent_tree *data_et,
88 struct ocfs2_caching_info *ref_ci,
89 struct buffer_head *ref_root_bh,
90 u32 cpos, u32 p_cluster, u32 num_clusters,
91 struct ocfs2_cached_dealloc_ctxt *dealloc,
92 struct ocfs2_post_refcount *post);
86#endif /* OCFS2_REFCOUNTTREE_H */ 93#endif /* OCFS2_REFCOUNTTREE_H */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index bfa7ee208855..501539a733f4 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -5551,6 +5551,297 @@ out:
5551} 5551}
5552 5552
5553/* 5553/*
5554 * Add the REFCOUNTED flags for all the extent rec in ocfs2_xattr_value_root.
5555 * The physical clusters will be added to refcount tree.
5556 */
5557static int ocfs2_xattr_value_attach_refcount(struct inode *inode,
5558 struct ocfs2_xattr_value_root *xv,
5559 struct ocfs2_extent_tree *value_et,
5560 struct ocfs2_caching_info *ref_ci,
5561 struct buffer_head *ref_root_bh,
5562 struct ocfs2_cached_dealloc_ctxt *dealloc,
5563 struct ocfs2_post_refcount *refcount)
5564{
5565 int ret = 0;
5566 u32 clusters = le32_to_cpu(xv->xr_clusters);
5567 u32 cpos, p_cluster, num_clusters;
5568 struct ocfs2_extent_list *el = &xv->xr_list;
5569 unsigned int ext_flags;
5570
5571 cpos = 0;
5572 while (cpos < clusters) {
5573 ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
5574 &num_clusters, el, &ext_flags);
5575
5576 cpos += num_clusters;
5577 if ((ext_flags & OCFS2_EXT_REFCOUNTED))
5578 continue;
5579
5580 BUG_ON(!p_cluster);
5581
5582 ret = ocfs2_add_refcount_flag(inode, value_et,
5583 ref_ci, ref_root_bh,
5584 cpos - num_clusters,
5585 p_cluster, num_clusters,
5586 dealloc, refcount);
5587 if (ret) {
5588 mlog_errno(ret);
5589 break;
5590 }
5591 }
5592
5593 return ret;
5594}
5595
5596/*
5597 * Given a normal ocfs2_xattr_header, refcount all the entries which
5598 * have value stored outside.
5599 * Used for xattrs stored in inode and ocfs2_xattr_block.
5600 */
5601static int ocfs2_xattr_attach_refcount_normal(struct inode *inode,
5602 struct ocfs2_xattr_value_buf *vb,
5603 struct ocfs2_xattr_header *header,
5604 struct ocfs2_caching_info *ref_ci,
5605 struct buffer_head *ref_root_bh,
5606 struct ocfs2_cached_dealloc_ctxt *dealloc)
5607{
5608
5609 struct ocfs2_xattr_entry *xe;
5610 struct ocfs2_xattr_value_root *xv;
5611 struct ocfs2_extent_tree et;
5612 int i, ret = 0;
5613
5614 for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
5615 xe = &header->xh_entries[i];
5616
5617 if (ocfs2_xattr_is_local(xe))
5618 continue;
5619
5620 xv = (struct ocfs2_xattr_value_root *)((void *)header +
5621 le16_to_cpu(xe->xe_name_offset) +
5622 OCFS2_XATTR_SIZE(xe->xe_name_len));
5623
5624 vb->vb_xv = xv;
5625 ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb);
5626
5627 ret = ocfs2_xattr_value_attach_refcount(inode, xv, &et,
5628 ref_ci, ref_root_bh,
5629 dealloc, NULL);
5630 if (ret) {
5631 mlog_errno(ret);
5632 break;
5633 }
5634 }
5635
5636 return ret;
5637}
5638
5639static int ocfs2_xattr_inline_attach_refcount(struct inode *inode,
5640 struct buffer_head *fe_bh,
5641 struct ocfs2_caching_info *ref_ci,
5642 struct buffer_head *ref_root_bh,
5643 struct ocfs2_cached_dealloc_ctxt *dealloc)
5644{
5645 struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
5646 struct ocfs2_xattr_header *header = (struct ocfs2_xattr_header *)
5647 (fe_bh->b_data + inode->i_sb->s_blocksize -
5648 le16_to_cpu(di->i_xattr_inline_size));
5649 struct ocfs2_xattr_value_buf vb = {
5650 .vb_bh = fe_bh,
5651 .vb_access = ocfs2_journal_access_di,
5652 };
5653
5654 return ocfs2_xattr_attach_refcount_normal(inode, &vb, header,
5655 ref_ci, ref_root_bh, dealloc);
5656}
5657
5658struct ocfs2_xattr_tree_value_refcount_para {
5659 struct ocfs2_caching_info *ref_ci;
5660 struct buffer_head *ref_root_bh;
5661 struct ocfs2_cached_dealloc_ctxt *dealloc;
5662};
5663
5664static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
5665 struct ocfs2_xattr_bucket *bucket,
5666 int offset,
5667 struct ocfs2_xattr_value_root **xv,
5668 struct buffer_head **bh)
5669{
5670 int ret, block_off, name_offset;
5671 struct ocfs2_xattr_header *xh = bucket_xh(bucket);
5672 struct ocfs2_xattr_entry *xe = &xh->xh_entries[offset];
5673 void *base;
5674
5675 ret = ocfs2_xattr_bucket_get_name_value(sb,
5676 bucket_xh(bucket),
5677 offset,
5678 &block_off,
5679 &name_offset);
5680 if (ret) {
5681 mlog_errno(ret);
5682 goto out;
5683 }
5684
5685 base = bucket_block(bucket, block_off);
5686
5687 *xv = (struct ocfs2_xattr_value_root *)(base + name_offset +
5688 OCFS2_XATTR_SIZE(xe->xe_name_len));
5689
5690 if (bh)
5691 *bh = bucket->bu_bhs[block_off];
5692out:
5693 return ret;
5694}
5695
5696/*
5697 * For a given xattr bucket, refcount all the entries which
5698 * have value stored outside.
5699 */
5700static int ocfs2_xattr_bucket_value_refcount(struct inode *inode,
5701 struct ocfs2_xattr_bucket *bucket,
5702 void *para)
5703{
5704 int i, ret = 0;
5705 struct ocfs2_extent_tree et;
5706 struct ocfs2_xattr_tree_value_refcount_para *ref =
5707 (struct ocfs2_xattr_tree_value_refcount_para *)para;
5708 struct ocfs2_xattr_header *xh =
5709 (struct ocfs2_xattr_header *)bucket->bu_bhs[0]->b_data;
5710 struct ocfs2_xattr_entry *xe;
5711 struct ocfs2_xattr_value_buf vb = {
5712 .vb_access = ocfs2_journal_access,
5713 };
5714 struct ocfs2_post_refcount refcount = {
5715 .credits = bucket->bu_blocks,
5716 .para = bucket,
5717 .func = ocfs2_xattr_bucket_post_refcount,
5718 };
5719 struct ocfs2_post_refcount *p = NULL;
5720
5721 /* We only need post_refcount if we support metaecc. */
5722 if (ocfs2_meta_ecc(OCFS2_SB(inode->i_sb)))
5723 p = &refcount;
5724
5725 mlog(0, "refcount bucket %llu, count = %u\n",
5726 (unsigned long long)bucket_blkno(bucket),
5727 le16_to_cpu(xh->xh_count));
5728 for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
5729 xe = &xh->xh_entries[i];
5730
5731 if (ocfs2_xattr_is_local(xe))
5732 continue;
5733
5734 ret = ocfs2_get_xattr_tree_value_root(inode->i_sb, bucket, i,
5735 &vb.vb_xv, &vb.vb_bh);
5736 if (ret) {
5737 mlog_errno(ret);
5738 break;
5739 }
5740
5741 ocfs2_init_xattr_value_extent_tree(&et,
5742 INODE_CACHE(inode), &vb);
5743
5744 ret = ocfs2_xattr_value_attach_refcount(inode, vb.vb_xv,
5745 &et, ref->ref_ci,
5746 ref->ref_root_bh,
5747 ref->dealloc, p);
5748 if (ret) {
5749 mlog_errno(ret);
5750 break;
5751 }
5752 }
5753
5754 return ret;
5755
5756}
5757
5758static int ocfs2_refcount_xattr_tree_rec(struct inode *inode,
5759 struct buffer_head *root_bh,
5760 u64 blkno, u32 cpos, u32 len, void *para)
5761{
5762 return ocfs2_iterate_xattr_buckets(inode, blkno, len,
5763 ocfs2_xattr_bucket_value_refcount,
5764 para);
5765}
5766
5767static int ocfs2_xattr_block_attach_refcount(struct inode *inode,
5768 struct buffer_head *blk_bh,
5769 struct ocfs2_caching_info *ref_ci,
5770 struct buffer_head *ref_root_bh,
5771 struct ocfs2_cached_dealloc_ctxt *dealloc)
5772{
5773 int ret = 0;
5774 struct ocfs2_xattr_block *xb =
5775 (struct ocfs2_xattr_block *)blk_bh->b_data;
5776
5777 if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
5778 struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
5779 struct ocfs2_xattr_value_buf vb = {
5780 .vb_bh = blk_bh,
5781 .vb_access = ocfs2_journal_access_xb,
5782 };
5783
5784 ret = ocfs2_xattr_attach_refcount_normal(inode, &vb, header,
5785 ref_ci, ref_root_bh,
5786 dealloc);
5787 } else {
5788 struct ocfs2_xattr_tree_value_refcount_para para = {
5789 .ref_ci = ref_ci,
5790 .ref_root_bh = ref_root_bh,
5791 .dealloc = dealloc,
5792 };
5793
5794 ret = ocfs2_iterate_xattr_index_block(inode, blk_bh,
5795 ocfs2_refcount_xattr_tree_rec,
5796 &para);
5797 }
5798
5799 return ret;
5800}
5801
5802int ocfs2_xattr_attach_refcount_tree(struct inode *inode,
5803 struct buffer_head *fe_bh,
5804 struct ocfs2_caching_info *ref_ci,
5805 struct buffer_head *ref_root_bh,
5806 struct ocfs2_cached_dealloc_ctxt *dealloc)
5807{
5808 int ret = 0;
5809 struct ocfs2_inode_info *oi = OCFS2_I(inode);
5810 struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
5811 struct buffer_head *blk_bh = NULL;
5812
5813 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
5814 ret = ocfs2_xattr_inline_attach_refcount(inode, fe_bh,
5815 ref_ci, ref_root_bh,
5816 dealloc);
5817 if (ret) {
5818 mlog_errno(ret);
5819 goto out;
5820 }
5821 }
5822
5823 if (!di->i_xattr_loc)
5824 goto out;
5825
5826 ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc),
5827 &blk_bh);
5828 if (ret < 0) {
5829 mlog_errno(ret);
5830 goto out;
5831 }
5832
5833 ret = ocfs2_xattr_block_attach_refcount(inode, blk_bh, ref_ci,
5834 ref_root_bh, dealloc);
5835 if (ret)
5836 mlog_errno(ret);
5837
5838 brelse(blk_bh);
5839out:
5840
5841 return ret;
5842}
5843
5844/*
5554 * 'security' attributes support 5845 * 'security' attributes support
5555 */ 5846 */
5556static size_t ocfs2_xattr_security_list(struct inode *inode, char *list, 5847static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index 1ca7e9a1b7bc..a3295d705cea 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -83,5 +83,9 @@ struct ocfs2_xattr_value_buf {
83 struct ocfs2_xattr_value_root *vb_xv; 83 struct ocfs2_xattr_value_root *vb_xv;
84}; 84};
85 85
86 86int ocfs2_xattr_attach_refcount_tree(struct inode *inode,
87 struct buffer_head *fe_bh,
88 struct ocfs2_caching_info *ref_ci,
89 struct buffer_head *ref_root_bh,
90 struct ocfs2_cached_dealloc_ctxt *dealloc);
87#endif /* OCFS2_XATTR_H */ 91#endif /* OCFS2_XATTR_H */