btrfs: scrub: try harder to mark RAID56 block groups read-only
[ Upstream commit 7561551e7b
]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
9df872ec4a
Коммит
39ea949526
|
@ -2576,10 +2576,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inc_block_group_ro(cache, 0);
|
ret = inc_block_group_ro(cache, 0);
|
||||||
if (!do_chunk_alloc || ret == -ETXTBSY)
|
|
||||||
goto unlock_out;
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
if (ret == -ETXTBSY)
|
||||||
|
goto unlock_out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip chunk alloction if the bg is SYSTEM, this is to avoid system
|
||||||
|
* chunk allocation storm to exhaust the system chunk array. Otherwise
|
||||||
|
* we still want to try our best to mark the block group read-only.
|
||||||
|
*/
|
||||||
|
if (!do_chunk_alloc && ret == -ENOSPC &&
|
||||||
|
(cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
|
||||||
|
goto unlock_out;
|
||||||
|
|
||||||
alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
|
alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
|
||||||
ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
|
ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -3812,13 +3812,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ro_set = 1;
|
ro_set = 1;
|
||||||
} else if (ret == -ENOSPC && !sctx->is_dev_replace) {
|
} else if (ret == -ENOSPC && !sctx->is_dev_replace &&
|
||||||
|
!(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
|
||||||
/*
|
/*
|
||||||
* btrfs_inc_block_group_ro return -ENOSPC when it
|
* btrfs_inc_block_group_ro return -ENOSPC when it
|
||||||
* failed in creating new chunk for metadata.
|
* failed in creating new chunk for metadata.
|
||||||
* It is not a problem for scrub, because
|
* It is not a problem for scrub, because
|
||||||
* metadata are always cowed, and our scrub paused
|
* metadata are always cowed, and our scrub paused
|
||||||
* commit_transactions.
|
* commit_transactions.
|
||||||
|
*
|
||||||
|
* For RAID56 chunks, we have to mark them read-only
|
||||||
|
* for scrub, as later we would use our own cache
|
||||||
|
* out of RAID56 realm.
|
||||||
|
* Thus we want the RAID56 bg to be marked RO to
|
||||||
|
* prevent RMW from screwing up out cache.
|
||||||
*/
|
*/
|
||||||
ro_set = 0;
|
ro_set = 0;
|
||||||
} else if (ret == -ETXTBSY) {
|
} else if (ret == -ETXTBSY) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче