Skip to content

Commit 1bdc2d9

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: tune: add the ability to migrate the temporary csum items to regular csum items
At this stage, the csum tree should only contain the temporary csum items (CSUM_CHANGE, EXTENT_CSUM, logical), and no more old csum items. Now we can convert those temporary csum items back to regular csum items by changing their key objectids back to EXTENT_CSUM. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent dac97f8 commit 1bdc2d9

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

tune/change-csum.c

+86
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,89 @@ static int delete_old_data_csums(struct btrfs_fs_info *fs_info)
388388
return ret;
389389
}
390390

391+
static int change_csum_objectids(struct btrfs_fs_info *fs_info)
392+
{
393+
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, 0);
394+
struct btrfs_trans_handle *trans;
395+
struct btrfs_path path = { 0 };
396+
struct btrfs_key last_key;
397+
u64 super_flags;
398+
int ret = 0;
399+
400+
last_key.objectid = BTRFS_CSUM_CHANGE_OBJECTID;
401+
last_key.type = BTRFS_EXTENT_CSUM_KEY;
402+
last_key.offset = (u64)-1;
403+
404+
trans = btrfs_start_transaction(csum_root, 1);
405+
if (IS_ERR(trans)) {
406+
ret = PTR_ERR(trans);
407+
errno = -ret;
408+
error("failed to start transaction to change csum objectids: %m");
409+
return ret;
410+
}
411+
while (true) {
412+
struct btrfs_key found_key;
413+
int nr;
414+
415+
ret = btrfs_search_slot(trans, csum_root, &last_key, &path, 0, 1);
416+
if (ret < 0)
417+
goto out;
418+
assert(ret > 0);
419+
420+
nr = btrfs_header_nritems(path.nodes[0]);
421+
/* No item left (empty csum tree), exit. */
422+
if (!nr)
423+
goto out;
424+
/* No more temporary csum items, all converted, exit. */
425+
if (path.slots[0] == 0)
426+
goto out;
427+
428+
/* All csum items should be new csums. */
429+
btrfs_item_key_to_cpu(path.nodes[0], &found_key, 0);
430+
assert(found_key.objectid == BTRFS_CSUM_CHANGE_OBJECTID);
431+
432+
/*
433+
* Start changing the objectids, since EXTENT_CSUM (-10) is
434+
* larger than CSUM_CHANGE (-13), we always change from the tail.
435+
*/
436+
for (int i = nr - 1; i >= 0; i--) {
437+
btrfs_item_key_to_cpu(path.nodes[0], &found_key, i);
438+
found_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
439+
path.slots[0] = i;
440+
ret = btrfs_set_item_key_safe(csum_root, &path, &found_key);
441+
if (ret < 0) {
442+
errno = -ret;
443+
error("failed to set item key for data csum at logical %llu: %m",
444+
found_key.offset);
445+
goto out;
446+
}
447+
}
448+
btrfs_release_path(&path);
449+
}
450+
out:
451+
btrfs_release_path(&path);
452+
if (ret < 0) {
453+
btrfs_abort_transaction(trans, ret);
454+
return ret;
455+
}
456+
457+
/*
458+
* All data csum items has been changed to the new type, we can clear
459+
* the superblock flag for data csum change, and go to the metadata csum
460+
* change phase.
461+
*/
462+
super_flags = btrfs_super_flags(fs_info->super_copy);
463+
super_flags &= ~BTRFS_SUPER_FLAG_CHANGING_DATA_CSUM;
464+
super_flags |= BTRFS_SUPER_FLAG_CHANGING_META_CSUM;
465+
btrfs_set_super_flags(fs_info->super_copy, super_flags);
466+
ret = btrfs_commit_transaction(trans, csum_root);
467+
if (ret < 0) {
468+
errno = -ret;
469+
error("failed to commit transaction after changing data csum objectids: %m");
470+
}
471+
return ret;
472+
}
473+
391474
int btrfs_change_csum_type(struct btrfs_fs_info *fs_info, u16 new_csum_type)
392475
{
393476
int ret;
@@ -417,6 +500,9 @@ int btrfs_change_csum_type(struct btrfs_fs_info *fs_info, u16 new_csum_type)
417500
return ret;
418501

419502
/* Phase 3, change the new csum key objectid */
503+
ret = change_csum_objectids(fs_info);
504+
if (ret < 0)
505+
return ret;
420506

421507
/*
422508
* Phase 4, change the csums for metadata.

0 commit comments

Comments
 (0)