diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-18 11:43:49 +0800 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 20:09:44 -0700 |
commit | 8b2c0dba5159570af5721d40490f6c529d721500 (patch) | |
tree | faca76fab3c9a65ba8e7be3aa93d02e4ff53f0cf /fs/ocfs2/xattr.c | |
parent | 0129241e2b3b90ff83a8c774353e5612d84bd493 (diff) | |
download | lwn-8b2c0dba5159570af5721d40490f6c529d721500.tar.gz lwn-8b2c0dba5159570af5721d40490f6c529d721500.zip |
ocfs2: Call refcount tree remove process properly.
Now with xattr refcount support, we need to check whether
we have xattr refcounted before we remove the refcount tree.
Now the mechanism is:
1) Check whether i_clusters == 0, if no, exit.
2) check whether we have i_xattr_loc in dinode. if yes, exit.
2) Check whether we have inline xattr stored outside, if yes, exit.
4) Remove the tree.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 501539a733f4..6660f1c6149e 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -840,6 +840,23 @@ static int ocfs2_xattr_list_entries(struct inode *inode, return result; } +int ocfs2_has_inline_xattr_value_outside(struct inode *inode, + struct ocfs2_dinode *di) +{ + struct ocfs2_xattr_header *xh; + int i; + + xh = (struct ocfs2_xattr_header *) + ((void *)di + inode->i_sb->s_blocksize - + le16_to_cpu(di->i_xattr_inline_size)); + + for (i = 0; i < le16_to_cpu(xh->xh_count); i++) + if (!ocfs2_xattr_is_local(&xh->xh_entries[i])) + return 1; + + return 0; +} + static int ocfs2_xattr_ibody_list(struct inode *inode, struct ocfs2_dinode *di, char *buffer, @@ -2898,10 +2915,16 @@ int ocfs2_xattr_set(struct inode *inode, if (ocfs2_dealloc_has_cluster(&ctxt.dealloc)) ocfs2_schedule_truncate_log_flush(osb, 1); ocfs2_run_deallocs(osb, &ctxt.dealloc); + cleanup: if (ref_tree) ocfs2_unlock_refcount_tree(osb, ref_tree, 1); up_write(&OCFS2_I(inode)->ip_xattr_sem); + if (!value && !ret) { + ret = ocfs2_try_remove_refcount_tree(inode, di_bh); + if (ret) + mlog_errno(ret); + } ocfs2_inode_unlock(inode, 1); cleanup_nolock: brelse(di_bh); |