@@ -885,8 +885,26 @@ static int resume_data_csum_change(struct btrfs_fs_info *fs_info,
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);
@@ -899,6 +917,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;
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> --- tune/change-csum.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)