]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsblk: fix processing of dm partition mappings
authorPeter Rajnoha <prajnoha@redhat.com>
Thu, 20 Sep 2012 11:17:13 +0000 (13:17 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 1 Oct 2012 09:58:23 +0000 (11:58 +0200)
As blkid_devno_to_wholedisk returns parent dm device for
a partition mapping, the condition used in lsblk incorrectly
checked the parent-child relationship.

In this particular case, we need to process the dm partition
mapping like any other non-partition device as dm devices always
use proper holders/slaves sysfs hierarchy instead of
/sys/block/<parent>/<name> that is used for real partitions.

Example (test1 is a partition mapping and sdb1 is a real partition):
$ lsblk
NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                8:0    0  128M  0 disk
`-test (dm-0)    253:0    0  128M  0 dm
  `-test1 (dm-1) 253:1    0  127M  0 part
sdb                8:16   0  128M  0 disk
`-sdb1             8:17   0  127M  0 disk

Before this patch (test1 skipped!):
$ lsblk -s /dev/mapper/test1
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
test (dm-0) 253:0    0  128M  0 dm
`-sda         8:0    0  128M  0 disk

$ lsblk -s /dev/sdb1
NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb1    8:17   0  127M  0 disk
`-sdb   8:16   0  128M  0 disk

With this patch (test1 processed correctly):
$ lsblk -s /dev/mapper/test1
NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
test1 (dm-1)  253:1    0  127M  0 part
`-test (dm-0) 253:0    0  128M  0 dm
  `-sda         8:0    0  128M  0 disk

$ lsblk -s /dev/sdb1
NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb1    8:17   0  127M  0 disk
`-sdb   8:16   0  128M  0 disk

misc-utils/lsblk.c

index 2410de4cf1d876e24dec70950d10fd0cc1002a8a..38eca479f643f332576277fae3fd2efc305b5992 100644 (file)
@@ -1065,52 +1065,68 @@ static int iterate_block_devices(void)
        return EXIT_SUCCESS;
 }
 
+static char *devno_to_sysfs_name(dev_t devno, char *devname, char *buf, size_t buf_size)
+{
+       char path[PATH_MAX];
+       ssize_t len;
+
+       if (!sysfs_devno_path(devno, path, sizeof(path))) {
+               warn(_("%s: failed to compose sysfs path"), devname);
+               return NULL;
+       }
+
+       len = readlink(path, buf, buf_size);
+       if (len < 0) {
+               warn(_("%s: failed to read link"), path);
+               return NULL;
+       }
+       buf[len] = '\0';
+
+       return xstrdup(strrchr(buf, '/') + 1);
+}
+
 static int process_one_device(char *devname)
 {
        struct blkdev_cxt parent = {}, cxt = {};
        struct stat st;
-       char buf[PATH_MAX + 1], *diskname = NULL;
+       char buf[PATH_MAX + 1], *name, *diskname = NULL;
        dev_t disk = 0;
+       int real_part = 0;
        int status = EXIT_FAILURE;
 
        if (stat(devname, &st) || !S_ISBLK(st.st_mode)) {
                warnx(_("%s: not a block device"), devname);
                return EXIT_FAILURE;
        }
-       if (blkid_devno_to_wholedisk(st.st_rdev, buf, sizeof(buf), &disk)) {
-               warn(_("%s: failed to get whole-disk device number"), devname);
+
+       if (!(name = devno_to_sysfs_name(st.st_rdev, devname, buf, PATH_MAX))) {
+               warn(_("%s: failed to get sysfs name"), devname);
                return EXIT_FAILURE;
        }
-       if (st.st_rdev == disk) {
+
+       if (!strncmp(name, "dm-", 3)) {
+               /* dm mapping is never a real partition! */
+               real_part = 0;
+       } else {
+               if (blkid_devno_to_wholedisk(st.st_rdev, buf, sizeof(buf), &disk)) {
+                       warn(_("%s: failed to get whole-disk device number"), devname);
+                       return EXIT_FAILURE;
+               }
+               diskname = buf;
+               real_part = st.st_rdev != disk;
+       }
+
+       if (!real_part) {
                /*
                 * Device is not a partition.
                 */
-               if (set_cxt(&cxt, NULL, NULL, buf))
+               if (set_cxt(&cxt, NULL, NULL, name))
                        goto leave;
                process_blkdev(&cxt, NULL, !lsblk->inverse, NULL);
        } else {
                /*
                 * Partition, read sysfs name of the device.
                 */
-               ssize_t len;
-               char path[PATH_MAX], *name;
-
-               if (!sysfs_devno_path(st.st_rdev, path, sizeof(path))) {
-                       warn(_("failed to compose sysfs path for %s"), devname);
-                       goto leave;
-               }
-
-               diskname = xstrdup(buf);
-               len = readlink(path, buf, PATH_MAX);
-               if (len < 0) {
-                       warn(_("%s: failed to read link"), path);
-                       goto leave;
-               }
-               buf[len] = '\0';
-
-               /* sysfs device name */
-               name = strrchr(buf, '/') + 1;
-
                if (set_cxt(&parent, NULL, NULL, diskname))
                        goto leave;
                if (set_cxt(&cxt, &parent, &parent, name))
@@ -1124,10 +1140,10 @@ static int process_one_device(char *devname)
 
        status = EXIT_SUCCESS;
 leave:
-       free(diskname);
+       free(name);
        reset_blkdev_cxt(&cxt);
 
-       if (st.st_rdev != disk)
+       if (real_part)
                reset_blkdev_cxt(&parent);
 
        return status;