Patch "btrfs: fix mount failure due to past and transient device flush error" has been added to the 5.14-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    btrfs: fix mount failure due to past and transient device flush error

to the 5.14-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     btrfs-fix-mount-failure-due-to-past-and-transient-de.patch
and it can be found in the queue-5.14 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f1e0db076e807e5df11bca9cc88c60d96befad4f
Author: Filipe Manana <fdmanana@xxxxxxxx>
Date:   Wed Sep 8 19:05:44 2021 +0100

    btrfs: fix mount failure due to past and transient device flush error
    
    [ Upstream commit 6b225baababf1e3d41a4250e802cbd193e1343fb ]
    
    When we get an error flushing one device, during a super block commit, we
    record the error in the device structure, in the field 'last_flush_error'.
    This is used to later check if we should error out the super block commit,
    depending on whether the number of flush errors is greater than or equals
    to the maximum tolerated device failures for a raid profile.
    
    However if we get a transient device flush error, unmount the filesystem
    and later try to mount it, we can fail the mount because we treat that
    past error as critical and consider the device is missing. Even if it's
    very likely that the error will happen again, as it's probably due to a
    hardware related problem, there may be cases where the error might not
    happen again. One example is during testing, and a test case like the
    new generic/648 from fstests always triggers this. The test cases
    generic/019 and generic/475 also trigger this scenario, but very
    sporadically.
    
    When this happens we get an error like this:
    
      $ mount /dev/sdc /mnt
      mount: /mnt wrong fs type, bad option, bad superblock on /dev/sdc, missing codepage or helper program, or other error.
    
      $ dmesg
      (...)
      [12918.886926] BTRFS warning (device sdc): chunk 13631488 missing 1 devices, max tolerance is 0 for writable mount
      [12918.888293] BTRFS warning (device sdc): writable mount is not allowed due to too many missing devices
      [12918.890853] BTRFS error (device sdc): open_ctree failed
    
    The failure happens because when btrfs_check_rw_degradable() is called at
    mount time, or at remount from RO to RW time, is sees a non zero value in
    a device's ->last_flush_error attribute, and therefore considers that the
    device is 'missing'.
    
    Fix this by setting a device's ->last_flush_error to zero when we close a
    device, making sure the error is not seen on the next mount attempt. We
    only need to track flush errors during the current mount, so that we never
    commit a super block if such errors happened.
    
    Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
    Reviewed-by: David Sterba <dsterba@xxxxxxxx>
    Signed-off-by: David Sterba <dsterba@xxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 682416d4edef..19c780242e12 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1149,6 +1149,19 @@ static void btrfs_close_one_device(struct btrfs_device *device)
 	atomic_set(&device->dev_stats_ccnt, 0);
 	extent_io_tree_release(&device->alloc_state);
 
+	/*
+	 * Reset the flush error record. We might have a transient flush error
+	 * in this mount, and if so we aborted the current transaction and set
+	 * the fs to an error state, guaranteeing no super blocks can be further
+	 * committed. However that error might be transient and if we unmount the
+	 * filesystem and mount it again, we should allow the mount to succeed
+	 * (btrfs_check_rw_degradable() should not fail) - if after mounting the
+	 * filesystem again we still get flush errors, then we will again abort
+	 * any transaction and set the error state, guaranteeing no commits of
+	 * unsafe super blocks.
+	 */
+	device->last_flush_error = 0;
+
 	/* Verify the device is back in a pristine state  */
 	ASSERT(!test_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state));
 	ASSERT(!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state));



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux