Skip to content

Commit aa38a71

Browse files
Miao Xiekdave
authored andcommitted
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 <[email protected]>
1 parent b52f75a commit aa38a71

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

fs/btrfs/ctree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
23692369
int btrfs_block_rsv_refill(struct btrfs_root *root,
23702370
struct btrfs_block_rsv *block_rsv,
23712371
u64 min_reserved);
2372+
int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
2373+
struct btrfs_block_rsv *block_rsv,
2374+
u64 min_reserved);
23722375
int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
23732376
struct btrfs_block_rsv *dst_rsv,
23742377
u64 num_bytes);

fs/btrfs/extent-tree.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,9 +3887,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
38873887
return ret;
38883888
}
38893889

3890-
int btrfs_block_rsv_refill(struct btrfs_root *root,
3891-
struct btrfs_block_rsv *block_rsv,
3892-
u64 min_reserved)
3890+
static inline int __btrfs_block_rsv_refill(struct btrfs_root *root,
3891+
struct btrfs_block_rsv *block_rsv,
3892+
u64 min_reserved, int flush)
38933893
{
38943894
u64 num_bytes = 0;
38953895
int ret = -ENOSPC;
@@ -3908,7 +3908,7 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
39083908
if (!ret)
39093909
return 0;
39103910

3911-
ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1);
3911+
ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
39123912
if (!ret) {
39133913
block_rsv_add_bytes(block_rsv, num_bytes, 0);
39143914
return 0;
@@ -3917,6 +3917,20 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
39173917
return ret;
39183918
}
39193919

3920+
int 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+
3927+
int 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+
39203934
int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
39213935
struct btrfs_block_rsv *dst_rsv,
39223936
u64 num_bytes)

fs/btrfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3490,7 +3490,7 @@ void btrfs_evict_inode(struct inode *inode)
34903490
* doing the truncate.
34913491
*/
34923492
while (1) {
3493-
ret = btrfs_block_rsv_refill(root, rsv, min_size);
3493+
ret = btrfs_block_rsv_refill_noflush(root, rsv, min_size);
34943494

34953495
/*
34963496
* Try and steal from the global reserve since we will

0 commit comments

Comments
 (0)