xattr need refcount tree support, but some functions don't have an easy access to the inode bh, so add a helper function which read inode_bh first and then get the refcount tree.
And in order to speed up the refcount searching, we add a LRU to the ocfs2_super so that we can find a recently used refcount tree more quickly. Signed-off-by: Tao Ma <[email protected]> --- fs/ocfs2/ocfs2.h | 1 + fs/ocfs2/refcounttree.c | 85 ++++++++++++++++++++++++++++++++++++++++------- fs/ocfs2/refcounttree.h | 1 - 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 3f62291..9ea1b30 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -383,6 +383,7 @@ struct ocfs2_super /* rb tree root for refcount lock. */ struct rb_root osb_rf_lock_tree; + struct ocfs2_refcount_tree *osb_ref_tree_lru; }; #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 4ef6bd2..a12d739 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -3140,7 +3140,11 @@ static int ocfs2_get_refcount_tree(struct ocfs2_super *osb, u64 rf_blkno, struct ocfs2_refcount_tree *tree, *new = NULL; spin_lock(&osb->osb_lock); - tree = ocfs2_find_refcount_tree(osb, rf_blkno); + if (osb->osb_ref_tree_lru && + osb->osb_ref_tree_lru->rf_blkno == rf_blkno) + tree = osb->osb_ref_tree_lru; + else + tree = ocfs2_find_refcount_tree(osb, rf_blkno); if (tree) goto out; @@ -3176,29 +3180,48 @@ out: *ret_tree = tree; + osb->osb_ref_tree_lru = tree; spin_unlock(&osb->osb_lock); return ret; } -/* - * Lock the refcount tree pointed by ref_blkno and return the tree. - * In most case, we lock the tree and read the refcount block. - * So read it here if the caller really need it. - */ -int ocfs2_lock_refcount_tree(struct ocfs2_super *osb, u64 ref_blkno, int rw, - struct ocfs2_refcount_tree **ret_tree, - struct buffer_head **ref_bh) +/* Search refcount tree by inode. */ +static int ocfs2_get_refcount_tree_by_inode(struct inode *inode, + struct ocfs2_refcount_tree **ret_tree) { int ret; - struct ocfs2_refcount_tree *tree = NULL; + struct buffer_head *di_bh = NULL; + struct ocfs2_dinode *di; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - ret = ocfs2_get_refcount_tree(osb, ref_blkno, &tree); + /* We have never touch refcount tree for this inode. So let us do it. */ + ret = ocfs2_read_inode_block(inode, &di_bh); if (ret) { mlog_errno(ret); goto out; } + BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); + + di = (struct ocfs2_dinode *)di_bh->b_data; + ret = ocfs2_get_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), + ret_tree); + if (ret) + mlog_errno(ret); + + brelse(di_bh); +out: + return ret; +} + +static int __ocfs2_lock_refcount_tree(struct ocfs2_super *osb, + struct ocfs2_refcount_tree *tree, int rw, + struct ocfs2_refcount_tree **ret_tree, + struct buffer_head **ref_bh) +{ + int ret; + ret = ocfs2_refcount_lock(&tree->rf_lockres, rw); if (ret) { mlog_errno(ret); @@ -3212,7 +3235,7 @@ int ocfs2_lock_refcount_tree(struct ocfs2_super *osb, u64 ref_blkno, int rw, if (ref_bh) { ret = ocfs2_read_refcount_block(&tree->rf_ci, - ref_blkno, ref_bh); + tree->rf_blkno, ref_bh); if (ret) { mlog_errno(ret); ocfs2_unlock_refcount_tree(osb, tree, rw); @@ -3225,6 +3248,44 @@ out: return ret; } +/* + * Lock the refcount tree pointed by ref_blkno and return the tree. + * In most case, we lock the tree and read the refcount block. + * So read it here if the caller really need it. + */ +int ocfs2_lock_refcount_tree(struct ocfs2_super *osb, u64 ref_blkno, int rw, + struct ocfs2_refcount_tree **ret_tree, + struct buffer_head **ref_bh) +{ + int ret; + struct ocfs2_refcount_tree *tree = NULL; + + ret = ocfs2_get_refcount_tree(osb, ref_blkno, &tree); + if (ret) { + mlog_errno(ret); + return ret; + } + + return __ocfs2_lock_refcount_tree(osb, tree, rw, ret_tree, ref_bh); +} + +int ocfs2_lock_refcount_tree_by_inode(struct inode *inode, int rw, + struct ocfs2_refcount_tree **ret_tree, + struct buffer_head **ref_bh) +{ + int ret; + struct ocfs2_refcount_tree *tree = NULL; + + ret = ocfs2_get_refcount_tree_by_inode(inode, &tree); + if (ret) { + mlog_errno(ret); + return ret; + } + + return __ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb), tree, + rw, ret_tree, ref_bh); +} + void ocfs2_unlock_refcount_tree(struct ocfs2_super *osb, struct ocfs2_refcount_tree *tree, int rw) { diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h index b7fb077..ed86f65 100644 --- a/fs/ocfs2/refcounttree.h +++ b/fs/ocfs2/refcounttree.h @@ -28,7 +28,6 @@ struct ocfs2_refcount_tree { spinlock_t rf_lock; struct mutex rf_io_mutex; struct super_block *rf_sb; - }; static inline struct ocfs2_refcount_tree * -- 1.6.2.rc2.16.gf474c _______________________________________________ Ocfs2-devel mailing list [email protected] http://oss.oracle.com/mailman/listinfo/ocfs2-devel
