Commit df0af1a5 authored by Miao Xie's avatar Miao Xie Committed by Josef Bacik

Btrfs: use the inode own lock to protect its delalloc_bytes

We need not use a global lock to protect the delalloc_bytes of the
inode, just use its own lock. In this way, we can reduce the lock
contention and ->delalloc_lock will just protect delalloc inode
list.
Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent 963d678b
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define BTRFS_INODE_HAS_ASYNC_EXTENT 6 #define BTRFS_INODE_HAS_ASYNC_EXTENT 6
#define BTRFS_INODE_NEEDS_FULL_SYNC 7 #define BTRFS_INODE_NEEDS_FULL_SYNC 7
#define BTRFS_INODE_COPY_EVERYTHING 8 #define BTRFS_INODE_COPY_EVERYTHING 8
#define BTRFS_INODE_IN_DELALLOC_LIST 9
/* in memory btrfs inode */ /* in memory btrfs inode */
struct btrfs_inode { struct btrfs_inode {
......
...@@ -3690,6 +3690,8 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root) ...@@ -3690,6 +3690,8 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
delalloc_inodes); delalloc_inodes);
list_del_init(&btrfs_inode->delalloc_inodes); list_del_init(&btrfs_inode->delalloc_inodes);
clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&btrfs_inode->runtime_flags);
btrfs_invalidate_inodes(btrfs_inode->root); btrfs_invalidate_inodes(btrfs_inode->root);
} }
......
...@@ -1514,16 +1514,23 @@ static void btrfs_set_bit_hook(struct inode *inode, ...@@ -1514,16 +1514,23 @@ static void btrfs_set_bit_hook(struct inode *inode,
spin_unlock(&BTRFS_I(inode)->lock); spin_unlock(&BTRFS_I(inode)->lock);
} }
spin_lock(&root->fs_info->delalloc_lock);
BTRFS_I(inode)->delalloc_bytes += len;
__percpu_counter_add(&root->fs_info->delalloc_bytes, len, __percpu_counter_add(&root->fs_info->delalloc_bytes, len,
root->fs_info->delalloc_batch); root->fs_info->delalloc_batch);
if (do_list && list_empty(&BTRFS_I(inode)->delalloc_inodes)) { spin_lock(&BTRFS_I(inode)->lock);
BTRFS_I(inode)->delalloc_bytes += len;
if (do_list && !test_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&BTRFS_I(inode)->runtime_flags)) {
spin_lock(&root->fs_info->delalloc_lock);
if (list_empty(&BTRFS_I(inode)->delalloc_inodes)) {
list_add_tail(&BTRFS_I(inode)->delalloc_inodes, list_add_tail(&BTRFS_I(inode)->delalloc_inodes,
&root->fs_info->delalloc_inodes); &root->fs_info->delalloc_inodes);
set_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&BTRFS_I(inode)->runtime_flags);
} }
spin_unlock(&root->fs_info->delalloc_lock); spin_unlock(&root->fs_info->delalloc_lock);
} }
spin_unlock(&BTRFS_I(inode)->lock);
}
} }
/* /*
...@@ -1557,17 +1564,23 @@ static void btrfs_clear_bit_hook(struct inode *inode, ...@@ -1557,17 +1564,23 @@ static void btrfs_clear_bit_hook(struct inode *inode,
&& do_list) && do_list)
btrfs_free_reserved_data_space(inode, len); btrfs_free_reserved_data_space(inode, len);
spin_lock(&root->fs_info->delalloc_lock);
__percpu_counter_add(&root->fs_info->delalloc_bytes, -len, __percpu_counter_add(&root->fs_info->delalloc_bytes, -len,
root->fs_info->delalloc_batch); root->fs_info->delalloc_batch);
spin_lock(&BTRFS_I(inode)->lock);
BTRFS_I(inode)->delalloc_bytes -= len; BTRFS_I(inode)->delalloc_bytes -= len;
if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 && if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 &&
!list_empty(&BTRFS_I(inode)->delalloc_inodes)) { test_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&BTRFS_I(inode)->runtime_flags)) {
spin_lock(&root->fs_info->delalloc_lock);
if (!list_empty(&BTRFS_I(inode)->delalloc_inodes)) {
list_del_init(&BTRFS_I(inode)->delalloc_inodes); list_del_init(&BTRFS_I(inode)->delalloc_inodes);
clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&BTRFS_I(inode)->runtime_flags);
} }
spin_unlock(&root->fs_info->delalloc_lock); spin_unlock(&root->fs_info->delalloc_lock);
} }
spin_unlock(&BTRFS_I(inode)->lock);
}
} }
/* /*
...@@ -7326,14 +7339,19 @@ int btrfs_init_cachep(void) ...@@ -7326,14 +7339,19 @@ int btrfs_init_cachep(void)
static int btrfs_getattr(struct vfsmount *mnt, static int btrfs_getattr(struct vfsmount *mnt,
struct dentry *dentry, struct kstat *stat) struct dentry *dentry, struct kstat *stat)
{ {
u64 delalloc_bytes;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
u32 blocksize = inode->i_sb->s_blocksize; u32 blocksize = inode->i_sb->s_blocksize;
generic_fillattr(inode, stat); generic_fillattr(inode, stat);
stat->dev = BTRFS_I(inode)->root->anon_dev; stat->dev = BTRFS_I(inode)->root->anon_dev;
stat->blksize = PAGE_CACHE_SIZE; stat->blksize = PAGE_CACHE_SIZE;
spin_lock(&BTRFS_I(inode)->lock);
delalloc_bytes = BTRFS_I(inode)->delalloc_bytes;
spin_unlock(&BTRFS_I(inode)->lock);
stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) + stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
ALIGN(BTRFS_I(inode)->delalloc_bytes, blocksize)) >> 9; ALIGN(delalloc_bytes, blocksize)) >> 9;
return 0; return 0;
} }
...@@ -7620,8 +7638,11 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) ...@@ -7620,8 +7638,11 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
list_del_init(&binode->delalloc_inodes); list_del_init(&binode->delalloc_inodes);
inode = igrab(&binode->vfs_inode); inode = igrab(&binode->vfs_inode);
if (!inode) if (!inode) {
clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&binode->runtime_flags);
continue; continue;
}
list_add_tail(&binode->delalloc_inodes, list_add_tail(&binode->delalloc_inodes,
&root->fs_info->delalloc_inodes); &root->fs_info->delalloc_inodes);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment