Skip to content

Commit 54df8b8

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: always update btrfs_scrub_progress::last_physical
[BUG] When a scrub failed immediately without any byte scrubbed, the returned btrfs_scrub_progress::last_physical will always be 0, even if there is a non-zero @start passed into btrfs_scrub_dev() for resume cases. This will reset the progress and make later scrub resume start from the beginning. [CAUSE] The function btrfs_scrub_dev() accepts a @progress parameter to copy its updated progress to the caller, there are cases where we either don't touch progress::last_physical at all or copy 0 into last_physical: - last_physical not updated at all If some error happened before scrubbing any super block or chunk, we will not copy the progress, leaving the @last_physical untouched. E.g. failed to allocate @SCTX, scrubbing a missing device or even there is already a running scrub and so on. All those cases won't touch @progress at all, resulting the last_physical untouched and will be left as 0 for most cases. - Error out before scrubbing any bytes In those case we allocated @SCTX, and sctx->stat.last_physical is all zero (initialized by kvzalloc()). Unfortunately some critical errors happened during scrub_enumerate_chunks() or scrub_supers() before any stripe is really scrubbed. In that case although we will copy sctx->stat back to @progress, since no byte is really scrubbed, last_physical will be overwritten to 0. [FIX] Make sure the parameter @progress always has its @last_physical member updated to @start parameter inside btrfs_scrub_dev(). At the very beginning of the function, set @progress->last_physical to @start, so that even if we error out without doing progress copying, last_physical is still at @start. Then after we got @SCTX allocated, set sctx->stat.last_physical to @start, this will make sure even if we didn't get any byte scrubbed, at the progress copying stage the @last_physical is not left as zero. This should resolve the resume progress reset problem. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 7a832b8 commit 54df8b8

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

fs/btrfs/scrub.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,6 +3104,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
31043104
unsigned int nofs_flag;
31053105
bool need_commit = false;
31063106

3107+
/* Set the basic fallback @last_physical before we got a sctx. */
3108+
if (progress)
3109+
progress->last_physical = start;
3110+
31073111
if (btrfs_fs_closing(fs_info))
31083112
return -EAGAIN;
31093113

@@ -3122,6 +3126,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
31223126
sctx = scrub_setup_ctx(fs_info, is_dev_replace);
31233127
if (IS_ERR(sctx))
31243128
return PTR_ERR(sctx);
3129+
sctx->stat.last_physical = start;
31253130

31263131
ret = scrub_workers_get(fs_info);
31273132
if (ret)

0 commit comments

Comments
 (0)