Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165129
b: refs/heads/master
c: 8b2c0db
h: refs/heads/master
i:
  165127: 52b5475
v: v3
  • Loading branch information
Tao Ma authored and Joel Becker committed Sep 23, 2009
1 parent 20cb066 commit 0748a05
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0129241e2b3b90ff83a8c774353e5612d84bd493
refs/heads/master: 8b2c0dba5159570af5721d40490f6c529d721500
2 changes: 2 additions & 0 deletions trunk/fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ static int ocfs2_truncate_file(struct inode *inode,
up_write(&OCFS2_I(inode)->ip_alloc_sem);

bail:
if (!status && OCFS2_I(inode)->ip_clusters == 0)
status = ocfs2_try_remove_refcount_tree(inode, di_bh);

mlog_exit(status);
return status;
Expand Down
7 changes: 7 additions & 0 deletions trunk/fs/ocfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "sysfile.h"
#include "uptodate.h"
#include "xattr.h"
#include "refcounttree.h"

#include "buffer_head_io.h"

Expand Down Expand Up @@ -782,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode,
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,
orphan_dir_bh);
if (status < 0)
Expand Down
36 changes: 36 additions & 0 deletions trunk/fs/ocfs2/refcounttree.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,42 @@ static void ocfs2_find_refcount_rec_in_rl(struct ocfs2_caching_info *ci,
*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.
* 1. If cpos can be found in one refcount record, return the record.
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/ocfs2/refcounttree.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,7 @@ int ocfs2_add_refcount_flag(struct inode *inode,
u32 cpos, u32 p_cluster, u32 num_clusters,
struct ocfs2_cached_dealloc_ctxt *dealloc,
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 */
23 changes: 23 additions & 0 deletions trunk/fs/ocfs2/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/ocfs2/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *,
int, const char *, const void *, size_t, int,
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_init_security_get(struct inode *, struct inode *,
struct ocfs2_security_xattr_info *);
Expand Down

0 comments on commit 0748a05

Please sign in to comment.