Skip to content

Commit 7561551

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: try harder to mark RAID56 block groups read-only
Currently we allow a block group not to be marked read-only for scrub. But for RAID56 block groups if we require the block group to be read-only, then we're allowed to use cached content from scrub stripe to reduce unnecessary RAID56 reads. So this patch would: - Make btrfs_inc_block_group_ro() try harder During my tests, for cases like btrfs/061 and btrfs/064, we can hit ENOSPC from btrfs_inc_block_group_ro() calls during scrub. The reason is if we only have one single data chunk, and trying to scrub it, we won't have any space left for any newer data writes. But this check should be done by the caller, especially for scrub cases we only temporarily mark the chunk read-only. And newer data writes would always try to allocate a new data chunk when needed. - Return error for scrub if we failed to mark a RAID56 chunk read-only Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 1d6a4fc commit 7561551

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

fs/btrfs/block-group.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,10 +2818,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
28182818
}
28192819

28202820
ret = inc_block_group_ro(cache, 0);
2821-
if (!do_chunk_alloc || ret == -ETXTBSY)
2822-
goto unlock_out;
28232821
if (!ret)
28242822
goto out;
2823+
if (ret == -ETXTBSY)
2824+
goto unlock_out;
2825+
2826+
/*
2827+
* Skip chunk alloction if the bg is SYSTEM, this is to avoid system
2828+
* chunk allocation storm to exhaust the system chunk array. Otherwise
2829+
* we still want to try our best to mark the block group read-only.
2830+
*/
2831+
if (!do_chunk_alloc && ret == -ENOSPC &&
2832+
(cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
2833+
goto unlock_out;
2834+
28252835
alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
28262836
ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
28272837
if (ret < 0)

fs/btrfs/scrub.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2518,13 +2518,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
25182518

25192519
if (ret == 0) {
25202520
ro_set = 1;
2521-
} else if (ret == -ENOSPC && !sctx->is_dev_replace) {
2521+
} else if (ret == -ENOSPC && !sctx->is_dev_replace &&
2522+
!(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
25222523
/*
25232524
* btrfs_inc_block_group_ro return -ENOSPC when it
25242525
* failed in creating new chunk for metadata.
25252526
* It is not a problem for scrub, because
25262527
* metadata are always cowed, and our scrub paused
25272528
* commit_transactions.
2529+
*
2530+
* For RAID56 chunks, we have to mark them read-only
2531+
* for scrub, as later we would use our own cache
2532+
* out of RAID56 realm.
2533+
* Thus we want the RAID56 bg to be marked RO to
2534+
* prevent RMW from screwing up out cache.
25282535
*/
25292536
ro_set = 0;
25302537
} else if (ret == -ETXTBSY) {

0 commit comments

Comments
 (0)