diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-17 23:29:12 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 23:09:35 -0400 |
commit | bcbbb24a6a5c5b3e7b8e5284e0bfa23f45c32377 (patch) | |
tree | e45a6cfd75cd8005fdf280c2f5f57c09186249dd /fs/ocfs2/alloc.c | |
parent | 1aa75fea64bc26bda9be9b1b20ae253d7a481877 (diff) |
ocfs2: Decrement refcount when truncating refcounted extents.
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>
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r-- | fs/ocfs2/alloc.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 96f8ca6b3aba..03438a677933 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "super.h" | 49 | #include "super.h" |
50 | #include "uptodate.h" | 50 | #include "uptodate.h" |
51 | #include "xattr.h" | 51 | #include "xattr.h" |
52 | #include "refcounttree.h" | ||
52 | 53 | ||
53 | #include "buffer_head_io.h" | 54 | #include "buffer_head_io.h" |
54 | 55 | ||
@@ -6673,7 +6674,7 @@ out: | |||
6673 | */ | 6674 | */ |
6674 | static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, | 6675 | static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, |
6675 | handle_t *handle, struct ocfs2_truncate_context *tc, | 6676 | handle_t *handle, struct ocfs2_truncate_context *tc, |
6676 | u32 clusters_to_del, u64 *delete_start) | 6677 | u32 clusters_to_del, u64 *delete_start, u8 *flags) |
6677 | { | 6678 | { |
6678 | int ret, i, index = path->p_tree_depth; | 6679 | int ret, i, index = path->p_tree_depth; |
6679 | u32 new_edge = 0; | 6680 | u32 new_edge = 0; |
@@ -6683,6 +6684,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, | |||
6683 | struct ocfs2_extent_rec *rec; | 6684 | struct ocfs2_extent_rec *rec; |
6684 | 6685 | ||
6685 | *delete_start = 0; | 6686 | *delete_start = 0; |
6687 | *flags = 0; | ||
6686 | 6688 | ||
6687 | while (index >= 0) { | 6689 | while (index >= 0) { |
6688 | bh = path->p_node[index].bh; | 6690 | bh = path->p_node[index].bh; |
@@ -6770,6 +6772,7 @@ find_tail_record: | |||
6770 | *delete_start = le64_to_cpu(rec->e_blkno) | 6772 | *delete_start = le64_to_cpu(rec->e_blkno) |
6771 | + ocfs2_clusters_to_blocks(inode->i_sb, | 6773 | + ocfs2_clusters_to_blocks(inode->i_sb, |
6772 | le16_to_cpu(rec->e_leaf_clusters)); | 6774 | le16_to_cpu(rec->e_leaf_clusters)); |
6775 | *flags = rec->e_flags; | ||
6773 | 6776 | ||
6774 | /* | 6777 | /* |
6775 | * If it's now empty, remove this record. | 6778 | * If it's now empty, remove this record. |
@@ -6869,7 +6872,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
6869 | struct buffer_head *fe_bh, | 6872 | struct buffer_head *fe_bh, |
6870 | handle_t *handle, | 6873 | handle_t *handle, |
6871 | struct ocfs2_truncate_context *tc, | 6874 | struct ocfs2_truncate_context *tc, |
6872 | struct ocfs2_path *path) | 6875 | struct ocfs2_path *path, |
6876 | struct ocfs2_alloc_context *meta_ac) | ||
6873 | { | 6877 | { |
6874 | int status; | 6878 | int status; |
6875 | struct ocfs2_dinode *fe; | 6879 | struct ocfs2_dinode *fe; |
@@ -6877,6 +6881,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
6877 | struct ocfs2_extent_list *el; | 6881 | struct ocfs2_extent_list *el; |
6878 | struct buffer_head *last_eb_bh = NULL; | 6882 | struct buffer_head *last_eb_bh = NULL; |
6879 | u64 delete_blk = 0; | 6883 | u64 delete_blk = 0; |
6884 | u8 rec_flags; | ||
6880 | 6885 | ||
6881 | fe = (struct ocfs2_dinode *) fe_bh->b_data; | 6886 | fe = (struct ocfs2_dinode *) fe_bh->b_data; |
6882 | 6887 | ||
@@ -6932,7 +6937,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
6932 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 6937 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
6933 | 6938 | ||
6934 | status = ocfs2_trim_tree(inode, path, handle, tc, | 6939 | status = ocfs2_trim_tree(inode, path, handle, tc, |
6935 | clusters_to_del, &delete_blk); | 6940 | clusters_to_del, &delete_blk, &rec_flags); |
6936 | if (status) { | 6941 | if (status) { |
6937 | mlog_errno(status); | 6942 | mlog_errno(status); |
6938 | goto bail; | 6943 | goto bail; |
@@ -6964,8 +6969,16 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
6964 | } | 6969 | } |
6965 | 6970 | ||
6966 | if (delete_blk) { | 6971 | if (delete_blk) { |
6967 | status = ocfs2_truncate_log_append(osb, handle, delete_blk, | 6972 | if (rec_flags & OCFS2_EXT_REFCOUNTED) |
6968 | clusters_to_del); | 6973 | status = ocfs2_decrease_refcount(inode, handle, |
6974 | ocfs2_blocks_to_clusters(osb->sb, | ||
6975 | delete_blk), | ||
6976 | clusters_to_del, meta_ac, | ||
6977 | &tc->tc_dealloc); | ||
6978 | else | ||
6979 | status = ocfs2_truncate_log_append(osb, handle, | ||
6980 | delete_blk, | ||
6981 | clusters_to_del); | ||
6969 | if (status < 0) { | 6982 | if (status < 0) { |
6970 | mlog_errno(status); | 6983 | mlog_errno(status); |
6971 | goto bail; | 6984 | goto bail; |
@@ -7383,11 +7396,14 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, | |||
7383 | { | 7396 | { |
7384 | int status, i, credits, tl_sem = 0; | 7397 | int status, i, credits, tl_sem = 0; |
7385 | u32 clusters_to_del, new_highest_cpos, range; | 7398 | u32 clusters_to_del, new_highest_cpos, range; |
7399 | u64 blkno = 0; | ||
7386 | struct ocfs2_extent_list *el; | 7400 | struct ocfs2_extent_list *el; |
7387 | handle_t *handle = NULL; | 7401 | handle_t *handle = NULL; |
7388 | struct inode *tl_inode = osb->osb_tl_inode; | 7402 | struct inode *tl_inode = osb->osb_tl_inode; |
7389 | struct ocfs2_path *path = NULL; | 7403 | struct ocfs2_path *path = NULL; |
7390 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data; | 7404 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data; |
7405 | struct ocfs2_alloc_context *meta_ac = NULL; | ||
7406 | struct ocfs2_refcount_tree *ref_tree = NULL; | ||
7391 | 7407 | ||
7392 | mlog_entry_void(); | 7408 | mlog_entry_void(); |
7393 | 7409 | ||
@@ -7413,6 +7429,8 @@ start: | |||
7413 | goto bail; | 7429 | goto bail; |
7414 | } | 7430 | } |
7415 | 7431 | ||
7432 | credits = 0; | ||
7433 | |||
7416 | /* | 7434 | /* |
7417 | * Truncate always works against the rightmost tree branch. | 7435 | * Truncate always works against the rightmost tree branch. |
7418 | */ | 7436 | */ |
@@ -7453,10 +7471,15 @@ start: | |||
7453 | clusters_to_del = 0; | 7471 | clusters_to_del = 0; |
7454 | } else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) { | 7472 | } else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) { |
7455 | clusters_to_del = ocfs2_rec_clusters(el, &el->l_recs[i]); | 7473 | clusters_to_del = ocfs2_rec_clusters(el, &el->l_recs[i]); |
7474 | blkno = le64_to_cpu(el->l_recs[i].e_blkno); | ||
7456 | } else if (range > new_highest_cpos) { | 7475 | } else if (range > new_highest_cpos) { |
7457 | clusters_to_del = (ocfs2_rec_clusters(el, &el->l_recs[i]) + | 7476 | clusters_to_del = (ocfs2_rec_clusters(el, &el->l_recs[i]) + |
7458 | le32_to_cpu(el->l_recs[i].e_cpos)) - | 7477 | le32_to_cpu(el->l_recs[i].e_cpos)) - |
7459 | new_highest_cpos; | 7478 | new_highest_cpos; |
7479 | blkno = le64_to_cpu(el->l_recs[i].e_blkno) + | ||
7480 | ocfs2_clusters_to_blocks(inode->i_sb, | ||
7481 | ocfs2_rec_clusters(el, &el->l_recs[i]) - | ||
7482 | clusters_to_del); | ||
7460 | } else { | 7483 | } else { |
7461 | status = 0; | 7484 | status = 0; |
7462 | goto bail; | 7485 | goto bail; |
@@ -7465,6 +7488,29 @@ start: | |||
7465 | mlog(0, "clusters_to_del = %u in this pass, tail blk=%llu\n", | 7488 | mlog(0, "clusters_to_del = %u in this pass, tail blk=%llu\n", |
7466 | clusters_to_del, (unsigned long long)path_leaf_bh(path)->b_blocknr); | 7489 | clusters_to_del, (unsigned long long)path_leaf_bh(path)->b_blocknr); |
7467 | 7490 | ||
7491 | if (el->l_recs[i].e_flags & OCFS2_EXT_REFCOUNTED && clusters_to_del) { | ||
7492 | BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & | ||
7493 | OCFS2_HAS_REFCOUNT_FL)); | ||
7494 | |||
7495 | status = ocfs2_lock_refcount_tree(osb, | ||
7496 | le64_to_cpu(di->i_refcount_loc), | ||
7497 | 1, &ref_tree, NULL); | ||
7498 | if (status) { | ||
7499 | mlog_errno(status); | ||
7500 | goto bail; | ||
7501 | } | ||
7502 | |||
7503 | status = ocfs2_prepare_refcount_change_for_del(inode, fe_bh, | ||
7504 | blkno, | ||
7505 | clusters_to_del, | ||
7506 | &credits, | ||
7507 | &meta_ac); | ||
7508 | if (status < 0) { | ||
7509 | mlog_errno(status); | ||
7510 | goto bail; | ||
7511 | } | ||
7512 | } | ||
7513 | |||
7468 | mutex_lock(&tl_inode->i_mutex); | 7514 | mutex_lock(&tl_inode->i_mutex); |
7469 | tl_sem = 1; | 7515 | tl_sem = 1; |
7470 | /* ocfs2_truncate_log_needs_flush guarantees us at least one | 7516 | /* ocfs2_truncate_log_needs_flush guarantees us at least one |
@@ -7478,7 +7524,7 @@ start: | |||
7478 | } | 7524 | } |
7479 | } | 7525 | } |
7480 | 7526 | ||
7481 | credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del, | 7527 | credits += ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del, |
7482 | (struct ocfs2_dinode *)fe_bh->b_data, | 7528 | (struct ocfs2_dinode *)fe_bh->b_data, |
7483 | el); | 7529 | el); |
7484 | handle = ocfs2_start_trans(osb, credits); | 7530 | handle = ocfs2_start_trans(osb, credits); |
@@ -7490,7 +7536,7 @@ start: | |||
7490 | } | 7536 | } |
7491 | 7537 | ||
7492 | status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh, handle, | 7538 | status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh, handle, |
7493 | tc, path); | 7539 | tc, path, meta_ac); |
7494 | if (status < 0) { | 7540 | if (status < 0) { |
7495 | mlog_errno(status); | 7541 | mlog_errno(status); |
7496 | goto bail; | 7542 | goto bail; |
@@ -7504,6 +7550,16 @@ start: | |||
7504 | 7550 | ||
7505 | ocfs2_reinit_path(path, 1); | 7551 | ocfs2_reinit_path(path, 1); |
7506 | 7552 | ||
7553 | if (meta_ac) { | ||
7554 | ocfs2_free_alloc_context(meta_ac); | ||
7555 | meta_ac = NULL; | ||
7556 | } | ||
7557 | |||
7558 | if (ref_tree) { | ||
7559 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | ||
7560 | ref_tree = NULL; | ||
7561 | } | ||
7562 | |||
7507 | /* | 7563 | /* |
7508 | * The check above will catch the case where we've truncated | 7564 | * The check above will catch the case where we've truncated |
7509 | * away all allocation. | 7565 | * away all allocation. |
@@ -7520,6 +7576,12 @@ bail: | |||
7520 | if (handle) | 7576 | if (handle) |
7521 | ocfs2_commit_trans(osb, handle); | 7577 | ocfs2_commit_trans(osb, handle); |
7522 | 7578 | ||
7579 | if (meta_ac) | ||
7580 | ocfs2_free_alloc_context(meta_ac); | ||
7581 | |||
7582 | if (ref_tree) | ||
7583 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | ||
7584 | |||
7523 | ocfs2_run_deallocs(osb, &tc->tc_dealloc); | 7585 | ocfs2_run_deallocs(osb, &tc->tc_dealloc); |
7524 | 7586 | ||
7525 | ocfs2_free_path(path); | 7587 | ocfs2_free_path(path); |