aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2011-11-18 04:43:00 -0500
committerDavid Sterba <dsterba@suse.cz>2011-11-30 12:46:03 -0500
commitaa38a711a893accf5b5192f3d705a120deaa81e0 (patch)
tree59dbb3bca55b7141ba0e0fda1031452ae87a6935 /fs/btrfs/extent-tree.c
parentb52f75a595e8a70ee453bd6fb8023ee294f7a729 (diff)
Btrfs: fix deadlock on metadata reservation when evicting a inode
When I ran the xfstests, I found the test tasks was blocked on meta-data reservation. By debugging, I found the reason of this bug: start transaction | v reserve meta-data space | v flush delay allocation -> iput inode -> evict inode ^ | | v wait for delay allocation flush <- reserve meta-data space And besides that, the flush on evicting inode will block the thread, which is reclaiming the memory, and make oom happen easily. Fix this bug by skipping the flush step when evicting inode. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5d86877f10e1..b7e5f6898d07 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3887,9 +3887,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
3887 return ret; 3887 return ret;
3888} 3888}
3889 3889
3890int btrfs_block_rsv_refill(struct btrfs_root *root, 3890static inline int __btrfs_block_rsv_refill(struct btrfs_root *root,
3891 struct btrfs_block_rsv *block_rsv, 3891 struct btrfs_block_rsv *block_rsv,
3892 u64 min_reserved) 3892 u64 min_reserved, int flush)
3893{ 3893{
3894 u64 num_bytes = 0; 3894 u64 num_bytes = 0;
3895 int ret = -ENOSPC; 3895 int ret = -ENOSPC;
@@ -3908,7 +3908,7 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
3908 if (!ret) 3908 if (!ret)
3909 return 0; 3909 return 0;
3910 3910
3911 ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1); 3911 ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
3912 if (!ret) { 3912 if (!ret) {
3913 block_rsv_add_bytes(block_rsv, num_bytes, 0); 3913 block_rsv_add_bytes(block_rsv, num_bytes, 0);
3914 return 0; 3914 return 0;
@@ -3917,6 +3917,20 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
3917 return ret; 3917 return ret;
3918} 3918}
3919 3919
3920int btrfs_block_rsv_refill(struct btrfs_root *root,
3921 struct btrfs_block_rsv *block_rsv,
3922 u64 min_reserved)
3923{
3924 return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 1);
3925}
3926
3927int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
3928 struct btrfs_block_rsv *block_rsv,
3929 u64 min_reserved)
3930{
3931 return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 0);
3932}
3933
3920int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, 3934int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
3921 struct btrfs_block_rsv *dst_rsv, 3935 struct btrfs_block_rsv *dst_rsv,
3922 u64 num_bytes) 3936 u64 num_bytes)