btrfs-progs: tune: implement resume support for data csum objectid change

When the csum conversion is interrupted when changing data csum
objectid, we should just resume the objectid conversion.

This situation can be detected by comparing the old and new csum items.
They should both exist but doesn't intersect (interrupted halfway), or
only new csum items exist (interrupted after we have deleted old csums).

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2023-05-24 15:41:29 +08:00 committed by David Sterba
parent 1aa4a9c609
commit 03b4952971
1 changed files with 21 additions and 2 deletions

View File

@ -884,8 +884,26 @@ static int resume_data_csum_change(struct btrfs_fs_info *fs_info, u16 new_csum_t
new_csum_last >= old_csum_last)
goto delete_old;
/* Other cases are not yet supported. */
return -EOPNOTSUPP;
/*
* Both csums exist but not covering each other, or only new csum exists.
*
* This means we have already deleted all the old csums, is going to or
* have already started objectid change.
*/
if ((old_csum_found && new_csum_found && old_csum_last <= new_csum_first) &&
(!old_csum_found && new_csum_found))
goto change;
/* The remaining cases should not be possible. */
error("unexpected resume condition:");
error("old csum found=%d start=%llu last=%llu new csum found=%d start=%llu last=%llu",
old_csum_found,
old_csum_found ? old_csum_first : 0,
old_csum_found ? old_csum_last : 0,
new_csum_found,
new_csum_found ? new_csum_first : 0,
new_csum_found ? new_csum_last : 0);
return -EUCLEAN;
new_data_csums:
ret = generate_new_data_csums_range(fs_info, resume_start, new_csum_type);
@ -898,6 +916,7 @@ delete_old:
ret = delete_old_data_csums(fs_info);
if (ret < 0)
return ret;
change:
ret = change_csum_objectids(fs_info);
if (ret < 0)
return ret;