@@ -388,6 +388,89 @@ static int delete_old_data_csums(struct btrfs_fs_info *fs_info)
388
388
return ret ;
389
389
}
390
390
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
+
391
474
int btrfs_change_csum_type (struct btrfs_fs_info * fs_info , u16 new_csum_type )
392
475
{
393
476
int ret ;
@@ -417,6 +500,9 @@ int btrfs_change_csum_type(struct btrfs_fs_info *fs_info, u16 new_csum_type)
417
500
return ret ;
418
501
419
502
/* Phase 3, change the new csum key objectid */
503
+ ret = change_csum_objectids (fs_info );
504
+ if (ret < 0 )
505
+ return ret ;
420
506
421
507
/*
422
508
* Phase 4, change the csums for metadata.
0 commit comments