diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-17 23:43:17 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 23:09:41 -0400 |
commit | 492a8a33e1cb966fa0b5756c5fc11d30c8f8848e (patch) | |
tree | eacf691b07c8fa3e81c11ff1d6b8773c2dbb9e77 /fs/ocfs2/xattr.c | |
parent | 913580b4cd445c4fb25d7cf167911a8cf6bdb1eb (diff) |
ocfs2: Add CoW support for xattr.
In order to make 2 transcation(xattr and cow) independent with each other,
we CoW the whole xattr out in case we are setting them.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 234 |
1 files changed, 222 insertions, 12 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index dda49c00362a..a538cebbe9c5 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #include "buffer_head_io.h" | 55 | #include "buffer_head_io.h" |
56 | #include "super.h" | 56 | #include "super.h" |
57 | #include "xattr.h" | 57 | #include "xattr.h" |
58 | 58 | #include "refcounttree.h" | |
59 | 59 | ||
60 | struct ocfs2_xattr_def_value_root { | 60 | struct ocfs2_xattr_def_value_root { |
61 | struct ocfs2_xattr_value_root xv; | 61 | struct ocfs2_xattr_value_root xv; |
@@ -176,6 +176,14 @@ static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle, | |||
176 | u64 src_blk, u64 last_blk, u64 to_blk, | 176 | u64 src_blk, u64 last_blk, u64 to_blk, |
177 | unsigned int start_bucket, | 177 | unsigned int start_bucket, |
178 | u32 *first_hash); | 178 | u32 *first_hash); |
179 | static int ocfs2_prepare_refcount_xattr(struct inode *inode, | ||
180 | struct ocfs2_dinode *di, | ||
181 | struct ocfs2_xattr_info *xi, | ||
182 | struct ocfs2_xattr_search *xis, | ||
183 | struct ocfs2_xattr_search *xbs, | ||
184 | struct ocfs2_refcount_tree **ref_tree, | ||
185 | int *meta_need, | ||
186 | int *credits); | ||
179 | 187 | ||
180 | static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) | 188 | static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) |
181 | { | 189 | { |
@@ -647,6 +655,7 @@ leave: | |||
647 | static int __ocfs2_remove_xattr_range(struct inode *inode, | 655 | static int __ocfs2_remove_xattr_range(struct inode *inode, |
648 | struct ocfs2_xattr_value_buf *vb, | 656 | struct ocfs2_xattr_value_buf *vb, |
649 | u32 cpos, u32 phys_cpos, u32 len, | 657 | u32 cpos, u32 phys_cpos, u32 len, |
658 | unsigned int ext_flags, | ||
650 | struct ocfs2_xattr_set_ctxt *ctxt) | 659 | struct ocfs2_xattr_set_ctxt *ctxt) |
651 | { | 660 | { |
652 | int ret; | 661 | int ret; |
@@ -678,7 +687,14 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
678 | goto out; | 687 | goto out; |
679 | } | 688 | } |
680 | 689 | ||
681 | ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len); | 690 | if (ext_flags & OCFS2_EXT_REFCOUNTED) |
691 | ret = ocfs2_decrease_refcount(inode, handle, | ||
692 | ocfs2_blocks_to_clusters(inode->i_sb, | ||
693 | phys_blkno), | ||
694 | len, ctxt->meta_ac, &ctxt->dealloc, 1); | ||
695 | else | ||
696 | ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, | ||
697 | phys_blkno, len); | ||
682 | if (ret) | 698 | if (ret) |
683 | mlog_errno(ret); | 699 | mlog_errno(ret); |
684 | 700 | ||
@@ -693,6 +709,7 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
693 | struct ocfs2_xattr_set_ctxt *ctxt) | 709 | struct ocfs2_xattr_set_ctxt *ctxt) |
694 | { | 710 | { |
695 | int ret = 0; | 711 | int ret = 0; |
712 | unsigned int ext_flags; | ||
696 | u32 trunc_len, cpos, phys_cpos, alloc_size; | 713 | u32 trunc_len, cpos, phys_cpos, alloc_size; |
697 | u64 block; | 714 | u64 block; |
698 | 715 | ||
@@ -704,7 +721,7 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
704 | while (trunc_len) { | 721 | while (trunc_len) { |
705 | ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos, | 722 | ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos, |
706 | &alloc_size, | 723 | &alloc_size, |
707 | &vb->vb_xv->xr_list, NULL); | 724 | &vb->vb_xv->xr_list, &ext_flags); |
708 | if (ret) { | 725 | if (ret) { |
709 | mlog_errno(ret); | 726 | mlog_errno(ret); |
710 | goto out; | 727 | goto out; |
@@ -715,7 +732,7 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
715 | 732 | ||
716 | ret = __ocfs2_remove_xattr_range(inode, vb, cpos, | 733 | ret = __ocfs2_remove_xattr_range(inode, vb, cpos, |
717 | phys_cpos, alloc_size, | 734 | phys_cpos, alloc_size, |
718 | ctxt); | 735 | ext_flags, ctxt); |
719 | if (ret) { | 736 | if (ret) { |
720 | mlog_errno(ret); | 737 | mlog_errno(ret); |
721 | goto out; | 738 | goto out; |
@@ -1182,7 +1199,7 @@ static int ocfs2_xattr_get(struct inode *inode, | |||
1182 | 1199 | ||
1183 | static int __ocfs2_xattr_set_value_outside(struct inode *inode, | 1200 | static int __ocfs2_xattr_set_value_outside(struct inode *inode, |
1184 | handle_t *handle, | 1201 | handle_t *handle, |
1185 | struct ocfs2_xattr_value_root *xv, | 1202 | struct ocfs2_xattr_value_buf *vb, |
1186 | const void *value, | 1203 | const void *value, |
1187 | int value_len) | 1204 | int value_len) |
1188 | { | 1205 | { |
@@ -1193,18 +1210,22 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1193 | u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len); | 1210 | u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len); |
1194 | u64 blkno; | 1211 | u64 blkno; |
1195 | struct buffer_head *bh = NULL; | 1212 | struct buffer_head *bh = NULL; |
1213 | unsigned int ext_flags; | ||
1214 | struct ocfs2_xattr_value_root *xv = vb->vb_xv; | ||
1196 | 1215 | ||
1197 | BUG_ON(clusters > le32_to_cpu(xv->xr_clusters)); | 1216 | BUG_ON(clusters > le32_to_cpu(xv->xr_clusters)); |
1198 | 1217 | ||
1199 | while (cpos < clusters) { | 1218 | while (cpos < clusters) { |
1200 | ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster, | 1219 | ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster, |
1201 | &num_clusters, &xv->xr_list, | 1220 | &num_clusters, &xv->xr_list, |
1202 | NULL); | 1221 | &ext_flags); |
1203 | if (ret) { | 1222 | if (ret) { |
1204 | mlog_errno(ret); | 1223 | mlog_errno(ret); |
1205 | goto out; | 1224 | goto out; |
1206 | } | 1225 | } |
1207 | 1226 | ||
1227 | BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED); | ||
1228 | |||
1208 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | 1229 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); |
1209 | 1230 | ||
1210 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { | 1231 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { |
@@ -1356,7 +1377,7 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1356 | mlog_errno(ret); | 1377 | mlog_errno(ret); |
1357 | return ret; | 1378 | return ret; |
1358 | } | 1379 | } |
1359 | ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb->vb_xv, | 1380 | ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb, |
1360 | xi->value, xi->value_len); | 1381 | xi->value, xi->value_len); |
1361 | if (ret < 0) | 1382 | if (ret < 0) |
1362 | mlog_errno(ret); | 1383 | mlog_errno(ret); |
@@ -1595,7 +1616,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1595 | 1616 | ||
1596 | ret = __ocfs2_xattr_set_value_outside(inode, | 1617 | ret = __ocfs2_xattr_set_value_outside(inode, |
1597 | handle, | 1618 | handle, |
1598 | vb.vb_xv, | 1619 | &vb, |
1599 | xi->value, | 1620 | xi->value, |
1600 | xi->value_len); | 1621 | xi->value_len); |
1601 | if (ret < 0) | 1622 | if (ret < 0) |
@@ -2431,6 +2452,7 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, | |||
2431 | struct ocfs2_xattr_search *xis, | 2452 | struct ocfs2_xattr_search *xis, |
2432 | struct ocfs2_xattr_search *xbs, | 2453 | struct ocfs2_xattr_search *xbs, |
2433 | struct ocfs2_xattr_set_ctxt *ctxt, | 2454 | struct ocfs2_xattr_set_ctxt *ctxt, |
2455 | int extra_meta, | ||
2434 | int *credits) | 2456 | int *credits) |
2435 | { | 2457 | { |
2436 | int clusters_add, meta_add, ret; | 2458 | int clusters_add, meta_add, ret; |
@@ -2447,6 +2469,7 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, | |||
2447 | return ret; | 2469 | return ret; |
2448 | } | 2470 | } |
2449 | 2471 | ||
2472 | meta_add += extra_meta; | ||
2450 | mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, " | 2473 | mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, " |
2451 | "credits = %d\n", xi->name, meta_add, clusters_add, *credits); | 2474 | "credits = %d\n", xi->name, meta_add, clusters_add, *credits); |
2452 | 2475 | ||
@@ -2714,10 +2737,11 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2714 | { | 2737 | { |
2715 | struct buffer_head *di_bh = NULL; | 2738 | struct buffer_head *di_bh = NULL; |
2716 | struct ocfs2_dinode *di; | 2739 | struct ocfs2_dinode *di; |
2717 | int ret, credits; | 2740 | int ret, credits, ref_meta = 0, ref_credits = 0; |
2718 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2741 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2719 | struct inode *tl_inode = osb->osb_tl_inode; | 2742 | struct inode *tl_inode = osb->osb_tl_inode; |
2720 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; | 2743 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; |
2744 | struct ocfs2_refcount_tree *ref_tree = NULL; | ||
2721 | 2745 | ||
2722 | struct ocfs2_xattr_info xi = { | 2746 | struct ocfs2_xattr_info xi = { |
2723 | .name_index = name_index, | 2747 | .name_index = name_index, |
@@ -2782,6 +2806,17 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2782 | goto cleanup; | 2806 | goto cleanup; |
2783 | } | 2807 | } |
2784 | 2808 | ||
2809 | /* Check whether the value is refcounted and do some prepartion. */ | ||
2810 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL && | ||
2811 | (!xis.not_found || !xbs.not_found)) { | ||
2812 | ret = ocfs2_prepare_refcount_xattr(inode, di, &xi, | ||
2813 | &xis, &xbs, &ref_tree, | ||
2814 | &ref_meta, &ref_credits); | ||
2815 | if (ret) { | ||
2816 | mlog_errno(ret); | ||
2817 | goto cleanup; | ||
2818 | } | ||
2819 | } | ||
2785 | 2820 | ||
2786 | mutex_lock(&tl_inode->i_mutex); | 2821 | mutex_lock(&tl_inode->i_mutex); |
2787 | 2822 | ||
@@ -2796,7 +2831,7 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2796 | mutex_unlock(&tl_inode->i_mutex); | 2831 | mutex_unlock(&tl_inode->i_mutex); |
2797 | 2832 | ||
2798 | ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, | 2833 | ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, |
2799 | &xbs, &ctxt, &credits); | 2834 | &xbs, &ctxt, ref_meta, &credits); |
2800 | if (ret) { | 2835 | if (ret) { |
2801 | mlog_errno(ret); | 2836 | mlog_errno(ret); |
2802 | goto cleanup; | 2837 | goto cleanup; |
@@ -2804,7 +2839,7 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2804 | 2839 | ||
2805 | /* we need to update inode's ctime field, so add credit for it. */ | 2840 | /* we need to update inode's ctime field, so add credit for it. */ |
2806 | credits += OCFS2_INODE_UPDATE_CREDITS; | 2841 | credits += OCFS2_INODE_UPDATE_CREDITS; |
2807 | ctxt.handle = ocfs2_start_trans(osb, credits); | 2842 | ctxt.handle = ocfs2_start_trans(osb, credits + ref_credits); |
2808 | if (IS_ERR(ctxt.handle)) { | 2843 | if (IS_ERR(ctxt.handle)) { |
2809 | ret = PTR_ERR(ctxt.handle); | 2844 | ret = PTR_ERR(ctxt.handle); |
2810 | mlog_errno(ret); | 2845 | mlog_errno(ret); |
@@ -2823,6 +2858,8 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2823 | ocfs2_schedule_truncate_log_flush(osb, 1); | 2858 | ocfs2_schedule_truncate_log_flush(osb, 1); |
2824 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | 2859 | ocfs2_run_deallocs(osb, &ctxt.dealloc); |
2825 | cleanup: | 2860 | cleanup: |
2861 | if (ref_tree) | ||
2862 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | ||
2826 | up_write(&OCFS2_I(inode)->ip_xattr_sem); | 2863 | up_write(&OCFS2_I(inode)->ip_xattr_sem); |
2827 | ocfs2_inode_unlock(inode, 1); | 2864 | ocfs2_inode_unlock(inode, 1); |
2828 | cleanup_nolock: | 2865 | cleanup_nolock: |
@@ -4802,6 +4839,9 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | |||
4802 | struct ocfs2_xattr_entry *xe = xs->here; | 4839 | struct ocfs2_xattr_entry *xe = xs->here; |
4803 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | 4840 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); |
4804 | void *base; | 4841 | void *base; |
4842 | struct ocfs2_xattr_value_buf vb = { | ||
4843 | .vb_access = ocfs2_journal_access, | ||
4844 | }; | ||
4805 | 4845 | ||
4806 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); | 4846 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); |
4807 | 4847 | ||
@@ -4818,8 +4858,10 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | |||
4818 | xv = (struct ocfs2_xattr_value_root *)(base + offset + | 4858 | xv = (struct ocfs2_xattr_value_root *)(base + offset + |
4819 | OCFS2_XATTR_SIZE(xe->xe_name_len)); | 4859 | OCFS2_XATTR_SIZE(xe->xe_name_len)); |
4820 | 4860 | ||
4861 | vb.vb_xv = xv; | ||
4862 | vb.vb_bh = xs->bucket->bu_bhs[block_off]; | ||
4821 | ret = __ocfs2_xattr_set_value_outside(inode, handle, | 4863 | ret = __ocfs2_xattr_set_value_outside(inode, handle, |
4822 | xv, val, value_len); | 4864 | &vb, val, value_len); |
4823 | if (ret) | 4865 | if (ret) |
4824 | mlog_errno(ret); | 4866 | mlog_errno(ret); |
4825 | out: | 4867 | out: |
@@ -5311,6 +5353,174 @@ out: | |||
5311 | } | 5353 | } |
5312 | 5354 | ||
5313 | /* | 5355 | /* |
5356 | * Whenever we modify a xattr value root in the bucket(e.g, CoW | ||
5357 | * or change the extent record flag), we need to recalculate | ||
5358 | * the metaecc for the whole bucket. So it is done here. | ||
5359 | * | ||
5360 | * Note: | ||
5361 | * We have to give the extra credits for the caller. | ||
5362 | */ | ||
5363 | static int ocfs2_xattr_bucket_post_refcount(struct inode *inode, | ||
5364 | handle_t *handle, | ||
5365 | void *para) | ||
5366 | { | ||
5367 | int ret; | ||
5368 | struct ocfs2_xattr_bucket *bucket = | ||
5369 | (struct ocfs2_xattr_bucket *)para; | ||
5370 | |||
5371 | ret = ocfs2_xattr_bucket_journal_access(handle, bucket, | ||
5372 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
5373 | if (ret) { | ||
5374 | mlog_errno(ret); | ||
5375 | return ret; | ||
5376 | } | ||
5377 | |||
5378 | ocfs2_xattr_bucket_journal_dirty(handle, bucket); | ||
5379 | |||
5380 | return 0; | ||
5381 | } | ||
5382 | |||
5383 | /* | ||
5384 | * Special action we need if the xattr value is refcounted. | ||
5385 | * | ||
5386 | * 1. If the xattr is refcounted, lock the tree. | ||
5387 | * 2. CoW the xattr if we are setting the new value and the value | ||
5388 | * will be stored outside. | ||
5389 | * 3. In other case, decrease_refcount will work for us, so just | ||
5390 | * lock the refcount tree, calculate the meta and credits is OK. | ||
5391 | * | ||
5392 | * We have to do CoW before ocfs2_init_xattr_set_ctxt since | ||
5393 | * currently CoW is a completed transaction, while this function | ||
5394 | * will also lock the allocators and let us deadlock. So we will | ||
5395 | * CoW the whole xattr value. | ||
5396 | */ | ||
5397 | static int ocfs2_prepare_refcount_xattr(struct inode *inode, | ||
5398 | struct ocfs2_dinode *di, | ||
5399 | struct ocfs2_xattr_info *xi, | ||
5400 | struct ocfs2_xattr_search *xis, | ||
5401 | struct ocfs2_xattr_search *xbs, | ||
5402 | struct ocfs2_refcount_tree **ref_tree, | ||
5403 | int *meta_add, | ||
5404 | int *credits) | ||
5405 | { | ||
5406 | int ret = 0; | ||
5407 | struct ocfs2_xattr_block *xb; | ||
5408 | struct ocfs2_xattr_entry *xe; | ||
5409 | char *base; | ||
5410 | u32 p_cluster, num_clusters; | ||
5411 | unsigned int ext_flags; | ||
5412 | int name_offset, name_len; | ||
5413 | struct ocfs2_xattr_value_buf vb; | ||
5414 | struct ocfs2_xattr_bucket *bucket = NULL; | ||
5415 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
5416 | struct ocfs2_post_refcount refcount; | ||
5417 | struct ocfs2_post_refcount *p = NULL; | ||
5418 | struct buffer_head *ref_root_bh = NULL; | ||
5419 | |||
5420 | if (!xis->not_found) { | ||
5421 | xe = xis->here; | ||
5422 | name_offset = le16_to_cpu(xe->xe_name_offset); | ||
5423 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); | ||
5424 | base = xis->base; | ||
5425 | vb.vb_bh = xis->inode_bh; | ||
5426 | vb.vb_access = ocfs2_journal_access_di; | ||
5427 | } else { | ||
5428 | int i, block_off = 0; | ||
5429 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; | ||
5430 | xe = xbs->here; | ||
5431 | name_offset = le16_to_cpu(xe->xe_name_offset); | ||
5432 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); | ||
5433 | i = xbs->here - xbs->header->xh_entries; | ||
5434 | |||
5435 | if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) { | ||
5436 | ret = ocfs2_xattr_bucket_get_name_value(inode, | ||
5437 | bucket_xh(xbs->bucket), | ||
5438 | i, &block_off, | ||
5439 | &name_offset); | ||
5440 | if (ret) { | ||
5441 | mlog_errno(ret); | ||
5442 | goto out; | ||
5443 | } | ||
5444 | base = bucket_block(xbs->bucket, block_off); | ||
5445 | vb.vb_bh = xbs->bucket->bu_bhs[block_off]; | ||
5446 | vb.vb_access = ocfs2_journal_access; | ||
5447 | |||
5448 | if (ocfs2_meta_ecc(osb)) { | ||
5449 | /*create parameters for ocfs2_post_refcount. */ | ||
5450 | bucket = xbs->bucket; | ||
5451 | refcount.credits = bucket->bu_blocks; | ||
5452 | refcount.para = bucket; | ||
5453 | refcount.func = | ||
5454 | ocfs2_xattr_bucket_post_refcount; | ||
5455 | p = &refcount; | ||
5456 | } | ||
5457 | } else { | ||
5458 | base = xbs->base; | ||
5459 | vb.vb_bh = xbs->xattr_bh; | ||
5460 | vb.vb_access = ocfs2_journal_access_xb; | ||
5461 | } | ||
5462 | } | ||
5463 | |||
5464 | if (ocfs2_xattr_is_local(xe)) | ||
5465 | goto out; | ||
5466 | |||
5467 | vb.vb_xv = (struct ocfs2_xattr_value_root *) | ||
5468 | (base + name_offset + name_len); | ||
5469 | |||
5470 | ret = ocfs2_xattr_get_clusters(inode, 0, &p_cluster, | ||
5471 | &num_clusters, &vb.vb_xv->xr_list, | ||
5472 | &ext_flags); | ||
5473 | if (ret) { | ||
5474 | mlog_errno(ret); | ||
5475 | goto out; | ||
5476 | } | ||
5477 | |||
5478 | /* | ||
5479 | * We just need to check the 1st extent record, since we always | ||
5480 | * CoW the whole xattr. So there shouldn't be a xattr with | ||
5481 | * some REFCOUNT extent recs after the 1st one. | ||
5482 | */ | ||
5483 | if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) | ||
5484 | goto out; | ||
5485 | |||
5486 | ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), | ||
5487 | 1, ref_tree, &ref_root_bh); | ||
5488 | if (ret) { | ||
5489 | mlog_errno(ret); | ||
5490 | goto out; | ||
5491 | } | ||
5492 | |||
5493 | /* | ||
5494 | * If we are deleting the xattr or the new size will be stored inside, | ||
5495 | * cool, leave it there, the xattr truncate process will remove them | ||
5496 | * for us(it still needs the refcount tree lock and the meta, credits). | ||
5497 | * And the worse case is that every cluster truncate will split the | ||
5498 | * refcount tree, and make the original extent become 3. So we will need | ||
5499 | * 2 * cluster more extent recs at most. | ||
5500 | */ | ||
5501 | if (!xi->value || xi->value_len <= OCFS2_XATTR_INLINE_SIZE) { | ||
5502 | |||
5503 | ret = ocfs2_refcounted_xattr_delete_need(inode, | ||
5504 | &(*ref_tree)->rf_ci, | ||
5505 | ref_root_bh, vb.vb_xv, | ||
5506 | meta_add, credits); | ||
5507 | if (ret) | ||
5508 | mlog_errno(ret); | ||
5509 | goto out; | ||
5510 | } | ||
5511 | |||
5512 | ret = ocfs2_refcount_cow_xattr(inode, di, &vb, | ||
5513 | *ref_tree, ref_root_bh, 0, | ||
5514 | le32_to_cpu(vb.vb_xv->xr_clusters), p); | ||
5515 | if (ret) | ||
5516 | mlog_errno(ret); | ||
5517 | |||
5518 | out: | ||
5519 | brelse(ref_root_bh); | ||
5520 | return ret; | ||
5521 | } | ||
5522 | |||
5523 | /* | ||
5314 | * 'security' attributes support | 5524 | * 'security' attributes support |
5315 | */ | 5525 | */ |
5316 | static size_t ocfs2_xattr_security_list(struct inode *inode, char *list, | 5526 | static size_t ocfs2_xattr_security_list(struct inode *inode, char *list, |