Skip to content

Commit

Permalink
ocfs2: Decrement refcount when truncating refcounted extents.
Browse files Browse the repository at this point in the history
Add 'Decrement refcount for delete' in to the normal truncate
process. So for a refcounted extent record, call refcount rec
decrementation instead of cluster free.

Signed-off-by: Tao Ma <tao.ma@oracle.com>
  • Loading branch information
Tao Ma authored and Joel Becker committed Sep 23, 2009
1 parent 1aa75fe commit bcbbb24
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 7 deletions.
76 changes: 69 additions & 7 deletions fs/ocfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "super.h"
#include "uptodate.h"
#include "xattr.h"
#include "refcounttree.h"

#include "buffer_head_io.h"

Expand Down Expand Up @@ -6673,7 +6674,7 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode,
*/
static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
handle_t *handle, struct ocfs2_truncate_context *tc,
u32 clusters_to_del, u64 *delete_start)
u32 clusters_to_del, u64 *delete_start, u8 *flags)
{
int ret, i, index = path->p_tree_depth;
u32 new_edge = 0;
Expand All @@ -6683,6 +6684,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
struct ocfs2_extent_rec *rec;

*delete_start = 0;
*flags = 0;

while (index >= 0) {
bh = path->p_node[index].bh;
Expand Down Expand Up @@ -6770,6 +6772,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
*delete_start = le64_to_cpu(rec->e_blkno)
+ ocfs2_clusters_to_blocks(inode->i_sb,
le16_to_cpu(rec->e_leaf_clusters));
*flags = rec->e_flags;

/*
* If it's now empty, remove this record.
Expand Down Expand Up @@ -6869,14 +6872,16 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
struct buffer_head *fe_bh,
handle_t *handle,
struct ocfs2_truncate_context *tc,
struct ocfs2_path *path)
struct ocfs2_path *path,
struct ocfs2_alloc_context *meta_ac)
{
int status;
struct ocfs2_dinode *fe;
struct ocfs2_extent_block *last_eb = NULL;
struct ocfs2_extent_list *el;
struct buffer_head *last_eb_bh = NULL;
u64 delete_blk = 0;
u8 rec_flags;

fe = (struct ocfs2_dinode *) fe_bh->b_data;

Expand Down Expand Up @@ -6932,7 +6937,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
inode->i_blocks = ocfs2_inode_sector_count(inode);

status = ocfs2_trim_tree(inode, path, handle, tc,
clusters_to_del, &delete_blk);
clusters_to_del, &delete_blk, &rec_flags);
if (status) {
mlog_errno(status);
goto bail;
Expand Down Expand Up @@ -6964,8 +6969,16 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
}

if (delete_blk) {
status = ocfs2_truncate_log_append(osb, handle, delete_blk,
clusters_to_del);
if (rec_flags & OCFS2_EXT_REFCOUNTED)
status = ocfs2_decrease_refcount(inode, handle,
ocfs2_blocks_to_clusters(osb->sb,
delete_blk),
clusters_to_del, meta_ac,
&tc->tc_dealloc);
else
status = ocfs2_truncate_log_append(osb, handle,
delete_blk,
clusters_to_del);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand Down Expand Up @@ -7383,11 +7396,14 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
{
int status, i, credits, tl_sem = 0;
u32 clusters_to_del, new_highest_cpos, range;
u64 blkno = 0;
struct ocfs2_extent_list *el;
handle_t *handle = NULL;
struct inode *tl_inode = osb->osb_tl_inode;
struct ocfs2_path *path = NULL;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
struct ocfs2_alloc_context *meta_ac = NULL;
struct ocfs2_refcount_tree *ref_tree = NULL;

mlog_entry_void();

Expand All @@ -7413,6 +7429,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
goto bail;
}

credits = 0;

/*
* Truncate always works against the rightmost tree branch.
*/
Expand Down Expand Up @@ -7453,10 +7471,15 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
clusters_to_del = 0;
} else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) {
clusters_to_del = ocfs2_rec_clusters(el, &el->l_recs[i]);
blkno = le64_to_cpu(el->l_recs[i].e_blkno);
} else if (range > new_highest_cpos) {
clusters_to_del = (ocfs2_rec_clusters(el, &el->l_recs[i]) +
le32_to_cpu(el->l_recs[i].e_cpos)) -
new_highest_cpos;
blkno = le64_to_cpu(el->l_recs[i].e_blkno) +
ocfs2_clusters_to_blocks(inode->i_sb,
ocfs2_rec_clusters(el, &el->l_recs[i]) -
clusters_to_del);
} else {
status = 0;
goto bail;
Expand All @@ -7465,6 +7488,29 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
mlog(0, "clusters_to_del = %u in this pass, tail blk=%llu\n",
clusters_to_del, (unsigned long long)path_leaf_bh(path)->b_blocknr);

if (el->l_recs[i].e_flags & OCFS2_EXT_REFCOUNTED && clusters_to_del) {
BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
OCFS2_HAS_REFCOUNT_FL));

status = ocfs2_lock_refcount_tree(osb,
le64_to_cpu(di->i_refcount_loc),
1, &ref_tree, NULL);
if (status) {
mlog_errno(status);
goto bail;
}

status = ocfs2_prepare_refcount_change_for_del(inode, fe_bh,
blkno,
clusters_to_del,
&credits,
&meta_ac);
if (status < 0) {
mlog_errno(status);
goto bail;
}
}

mutex_lock(&tl_inode->i_mutex);
tl_sem = 1;
/* ocfs2_truncate_log_needs_flush guarantees us at least one
Expand All @@ -7478,7 +7524,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
}
}

credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
credits += ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
(struct ocfs2_dinode *)fe_bh->b_data,
el);
handle = ocfs2_start_trans(osb, credits);
Expand All @@ -7490,7 +7536,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
}

status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh, handle,
tc, path);
tc, path, meta_ac);
if (status < 0) {
mlog_errno(status);
goto bail;
Expand All @@ -7504,6 +7550,16 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,

ocfs2_reinit_path(path, 1);

if (meta_ac) {
ocfs2_free_alloc_context(meta_ac);
meta_ac = NULL;
}

if (ref_tree) {
ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
ref_tree = NULL;
}

/*
* The check above will catch the case where we've truncated
* away all allocation.
Expand All @@ -7520,6 +7576,12 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
if (handle)
ocfs2_commit_trans(osb, handle);

if (meta_ac)
ocfs2_free_alloc_context(meta_ac);

if (ref_tree)
ocfs2_unlock_refcount_tree(osb, ref_tree, 1);

ocfs2_run_deallocs(osb, &tc->tc_dealloc);

ocfs2_free_path(path);
Expand Down
3 changes: 3 additions & 0 deletions fs/ocfs2/journal.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ static inline int ocfs2_calc_dxi_expand_credits(struct super_block *sb)
*/
#define OCFS2_REFCOUNT_TREE_REMOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)

/* 2 metadata alloc, 2 new blocks and root refcount block */
#define OCFS2_EXPAND_REFCOUNT_TREE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + 3)

/*
* Please note that the caller must make sure that root_el is the root
* of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
Expand Down
Loading

0 comments on commit bcbbb24

Please sign in to comment.