mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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>
This commit is contained in:
parent
0129241e2b
commit
8b2c0dba51
6 changed files with 73 additions and 0 deletions
|
@ -531,6 +531,8 @@ bail_unlock_sem:
|
||||||
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
if (!status && OCFS2_I(inode)->ip_clusters == 0)
|
||||||
|
status = ocfs2_try_remove_refcount_tree(inode, di_bh);
|
||||||
|
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "sysfile.h"
|
#include "sysfile.h"
|
||||||
#include "uptodate.h"
|
#include "uptodate.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
|
#include "refcounttree.h"
|
||||||
|
|
||||||
#include "buffer_head_io.h"
|
#include "buffer_head_io.h"
|
||||||
|
|
||||||
|
@ -782,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode,
|
||||||
goto bail_unlock_dir;
|
goto bail_unlock_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = ocfs2_remove_refcount_tree(inode, di_bh);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto bail_unlock_dir;
|
||||||
|
}
|
||||||
|
|
||||||
status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
|
status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
|
||||||
orphan_dir_bh);
|
orphan_dir_bh);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
|
|
|
@ -926,6 +926,42 @@ out:
|
||||||
*index = i;
|
*index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to remove refcount tree. 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.
|
||||||
|
* 3) Check whether we have inline xattr stored outside, if yes, exit.
|
||||||
|
* 4) Remove the tree.
|
||||||
|
*/
|
||||||
|
int ocfs2_try_remove_refcount_tree(struct inode *inode,
|
||||||
|
struct buffer_head *di_bh)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ocfs2_inode_info *oi = OCFS2_I(inode);
|
||||||
|
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
|
||||||
|
|
||||||
|
down_write(&oi->ip_xattr_sem);
|
||||||
|
down_write(&oi->ip_alloc_sem);
|
||||||
|
|
||||||
|
if (oi->ip_clusters)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && di->i_xattr_loc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL &&
|
||||||
|
ocfs2_has_inline_xattr_value_outside(inode, di))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = ocfs2_remove_refcount_tree(inode, di_bh);
|
||||||
|
if (ret)
|
||||||
|
mlog_errno(ret);
|
||||||
|
out:
|
||||||
|
up_write(&oi->ip_alloc_sem);
|
||||||
|
up_write(&oi->ip_xattr_sem);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a cpos and len, try to find the refcount record which contains cpos.
|
* Given a cpos and len, try to find the refcount record which contains cpos.
|
||||||
* 1. If cpos can be found in one refcount record, return the record.
|
* 1. If cpos can be found in one refcount record, return the record.
|
||||||
|
|
|
@ -90,4 +90,7 @@ int ocfs2_add_refcount_flag(struct inode *inode,
|
||||||
u32 cpos, u32 p_cluster, u32 num_clusters,
|
u32 cpos, u32 p_cluster, u32 num_clusters,
|
||||||
struct ocfs2_cached_dealloc_ctxt *dealloc,
|
struct ocfs2_cached_dealloc_ctxt *dealloc,
|
||||||
struct ocfs2_post_refcount *post);
|
struct ocfs2_post_refcount *post);
|
||||||
|
int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh);
|
||||||
|
int ocfs2_try_remove_refcount_tree(struct inode *inode,
|
||||||
|
struct buffer_head *di_bh);
|
||||||
#endif /* OCFS2_REFCOUNTTREE_H */
|
#endif /* OCFS2_REFCOUNTTREE_H */
|
||||||
|
|
|
@ -840,6 +840,23 @@ static int ocfs2_xattr_list_entries(struct inode *inode,
|
||||||
return result;
|
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,
|
static int ocfs2_xattr_ibody_list(struct inode *inode,
|
||||||
struct ocfs2_dinode *di,
|
struct ocfs2_dinode *di,
|
||||||
char *buffer,
|
char *buffer,
|
||||||
|
@ -2898,10 +2915,16 @@ int ocfs2_xattr_set(struct inode *inode,
|
||||||
if (ocfs2_dealloc_has_cluster(&ctxt.dealloc))
|
if (ocfs2_dealloc_has_cluster(&ctxt.dealloc))
|
||||||
ocfs2_schedule_truncate_log_flush(osb, 1);
|
ocfs2_schedule_truncate_log_flush(osb, 1);
|
||||||
ocfs2_run_deallocs(osb, &ctxt.dealloc);
|
ocfs2_run_deallocs(osb, &ctxt.dealloc);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (ref_tree)
|
if (ref_tree)
|
||||||
ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
|
ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
|
||||||
up_write(&OCFS2_I(inode)->ip_xattr_sem);
|
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);
|
ocfs2_inode_unlock(inode, 1);
|
||||||
cleanup_nolock:
|
cleanup_nolock:
|
||||||
brelse(di_bh);
|
brelse(di_bh);
|
||||||
|
|
|
@ -55,6 +55,8 @@ int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *,
|
||||||
int, const char *, const void *, size_t, int,
|
int, const char *, const void *, size_t, int,
|
||||||
struct ocfs2_alloc_context *,
|
struct ocfs2_alloc_context *,
|
||||||
struct ocfs2_alloc_context *);
|
struct ocfs2_alloc_context *);
|
||||||
|
int ocfs2_has_inline_xattr_value_outside(struct inode *inode,
|
||||||
|
struct ocfs2_dinode *di);
|
||||||
int ocfs2_xattr_remove(struct inode *, struct buffer_head *);
|
int ocfs2_xattr_remove(struct inode *, struct buffer_head *);
|
||||||
int ocfs2_init_security_get(struct inode *, struct inode *,
|
int ocfs2_init_security_get(struct inode *, struct inode *,
|
||||||
struct ocfs2_security_xattr_info *);
|
struct ocfs2_security_xattr_info *);
|
||||||
|
|
Loading…
Reference in a new issue