btrfs: keep device list sorted
authorAnand Jain <anand.jain@oracle.com>
Mon, 22 Jan 2018 22:49:36 +0000 (14:49 -0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 26 Mar 2018 13:09:36 +0000 (15:09 +0200)
By maintaining the device list sorted lets us reproduce the problems
related to missing chunk in the degraded mode much more consistent. So
fix this by sorting the devices by devid within the kernel. So that we
know which device is assigned to the struct fs_info::latest_bdev when
all the devices are having and same SB generation.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index 77c7a0c181908fd4b59527c55973f8ac942a624b..abc6555105bb8758889fc8fda63574e5b4fe0d71 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/raid/pq.h>
 #include <linux/semaphore.h>
 #include <linux/uuid.h>
+#include <linux/list_sort.h>
 #include <asm/div64.h>
 #include "ctree.h"
 #include "extent_map.h"
@@ -1103,6 +1104,20 @@ out:
        return ret;
 }
 
+static int devid_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct btrfs_device *dev1, *dev2;
+
+       dev1 = list_entry(a, struct btrfs_device, dev_list);
+       dev2 = list_entry(b, struct btrfs_device, dev_list);
+
+       if (dev1->devid < dev2->devid)
+               return -1;
+       else if (dev1->devid > dev2->devid)
+               return 1;
+       return 0;
+}
+
 int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                       fmode_t flags, void *holder)
 {
@@ -1113,6 +1128,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                fs_devices->opened++;
                ret = 0;
        } else {
+               list_sort(NULL, &fs_devices->devices, devid_cmp);
                ret = __btrfs_open_devices(fs_devices, flags, holder);
        }
        mutex_unlock(&uuid_mutex);