btrfs: factor btrfs_check_rw_degradable() to check given device
authorAnand Jain <Anand.Jain@oracle.com>
Mon, 18 Dec 2017 09:08:59 +0000 (17:08 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 22 Jan 2018 15:08:20 +0000 (16:08 +0100)
Update btrfs_check_rw_degradable() to check against the given device if
its lost.

We can use this function to know if the volume is going to be in
degraded mode OR failed state, when the given device fails.  Which is
needed when we are handling the device failed state.

A preparatory patch does not affect the flow as such.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
[ enhance comment ]
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index 41d151b9ffd236c88e38b0b9781fc7e61e0f871e..73ab44159d820538cb98bc4f050a34e31ed64a19 100644 (file)
@@ -2866,7 +2866,7 @@ retry_root_backup:
                goto fail_sysfs;
        }
 
-       if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info)) {
+       if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) {
                btrfs_warn(fs_info,
                "writeable mount is not allowed due to too many missing devices");
                goto fail_sysfs;
@@ -3369,7 +3369,7 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
 
 static int check_barrier_error(struct btrfs_fs_info *fs_info)
 {
-       if (!btrfs_check_rw_degradable(fs_info))
+       if (!btrfs_check_rw_degradable(fs_info, NULL))
                return -EIO;
        return 0;
 }
index f40352843c0bb09fd62f78fc78576b2005ac44cb..8af7590a56380cae9552193e55566ffb509696e5 100644 (file)
@@ -1844,7 +1844,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        goto restore;
                }
 
-               if (!btrfs_check_rw_degradable(fs_info)) {
+               if (!btrfs_check_rw_degradable(fs_info, NULL)) {
                        btrfs_warn(fs_info,
                                "too many missing devices, writeable remount is not allowed");
                        ret = -EACCES;
index 9a04245003ab837de9cc0312918e778ffb27f2dd..f85991a2585cf1c55601101cdebc9fbfba7cee58 100644 (file)
@@ -6851,10 +6851,13 @@ out_short_read:
 /*
  * Check if all chunks in the fs are OK for read-write degraded mount
  *
+ * If the @failing_dev is specified, it's accounted as missing.
+ *
  * Return true if all chunks meet the minimal RW mount requirements.
  * Return false if any chunk doesn't meet the minimal RW mount requirements.
  */
-bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info)
+bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info,
+                                       struct btrfs_device *failing_dev)
 {
        struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        struct extent_map *em;
@@ -6886,9 +6889,12 @@ bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info)
                            test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) ||
                            dev->last_flush_error)
                                missing++;
+                       else if (failing_dev && failing_dev == dev)
+                               missing++;
                }
                if (missing > max_tolerated) {
-                       btrfs_warn(fs_info,
+                       if (!failing_dev)
+                               btrfs_warn(fs_info,
        "chunk %llu missing %d devices, max tolerance is %d for writeable mount",
                                   em->start, missing, max_tolerated);
                        free_extent_map(em);
index 3e3ae44b6ccc6ef31056c5078619e6592c64cb55..a339bcf72febc262896b1b52151c82c2f5c110ab 100644 (file)
@@ -554,7 +554,7 @@ void btrfs_update_commit_device_bytes_used(struct btrfs_fs_info *fs_info,
 struct list_head *btrfs_get_fs_uuids(void);
 void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info);
 void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info);
-
-bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info);
+bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info,
+                                       struct btrfs_device *failing_dev);
 
 #endif