@@ -539,13 +539,12 @@ u64 bch2_recovery_passes_from_stable(u64 v)
539539 return ret ;
540540}
541541
542- static void check_version_upgrade (struct bch_fs * c )
542+ static bool check_version_upgrade (struct bch_fs * c )
543543{
544544 unsigned latest_compatible = bch2_latest_compatible_version (c -> sb .version );
545545 unsigned latest_version = bcachefs_metadata_version_current ;
546546 unsigned old_version = c -> sb .version_upgrade_complete ?: c -> sb .version ;
547547 unsigned new_version = 0 ;
548- u64 recovery_passes ;
549548
550549 if (old_version < bcachefs_metadata_required_upgrade_below ) {
551550 if (c -> opts .version_upgrade == BCH_VERSION_UPGRADE_incompatible ||
@@ -589,7 +588,7 @@ static void check_version_upgrade(struct bch_fs *c)
589588 bch2_version_to_text (& buf , new_version );
590589 prt_newline (& buf );
591590
592- recovery_passes = bch2_upgrade_recovery_passes (c , old_version , new_version );
591+ u64 recovery_passes = bch2_upgrade_recovery_passes (c , old_version , new_version );
593592 if (recovery_passes ) {
594593 if ((recovery_passes & RECOVERY_PASS_ALL_FSCK ) == RECOVERY_PASS_ALL_FSCK )
595594 prt_str (& buf , "fsck required" );
@@ -604,12 +603,13 @@ static void check_version_upgrade(struct bch_fs *c)
604603
605604 bch_info (c , "%s" , buf .buf );
606605
607- mutex_lock (& c -> sb_lock );
608606 bch2_sb_upgrade (c , new_version );
609- mutex_unlock (& c -> sb_lock );
610607
611608 printbuf_exit (& buf );
609+ return true;
612610 }
611+
612+ return false;
613613}
614614
615615u64 bch2_fsck_recovery_passes (void )
@@ -684,7 +684,6 @@ int bch2_fs_recovery(struct bch_fs *c)
684684 struct bch_sb_field_clean * clean = NULL ;
685685 struct jset * last_journal_entry = NULL ;
686686 u64 last_seq = 0 , blacklist_seq , journal_seq ;
687- bool write_sb = false;
688687 int ret = 0 ;
689688
690689 if (c -> sb .clean ) {
@@ -712,15 +711,52 @@ int bch2_fs_recovery(struct bch_fs *c)
712711 goto err ;
713712 }
714713
715- if (c -> opts .fsck || !(c -> opts .nochanges && c -> opts .norecovery ))
716- check_version_upgrade (c );
717-
718714 if (c -> opts .fsck && c -> opts .norecovery ) {
719715 bch_err (c , "cannot select both norecovery and fsck" );
720716 ret = - EINVAL ;
721717 goto err ;
722718 }
723719
720+ if (!(c -> opts .nochanges && c -> opts .norecovery )) {
721+ mutex_lock (& c -> sb_lock );
722+ bool write_sb = false;
723+
724+ struct bch_sb_field_ext * ext =
725+ bch2_sb_field_get_minsize (& c -> disk_sb , ext , sizeof (* ext ) / sizeof (u64 ));
726+ if (!ext ) {
727+ ret = - BCH_ERR_ENOSPC_sb ;
728+ mutex_unlock (& c -> sb_lock );
729+ goto err ;
730+ }
731+
732+ if (BCH_SB_HAS_TOPOLOGY_ERRORS (c -> disk_sb .sb )) {
733+ ext -> recovery_passes_required [0 ] |=
734+ cpu_to_le64 (bch2_recovery_passes_to_stable (BIT_ULL (BCH_RECOVERY_PASS_check_topology )));
735+ write_sb = true;
736+ }
737+
738+ u64 sb_passes = bch2_recovery_passes_from_stable (le64_to_cpu (ext -> recovery_passes_required [0 ]));
739+ if (sb_passes ) {
740+ struct printbuf buf = PRINTBUF ;
741+ prt_str (& buf , "superblock requires following recovery passes to be run:\n " );
742+ prt_bitflags (& buf , bch2_recovery_passes , sb_passes );
743+ bch_info (c , "%s" , buf .buf );
744+ printbuf_exit (& buf );
745+ }
746+
747+ if (check_version_upgrade (c ))
748+ write_sb = true;
749+
750+ if (write_sb )
751+ bch2_write_super (c );
752+
753+ c -> recovery_passes_explicit |= bch2_recovery_passes_from_stable (le64_to_cpu (ext -> recovery_passes_required [0 ]));
754+ mutex_unlock (& c -> sb_lock );
755+ }
756+
757+ if (c -> opts .fsck && IS_ENABLED (CONFIG_BCACHEFS_DEBUG ))
758+ c -> recovery_passes_explicit |= BIT_ULL (BCH_RECOVERY_PASS_check_topology );
759+
724760 ret = bch2_blacklist_table_initialize (c );
725761 if (ret ) {
726762 bch_err (c , "error initializing blacklist table" );
@@ -857,11 +893,6 @@ int bch2_fs_recovery(struct bch_fs *c)
857893 if (ret )
858894 goto err ;
859895
860- if (c -> opts .fsck &&
861- (IS_ENABLED (CONFIG_BCACHEFS_DEBUG ) ||
862- BCH_SB_HAS_TOPOLOGY_ERRORS (c -> disk_sb .sb )))
863- c -> recovery_passes_explicit |= BIT_ULL (BCH_RECOVERY_PASS_check_topology );
864-
865896 ret = bch2_run_recovery_passes (c );
866897 if (ret )
867898 goto err ;
@@ -898,16 +929,30 @@ int bch2_fs_recovery(struct bch_fs *c)
898929 }
899930
900931 mutex_lock (& c -> sb_lock );
932+ bool write_sb = false;
933+
901934 if (BCH_SB_VERSION_UPGRADE_COMPLETE (c -> disk_sb .sb ) != le16_to_cpu (c -> disk_sb .sb -> version )) {
902935 SET_BCH_SB_VERSION_UPGRADE_COMPLETE (c -> disk_sb .sb , le16_to_cpu (c -> disk_sb .sb -> version ));
903936 write_sb = true;
904937 }
905938
906- if (!test_bit (BCH_FS_ERROR , & c -> flags )) {
939+ if (!test_bit (BCH_FS_ERROR , & c -> flags ) &&
940+ !(c -> disk_sb .sb -> compat [0 ] & cpu_to_le64 (1ULL << BCH_COMPAT_alloc_info ))) {
907941 c -> disk_sb .sb -> compat [0 ] |= cpu_to_le64 (1ULL << BCH_COMPAT_alloc_info );
908942 write_sb = true;
909943 }
910944
945+ if (!test_bit (BCH_FS_ERROR , & c -> flags )) {
946+ struct bch_sb_field_ext * ext = bch2_sb_field_get (c -> disk_sb .sb , ext );
947+ if (ext &&
948+ (!bch2_is_zero (ext -> recovery_passes_required , sizeof (ext -> recovery_passes_required )) ||
949+ !bch2_is_zero (ext -> errors_silent , sizeof (ext -> errors_silent )))) {
950+ memset (ext -> recovery_passes_required , 0 , sizeof (ext -> recovery_passes_required ));
951+ memset (ext -> errors_silent , 0 , sizeof (ext -> errors_silent ));
952+ write_sb = true;
953+ }
954+ }
955+
911956 if (c -> opts .fsck &&
912957 !test_bit (BCH_FS_ERROR , & c -> flags ) &&
913958 !test_bit (BCH_FS_ERRORS_NOT_FIXED , & c -> flags )) {
0 commit comments