btrfs-progs: tune: add the ability to delete old data csums

The new helper function, delete_old_data_csums(), would delete the old
data csums while keep the new one untouched.

Since the new data csums have a key objectid (-13) smaller than the
old data csums (-10), we can safely delete from the tail of the btree.

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-18 10:10:43 +08:00 committed by David Sterba
parent 08a3bd7694
commit 4cf02fbc84

View File

@ -326,6 +326,68 @@ out:
return ret;
}
static int delete_old_data_csums(struct btrfs_fs_info *fs_info)
{
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, 0);
struct btrfs_trans_handle *trans;
struct btrfs_path path = { 0 };
struct btrfs_key last_key;
int ret;
last_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
last_key.type = BTRFS_EXTENT_CSUM_KEY;
last_key.offset = (u64)-1;
trans = btrfs_start_transaction(csum_root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
error("failed to start transaction to delete old data csums: %m");
return ret;
}
while (true) {
int start_slot;
int nr;
ret = btrfs_search_slot(trans, csum_root, &last_key, &path, -1, 1);
nr = btrfs_header_nritems(path.nodes[0]);
/* No item left (empty csum tree), exit. */
if (!nr)
break;
for (start_slot = 0; start_slot < nr; start_slot++) {
struct btrfs_key found_key;
btrfs_item_key_to_cpu(path.nodes[0], &found_key, start_slot);
/* Break from the for loop, we found the first old csum. */
if (found_key.objectid == BTRFS_EXTENT_CSUM_OBJECTID)
break;
}
/* No more old csum item detected, exit. */
if (start_slot == nr)
break;
/* Delete items starting from @start_slot to the end. */
ret = btrfs_del_items(trans, csum_root, &path, start_slot,
nr - start_slot);
if (ret < 0) {
errno = -ret;
error("failed to delete items: %m");
break;
}
btrfs_release_path(&path);
}
btrfs_release_path(&path);
if (ret < 0)
btrfs_abort_transaction(trans, ret);
ret = btrfs_commit_transaction(trans, csum_root);
if (ret < 0) {
errno = -ret;
error("failed to commit transaction after deleting the old data csums: %m");
}
return ret;
}
int btrfs_change_csum_type(struct btrfs_fs_info *fs_info, u16 new_csum_type)
{
int ret;
@ -350,6 +412,9 @@ int btrfs_change_csum_type(struct btrfs_fs_info *fs_info, u16 new_csum_type)
}
/* Phase 2, delete the old data csums. */
ret = delete_old_data_csums(fs_info);
if (ret < 0)
return ret;
/* Phase 3, change the new csum key objectid */