Scan /dev/md and device mapper devices last
authorChris Mason <chris.mason@oracle.com>
Tue, 21 Feb 2012 20:56:10 +0000 (15:56 -0500)
committerChris Mason <chris.mason@oracle.com>
Wed, 22 Feb 2012 15:59:55 +0000 (10:59 -0500)
When we're using multipath or raid0, it is possible
that btrfs dev scan will find one of the component devices
instead of the proper virtual device the kernel creates.

We want to make sure the kernel scans the virtual devices last,
since it always remembers the last device it finds with a given fsid.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
utils.c
volumes.c

diff --git a/utils.c b/utils.c
index f0dd5270cf12e22a5ebdfa8aa86e5a8d7be9b4b9..ee7fa1b877d2a3815d349aa465fa088bace7a0ab 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -1138,7 +1138,10 @@ int btrfs_scan_block_devices(int run_ioctl)
        int i;
        char buf[1024];
        char fullpath[110];
+       int scans = 0;
+       int special;
 
+scan_again:
        proc_partitions = fopen("/proc/partitions","r");
        if (!proc_partitions) {
                fprintf(stderr, "Unable to open '/proc/partitions' for scanning\n");
@@ -1154,8 +1157,23 @@ int btrfs_scan_block_devices(int run_ioctl)
 
        strcpy(fullpath,"/dev/");
        while(fgets(buf, 1023, proc_partitions)) {
-
                i = sscanf(buf," %*d %*d %*d %99s", fullpath+5);
+
+               /*
+                * multipath and MD devices may register as a btrfs filesystem
+                * both through the original block device and through
+                * the special (/dev/mapper or /dev/mdX) entry.
+                * This scans the special entries last
+                */
+               special = strncmp(fullpath, "/dev/dm-", strlen("/dev/dm-")) == 0;
+               if (!special)
+                       special = strncmp(fullpath, "/dev/md", strlen("/dev/md")) == 0;
+
+               if (scans == 0 && special)
+                       continue;
+               if (scans > 0 && !special)
+                       continue;
+
                ret = lstat(fullpath, &st);
                if (ret < 0) {
                        fprintf(stderr, "failed to stat %s\n", fullpath);
@@ -1180,6 +1198,11 @@ int btrfs_scan_block_devices(int run_ioctl)
        }
 
        fclose(proc_partitions);
+
+       if (scans == 0) {
+               scans++;
+               goto scan_again;
+       }
        return 0;
 }
 
index 4c29cefdbe530c059699ea4e9c6ebb516ccea1ab..375713f202d7c1fd415c07091606660e9e784c73 100644 (file)
--- a/volumes.c
+++ b/volumes.c
@@ -128,7 +128,14 @@ static int device_list_add(const char *path,
                        btrfs_stack_device_bytes_used(&disk_super->dev_item);
                list_add(&device->dev_list, &fs_devices->devices);
                device->fs_devices = fs_devices;
-       }
+       } else if (!device->name || strcmp(device->name, path)) {
+               char *name = strdup(path);
+                if (!name)
+                        return -ENOMEM;
+                kfree(device->name);
+                device->name = name;
+        }
+
 
        if (found_transid > fs_devices->latest_trans) {
                fs_devices->latest_devid = devid;