@@ -3634,11 +3634,15 @@ static void btrfs_end_super_write(struct bio *bio)
3634
3634
"lost super block write due to IO error on %s (%d)" ,
3635
3635
btrfs_dev_name (device ),
3636
3636
blk_status_to_errno (bio -> bi_status ));
3637
- folio_set_error (fi .folio );
3638
3637
btrfs_dev_stat_inc_and_print (device ,
3639
3638
BTRFS_DEV_STAT_WRITE_ERRS );
3639
+ /* Ensure failure if the primary sb fails. */
3640
+ if (bio -> bi_opf & REQ_FUA )
3641
+ atomic_add (BTRFS_SUPER_PRIMARY_WRITE_ERROR ,
3642
+ & device -> sb_write_errors );
3643
+ else
3644
+ atomic_inc (& device -> sb_write_errors );
3640
3645
}
3641
-
3642
3646
folio_unlock (fi .folio );
3643
3647
folio_put (fi .folio );
3644
3648
}
@@ -3742,10 +3746,11 @@ static int write_dev_supers(struct btrfs_device *device,
3742
3746
struct address_space * mapping = device -> bdev -> bd_inode -> i_mapping ;
3743
3747
SHASH_DESC_ON_STACK (shash , fs_info -> csum_shash );
3744
3748
int i ;
3745
- int errors = 0 ;
3746
3749
int ret ;
3747
3750
u64 bytenr , bytenr_orig ;
3748
3751
3752
+ atomic_set (& device -> sb_write_errors , 0 );
3753
+
3749
3754
if (max_mirrors == 0 )
3750
3755
max_mirrors = BTRFS_SUPER_MIRROR_MAX ;
3751
3756
@@ -3765,7 +3770,7 @@ static int write_dev_supers(struct btrfs_device *device,
3765
3770
btrfs_err (device -> fs_info ,
3766
3771
"couldn't get super block location for mirror %d" ,
3767
3772
i );
3768
- errors ++ ;
3773
+ atomic_inc ( & device -> sb_write_errors ) ;
3769
3774
continue ;
3770
3775
}
3771
3776
if (bytenr + BTRFS_SUPER_INFO_SIZE >=
@@ -3785,14 +3790,11 @@ static int write_dev_supers(struct btrfs_device *device,
3785
3790
btrfs_err (device -> fs_info ,
3786
3791
"couldn't get super block page for bytenr %llu" ,
3787
3792
bytenr );
3788
- errors ++ ;
3793
+ atomic_inc ( & device -> sb_write_errors ) ;
3789
3794
continue ;
3790
3795
}
3791
3796
ASSERT (folio_order (folio ) == 0 );
3792
3797
3793
- /* Bump the refcount for wait_dev_supers() */
3794
- folio_get (folio );
3795
-
3796
3798
offset = offset_in_folio (folio , bytenr );
3797
3799
disk_super = folio_address (folio ) + offset ;
3798
3800
memcpy (disk_super , sb , BTRFS_SUPER_INFO_SIZE );
@@ -3820,16 +3822,17 @@ static int write_dev_supers(struct btrfs_device *device,
3820
3822
submit_bio (bio );
3821
3823
3822
3824
if (btrfs_advance_sb_log (device , i ))
3823
- errors ++ ;
3825
+ atomic_inc ( & device -> sb_write_errors ) ;
3824
3826
}
3825
- return errors < i ? 0 : -1 ;
3827
+ return atomic_read ( & device -> sb_write_errors ) < i ? 0 : -1 ;
3826
3828
}
3827
3829
3828
3830
/*
3829
3831
* Wait for write completion of superblocks done by write_dev_supers,
3830
3832
* @max_mirrors same for write and wait phases.
3831
3833
*
3832
- * Return number of errors when folio is not found or not marked up to date.
3834
+ * Return -1 if primary super block write failed or when there were no super block
3835
+ * copies written. Otherwise 0.
3833
3836
*/
3834
3837
static int wait_dev_supers (struct btrfs_device * device , int max_mirrors )
3835
3838
{
@@ -3860,30 +3863,19 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
3860
3863
3861
3864
folio = filemap_get_folio (device -> bdev -> bd_inode -> i_mapping ,
3862
3865
bytenr >> PAGE_SHIFT );
3863
- if (IS_ERR (folio )) {
3864
- errors ++ ;
3865
- if (i == 0 )
3866
- primary_failed = true;
3866
+ /* If the folio has been removed, then we know it completed. */
3867
+ if (IS_ERR (folio ))
3867
3868
continue ;
3868
- }
3869
3869
ASSERT (folio_order (folio ) == 0 );
3870
3870
3871
3871
/* Folio will be unlocked once the write completes. */
3872
3872
folio_wait_locked (folio );
3873
- if (folio_test_error (folio )) {
3874
- errors ++ ;
3875
- if (i == 0 )
3876
- primary_failed = true;
3877
- }
3878
-
3879
- /* Drop our reference */
3880
- folio_put (folio );
3881
-
3882
- /* Drop the reference from the writing run */
3883
3873
folio_put (folio );
3884
3874
}
3885
3875
3886
- /* log error, force error return */
3876
+ errors += atomic_read (& device -> sb_write_errors );
3877
+ if (errors >= BTRFS_SUPER_PRIMARY_WRITE_ERROR )
3878
+ primary_failed = true;
3887
3879
if (primary_failed ) {
3888
3880
btrfs_err (device -> fs_info , "error writing primary super block to device %llu" ,
3889
3881
device -> devid );
0 commit comments