[Ocfs2-devel] [PATCH 23/39] ocfs2: lock refcount tree if needed.
Tao Ma
tao.ma at oracle.com
Wed Apr 29 15:58:35 PDT 2009
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
fs/ocfs2/alloc.c | 17 +++++++++++-
fs/ocfs2/refcounttree.c | 68 +++++++++++++++++++++++++++++------------------
2 files changed, 58 insertions(+), 27 deletions(-)
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 09f47f8..013e600 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -7283,6 +7283,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
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();
@@ -7294,11 +7295,21 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
if (!path) {
status = -ENOMEM;
mlog_errno(status);
- goto bail;
+ goto free;
}
ocfs2_extent_map_trunc(inode, new_highest_cpos);
+ if (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 free;
+ }
+ }
+
start:
/*
* Check that we still have allocation to delete.
@@ -7446,8 +7457,12 @@ bail:
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);
+free:
ocfs2_free_path(path);
/* This will drop the ext_alloc cluster lock for us */
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index ec9ee66..56c8c52 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -54,6 +54,9 @@ struct ocfs2_cow_context {
u32 cow_len;
};
+static void ocfs2_delete_refcount_tree(struct ocfs2_super *osb,
+ struct ocfs2_refcount_tree *tree);
+
static int ocfs2_validate_refcount_block(struct super_block *sb,
struct buffer_head *bh)
{
@@ -232,15 +235,16 @@ int ocfs2_set_refcount_tree(struct inode *inode,
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct buffer_head *ref_root_bh = NULL;
struct ocfs2_refcount_block *rb;
+ struct ocfs2_refcount_tree *ref_tree;
BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
BUG_ON(di->i_refcount_loc);
- ret = ocfs2_read_refcount_block(INODE_CACHE(inode),
- refcount_loc, &ref_root_bh);
+ ret = ocfs2_lock_refcount_tree(osb, refcount_loc, 1,
+ &ref_tree, &ref_root_bh);
if (ret) {
mlog_errno(ret);
- goto out;
+ return ret;
}
handle = ocfs2_start_trans(osb, OCFS2_REFCOUNT_TREE_SET_CREDITS);
@@ -275,9 +279,11 @@ int ocfs2_set_refcount_tree(struct inode *inode,
di->i_refcount_loc = cpu_to_le64(refcount_loc);
spin_unlock(&oi->ip_lock);
ocfs2_journal_dirty(handle, di_bh);
+
out_commit:
ocfs2_commit_trans(osb, handle);
out:
+ ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
brelse(ref_root_bh);
return ret;
@@ -285,7 +291,7 @@ out:
int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh)
{
- int ret;
+ int ret, delete_tree = 0;
handle_t *handle = NULL;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
@@ -294,19 +300,19 @@ int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh)
struct inode *alloc_inode = NULL;
struct buffer_head *alloc_bh = NULL;
struct buffer_head *blk_bh = NULL;
+ struct ocfs2_refcount_tree *ref_tree;
int credits = OCFS2_INODE_UPDATE_CREDITS + 1;
- u64 blk = 0, bg_blkno = 0;
+ u64 blk = 0, bg_blkno = 0, ref_blkno = le64_to_cpu(di->i_refcount_loc);
u16 bit = 0;
if (!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL))
return 0;
- ret = ocfs2_read_refcount_block(INODE_CACHE(inode),
- le64_to_cpu(di->i_refcount_loc),
- &blk_bh);
+ BUG_ON(!ref_blkno);
+ ret = ocfs2_lock_refcount_tree(osb, ref_blkno, 1, &ref_tree, &blk_bh);
if (ret) {
mlog_errno(ret);
- goto out;
+ return ret;
}
rb = (struct ocfs2_refcount_block *)blk_bh->b_data;
@@ -371,6 +377,7 @@ int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh)
ocfs2_journal_dirty(handle, blk_bh);
if (!rb->rf_count) {
+ delete_tree = 1;
ret = ocfs2_free_suballoc_bits(handle, alloc_inode,
alloc_bh, bit, bg_blkno, 1);
if (ret)
@@ -390,6 +397,9 @@ out_mutex:
iput(alloc_inode);
}
out:
+ ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+ if (delete_tree)
+ ocfs2_delete_refcount_tree(osb, ref_tree);
brelse(blk_bh);
return ret;
@@ -2422,9 +2432,11 @@ int ocfs2_refcount_cow(struct inode *inode,
int ret, has_data = 0, num_pages = 0;
u32 cow_start = 0, cow_len = 0;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
struct buffer_head *ref_root_bh = NULL;
struct page **pages = NULL;
+ struct ocfs2_refcount_tree *ref_tree;
loff_t start, end;
BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
@@ -2434,7 +2446,7 @@ int ocfs2_refcount_cow(struct inode *inode,
&cow_start, &cow_len, &has_data);
if (ret) {
mlog_errno(ret);
- goto out;
+ return ret;
}
mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, "
"cow_len %u\n", inode->i_ino,
@@ -2461,9 +2473,8 @@ int ocfs2_refcount_cow(struct inode *inode,
}
}
- ret = ocfs2_read_refcount_block(INODE_CACHE(inode),
- le64_to_cpu(di->i_refcount_loc),
- &ref_root_bh);
+ ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc),
+ 1, &ref_tree, &ref_root_bh);
if (ret) {
mlog_errno(ret);
goto out;
@@ -2474,12 +2485,13 @@ int ocfs2_refcount_cow(struct inode *inode,
if (ret)
mlog_errno(ret);
+ ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+ brelse(ref_root_bh);
out:
if (pages) {
ocfs2_unlock_and_free_pages(pages, num_pages);
kfree(pages);
}
- brelse(ref_root_bh);
return ret;
}
@@ -2557,6 +2569,8 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
struct buffer_head *ref_root_bh = NULL;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_refcount_tree *ref_tree;
unsigned int ext_flags;
loff_t size;
u32 cpos, num_clusters, clusters, p_cluster;
@@ -2574,9 +2588,9 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
}
BUG_ON(!di->i_refcount_loc);
- ret = ocfs2_read_refcount_block(INODE_CACHE(inode),
- le64_to_cpu(di->i_refcount_loc),
- &ref_root_bh);
+ ret = ocfs2_lock_refcount_tree(osb,
+ le64_to_cpu(di->i_refcount_loc), 1,
+ &ref_tree, &ref_root_bh);
if (ret) {
mlog_errno(ret);
goto out;
@@ -2612,13 +2626,14 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
* record from the disk.
*/
ocfs2_extent_map_trunc(inode, 0);
+ ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
brelse(ref_root_bh);
-out:
if (!ret && ocfs2_dealloc_has_cluster(&dealloc)) {
- ocfs2_schedule_truncate_log_flush(OCFS2_SB(inode->i_sb), 1);
- ocfs2_run_deallocs(OCFS2_SB(inode->i_sb), &dealloc);
+ ocfs2_schedule_truncate_log_flush(osb, 1);
+ ocfs2_run_deallocs(osb, &dealloc);
}
+out:
return ret;
}
@@ -2768,6 +2783,7 @@ static int ocfs2_create_reflink_node(struct inode *s_inode,
struct ocfs2_super *osb = OCFS2_SB(s_inode->i_sb);
struct ocfs2_refcount_block *rb;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)s_bh->b_data;
+ struct ocfs2_refcount_tree *ref_tree;
struct ocfs2_extent_list *el;
ocfs2_init_dealloc_ctxt(&dealloc);
@@ -2779,9 +2795,8 @@ static int ocfs2_create_reflink_node(struct inode *s_inode,
goto out;
}
- ret = ocfs2_read_refcount_block(INODE_CACHE(t_inode),
- le64_to_cpu(di->i_refcount_loc),
- &ref_root_bh);
+ ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc),
+ 1, &ref_tree, &ref_root_bh);
if (ret) {
mlog_errno(ret);
goto out;
@@ -2794,21 +2809,22 @@ static int ocfs2_create_reflink_node(struct inode *s_inode,
ref_root_bh, &dealloc);
if (ret) {
mlog_errno(ret);
- goto out;
+ goto out_unlock_refcount;
}
ret = ocfs2_complete_reflink(s_inode, t_inode, t_bh);
if (ret)
mlog_errno(ret);
+out_unlock_refcount:
+ ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+ brelse(ref_root_bh);
out:
if (ocfs2_dealloc_has_cluster(&dealloc)) {
ocfs2_schedule_truncate_log_flush(osb, 1);
ocfs2_run_deallocs(osb, &dealloc);
}
- brelse(ref_root_bh);
-
return ret;
}
--
1.6.2.rc2.16.gf474c
More information about the Ocfs2-devel
mailing list