Skip to content

Commit 44d354a

Browse files
adam900710kdave
authored andcommitted
btrfs: relocation: review the call sites which can be interrupted by signal
Since most metadata reservation calls can return -EINTR when get interrupted by fatal signal, we need to review the all the metadata reservation call sites. In relocation code, the metadata reservation happens in the following sites: - btrfs_block_rsv_refill() in merge_reloc_root() merge_reloc_root() is a pretty critical section, we don't want to be interrupted by signal, so change the flush status to BTRFS_RESERVE_FLUSH_LIMIT, so it won't get interrupted by signal. Since such change can be ENPSPC-prone, also shrink the amount of metadata to reserve least amount avoid deadly ENOSPC there. - btrfs_block_rsv_refill() in reserve_metadata_space() It calls with BTRFS_RESERVE_FLUSH_LIMIT, which won't get interrupted by signal. - btrfs_block_rsv_refill() in prepare_to_relocate() - btrfs_block_rsv_add() in prepare_to_relocate() - btrfs_block_rsv_refill() in relocate_block_group() - btrfs_delalloc_reserve_metadata() in relocate_file_extent_cluster() - btrfs_start_transaction() in relocate_block_group() - btrfs_start_transaction() in create_reloc_inode() Can be interrupted by fatal signal and we can handle it easily. For these call sites, just catch the -EINTR value in btrfs_balance() and count them as canceled. CC: [email protected] # 5.4+ Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent f3e3d9c commit 44d354a

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

fs/btrfs/relocation.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -1686,12 +1686,20 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
16861686
btrfs_unlock_up_safe(path, 0);
16871687
}
16881688

1689-
min_reserved = fs_info->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;
1689+
/*
1690+
* In merge_reloc_root(), we modify the upper level pointer to swap the
1691+
* tree blocks between reloc tree and subvolume tree. Thus for tree
1692+
* block COW, we COW at most from level 1 to root level for each tree.
1693+
*
1694+
* Thus the needed metadata size is at most root_level * nodesize,
1695+
* and * 2 since we have two trees to COW.
1696+
*/
1697+
min_reserved = fs_info->nodesize * btrfs_root_level(root_item) * 2;
16901698
memset(&next_key, 0, sizeof(next_key));
16911699

16921700
while (1) {
16931701
ret = btrfs_block_rsv_refill(root, rc->block_rsv, min_reserved,
1694-
BTRFS_RESERVE_FLUSH_ALL);
1702+
BTRFS_RESERVE_FLUSH_LIMIT);
16951703
if (ret) {
16961704
err = ret;
16971705
goto out;

fs/btrfs/volumes.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -4135,7 +4135,22 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
41354135
mutex_lock(&fs_info->balance_mutex);
41364136
if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req))
41374137
btrfs_info(fs_info, "balance: paused");
4138-
else if (ret == -ECANCELED && atomic_read(&fs_info->balance_cancel_req))
4138+
/*
4139+
* Balance can be canceled by:
4140+
*
4141+
* - Regular cancel request
4142+
* Then ret == -ECANCELED and balance_cancel_req > 0
4143+
*
4144+
* - Fatal signal to "btrfs" process
4145+
* Either the signal caught by wait_reserve_ticket() and callers
4146+
* got -EINTR, or caught by btrfs_should_cancel_balance() and
4147+
* got -ECANCELED.
4148+
* Either way, in this case balance_cancel_req = 0, and
4149+
* ret == -EINTR or ret == -ECANCELED.
4150+
*
4151+
* So here we only check the return value to catch canceled balance.
4152+
*/
4153+
else if (ret == -ECANCELED || ret == -EINTR)
41394154
btrfs_info(fs_info, "balance: canceled");
41404155
else
41414156
btrfs_info(fs_info, "balance: ended with status: %d", ret);

0 commit comments

Comments
 (0)