Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165132
b: refs/heads/master
c: ce9c5a5
h: refs/heads/master
v: v3
  • Loading branch information
Tao Ma authored and Joel Becker committed Sep 23, 2009
1 parent 296e394 commit 9f9d9f5
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2999d12f4d5529b282ce201b21444590c3f9f723
refs/heads/master: ce9c5a54c0f06b0efb4db8720a0616cc6aa0e5b2
190 changes: 154 additions & 36 deletions trunk/fs/ocfs2/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ static int ocfs2_prepare_refcount_xattr(struct inode *inode,
struct ocfs2_refcount_tree **ref_tree,
int *meta_need,
int *credits);
static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
struct ocfs2_xattr_bucket *bucket,
int offset,
struct ocfs2_xattr_value_root **xv,
struct buffer_head **bh);

static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
{
Expand Down Expand Up @@ -1752,51 +1757,112 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
return ret;
}

/*
* In xattr remove, if it is stored outside and refcounted, we may have
* the chance to split the refcount tree. So need the allocators.
*/
static int ocfs2_lock_xattr_remove_allocators(struct inode *inode,
struct ocfs2_xattr_value_root *xv,
struct ocfs2_caching_info *ref_ci,
struct buffer_head *ref_root_bh,
struct ocfs2_alloc_context **meta_ac,
int *ref_credits)
{
int ret, meta_add = 0;
u32 p_cluster, num_clusters;
unsigned int ext_flags;

*ref_credits = 0;
ret = ocfs2_xattr_get_clusters(inode, 0, &p_cluster,
&num_clusters,
&xv->xr_list,
&ext_flags);
if (ret) {
mlog_errno(ret);
goto out;
}

if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
goto out;

ret = ocfs2_refcounted_xattr_delete_need(inode, ref_ci,
ref_root_bh, xv,
&meta_add, ref_credits);
if (ret) {
mlog_errno(ret);
goto out;
}

ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb),
meta_add, meta_ac);
if (ret)
mlog_errno(ret);

out:
return ret;
}

static int ocfs2_remove_value_outside(struct inode*inode,
struct ocfs2_xattr_value_buf *vb,
struct ocfs2_xattr_header *header)
struct ocfs2_xattr_header *header,
struct ocfs2_caching_info *ref_ci,
struct buffer_head *ref_root_bh)
{
int ret = 0, i;
int ret = 0, i, ref_credits;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
void *val;

ocfs2_init_dealloc_ctxt(&ctxt.dealloc);

ctxt.handle = ocfs2_start_trans(osb,
ocfs2_remove_extent_credits(osb->sb));
if (IS_ERR(ctxt.handle)) {
ret = PTR_ERR(ctxt.handle);
mlog_errno(ret);
goto out;
}

for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
struct ocfs2_xattr_entry *entry = &header->xh_entries[i];

if (!ocfs2_xattr_is_local(entry)) {
void *val;
if (ocfs2_xattr_is_local(entry))
continue;

val = (void *)header +
le16_to_cpu(entry->xe_name_offset);
vb->vb_xv = (struct ocfs2_xattr_value_root *)
(val + OCFS2_XATTR_SIZE(entry->xe_name_len));
ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
if (ret < 0) {
mlog_errno(ret);
break;
}
val = (void *)header +
le16_to_cpu(entry->xe_name_offset);
vb->vb_xv = (struct ocfs2_xattr_value_root *)
(val + OCFS2_XATTR_SIZE(entry->xe_name_len));

ret = ocfs2_lock_xattr_remove_allocators(inode, vb->vb_xv,
ref_ci, ref_root_bh,
&ctxt.meta_ac,
&ref_credits);

ctxt.handle = ocfs2_start_trans(osb, ref_credits +
ocfs2_remove_extent_credits(osb->sb));
if (IS_ERR(ctxt.handle)) {
ret = PTR_ERR(ctxt.handle);
mlog_errno(ret);
break;
}

ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
if (ret < 0) {
mlog_errno(ret);
break;
}

ocfs2_commit_trans(osb, ctxt.handle);
if (ctxt.meta_ac) {
ocfs2_free_alloc_context(ctxt.meta_ac);
ctxt.meta_ac = NULL;
}
}

ocfs2_commit_trans(osb, ctxt.handle);
if (ctxt.meta_ac)
ocfs2_free_alloc_context(ctxt.meta_ac);
ocfs2_schedule_truncate_log_flush(osb, 1);
ocfs2_run_deallocs(osb, &ctxt.dealloc);
out:
return ret;
}

static int ocfs2_xattr_ibody_remove(struct inode *inode,
struct buffer_head *di_bh)
struct buffer_head *di_bh,
struct ocfs2_caching_info *ref_ci,
struct buffer_head *ref_root_bh)
{

struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
Expand All @@ -1811,36 +1877,51 @@ static int ocfs2_xattr_ibody_remove(struct inode *inode,
((void *)di + inode->i_sb->s_blocksize -
le16_to_cpu(di->i_xattr_inline_size));

ret = ocfs2_remove_value_outside(inode, &vb, header);
ret = ocfs2_remove_value_outside(inode, &vb, header,
ref_ci, ref_root_bh);

return ret;
}

struct ocfs2_rm_xattr_bucket_para {
struct ocfs2_caching_info *ref_ci;
struct buffer_head *ref_root_bh;
};

static int ocfs2_xattr_block_remove(struct inode *inode,
struct buffer_head *blk_bh)
struct buffer_head *blk_bh,
struct ocfs2_caching_info *ref_ci,
struct buffer_head *ref_root_bh)
{
struct ocfs2_xattr_block *xb;
int ret = 0;
struct ocfs2_xattr_value_buf vb = {
.vb_bh = blk_bh,
.vb_access = ocfs2_journal_access_xb,
};
struct ocfs2_rm_xattr_bucket_para args = {
.ref_ci = ref_ci,
.ref_root_bh = ref_root_bh,
};

xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header);
ret = ocfs2_remove_value_outside(inode, &vb, header);
ret = ocfs2_remove_value_outside(inode, &vb, header,
ref_ci, ref_root_bh);
} else
ret = ocfs2_iterate_xattr_index_block(inode,
blk_bh,
ocfs2_rm_xattr_cluster,
NULL);
&args);

return ret;
}

static int ocfs2_xattr_free_block(struct inode *inode,
u64 block)
u64 block,
struct ocfs2_caching_info *ref_ci,
struct buffer_head *ref_root_bh)
{
struct inode *xb_alloc_inode;
struct buffer_head *xb_alloc_bh = NULL;
Expand All @@ -1858,7 +1939,7 @@ static int ocfs2_xattr_free_block(struct inode *inode,
goto out;
}

ret = ocfs2_xattr_block_remove(inode, blk_bh);
ret = ocfs2_xattr_block_remove(inode, blk_bh, ref_ci, ref_root_bh);
if (ret < 0) {
mlog_errno(ret);
goto out;
Expand Down Expand Up @@ -1918,6 +1999,9 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
{
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
struct ocfs2_refcount_tree *ref_tree = NULL;
struct buffer_head *ref_root_bh = NULL;
struct ocfs2_caching_info *ref_ci = NULL;
handle_t *handle;
int ret;

Expand All @@ -1927,8 +2011,21 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
return 0;

if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
ret = ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb),
le64_to_cpu(di->i_refcount_loc),
1, &ref_tree, &ref_root_bh);
if (ret) {
mlog_errno(ret);
goto out;
}
ref_ci = &ref_tree->rf_ci;

}

if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
ret = ocfs2_xattr_ibody_remove(inode, di_bh);
ret = ocfs2_xattr_ibody_remove(inode, di_bh,
ref_ci, ref_root_bh);
if (ret < 0) {
mlog_errno(ret);
goto out;
Expand All @@ -1937,7 +2034,8 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)

if (di->i_xattr_loc) {
ret = ocfs2_xattr_free_block(inode,
le64_to_cpu(di->i_xattr_loc));
le64_to_cpu(di->i_xattr_loc),
ref_ci, ref_root_bh);
if (ret < 0) {
mlog_errno(ret);
goto out;
Expand Down Expand Up @@ -1971,6 +2069,9 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
out_commit:
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
out:
if (ref_tree)
ocfs2_unlock_refcount_tree(OCFS2_SB(inode->i_sb), ref_tree, 1);
brelse(ref_root_bh);
return ret;
}

Expand Down Expand Up @@ -4989,7 +5090,7 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode,
struct ocfs2_extent_tree et;

ret = ocfs2_iterate_xattr_buckets(inode, blkno, len,
ocfs2_delete_xattr_in_bucket, NULL);
ocfs2_delete_xattr_in_bucket, para);
if (ret) {
mlog_errno(ret);
return ret;
Expand Down Expand Up @@ -5378,15 +5479,17 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
struct ocfs2_xattr_bucket *bucket,
void *para)
{
int ret = 0;
int ret = 0, ref_credits;
struct ocfs2_xattr_header *xh = bucket_xh(bucket);
u16 i;
struct ocfs2_xattr_entry *xe;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,};
int credits = ocfs2_remove_extent_credits(osb->sb) +
ocfs2_blocks_per_xattr_bucket(inode->i_sb);

struct ocfs2_xattr_value_root *xv;
struct ocfs2_rm_xattr_bucket_para *args =
(struct ocfs2_rm_xattr_bucket_para *)para;

ocfs2_init_dealloc_ctxt(&ctxt.dealloc);

Expand All @@ -5395,7 +5498,16 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
if (ocfs2_xattr_is_local(xe))
continue;

ctxt.handle = ocfs2_start_trans(osb, credits);
ret = ocfs2_get_xattr_tree_value_root(inode->i_sb, bucket,
i, &xv, NULL);

ret = ocfs2_lock_xattr_remove_allocators(inode, xv,
args->ref_ci,
args->ref_root_bh,
&ctxt.meta_ac,
&ref_credits);

ctxt.handle = ocfs2_start_trans(osb, credits + ref_credits);
if (IS_ERR(ctxt.handle)) {
ret = PTR_ERR(ctxt.handle);
mlog_errno(ret);
Expand All @@ -5406,12 +5518,18 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
i, 0, &ctxt);

ocfs2_commit_trans(osb, ctxt.handle);
if (ctxt.meta_ac) {
ocfs2_free_alloc_context(ctxt.meta_ac);
ctxt.meta_ac = NULL;
}
if (ret) {
mlog_errno(ret);
break;
}
}

if (ctxt.meta_ac)
ocfs2_free_alloc_context(ctxt.meta_ac);
ocfs2_schedule_truncate_log_flush(osb, 1);
ocfs2_run_deallocs(osb, &ctxt.dealloc);
return ret;
Expand Down

0 comments on commit 9f9d9f5

Please sign in to comment.