]> err.no Git - util-linux/commitdiff
libblkid: add LVM topology support (for old kernels)
authorKarel Zak <kzak@redhat.com>
Wed, 23 Sep 2009 19:27:01 +0000 (21:27 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 23 Sep 2009 19:27:01 +0000 (21:27 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/topology/Makefile.am
shlibs/blkid/src/topology/lvm.c [new file with mode: 0644]
shlibs/blkid/src/topology/topology.c
shlibs/blkid/src/topology/topology.h

index ffaf58dcc6714fa61593fe27c2b21b26e78203d0..05a8ac9f249192a614329579916f5911208fb629 100644 (file)
@@ -9,4 +9,5 @@ libblkid_topology_la_SOURCES =  topology.c \
                                sysfs.c \
                                md.c \
                                dm.c \
-                               evms.c
+                               evms.c \
+                               lvm.c
diff --git a/shlibs/blkid/src/topology/lvm.c b/shlibs/blkid/src/topology/lvm.c
new file mode 100644 (file)
index 0000000..0ea984a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * lvm topology
+ * -- this is fallback for old systems where the toplogy information are not
+ *    exported by sysfs
+ *
+ * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "topology.h"
+
+#ifndef LVM_BLK_MAJOR
+# define LVM_BLK_MAJOR     58
+#endif
+
+static int is_lvm_device(dev_t devno)
+{
+       if (major(devno) == LVM_BLK_MAJOR)
+               return 1;
+       return blkid_driver_has_major("lvm", major(devno));
+}
+
+static int probe_lvm_tp(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       const char *paths[] = {
+               "/usr/local/sbin/lvdisplay",
+               "/usr/sbin/lvdisplay",
+               "/sbin/lvdisplay"
+       };
+       int i, lvpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
+       FILE *stream = NULL;
+       char *cmd = NULL, *devname = NULL, buf[1024];
+       dev_t devno = blkid_probe_get_devno(pr);
+
+       if (!devno)
+               goto nothing;           /* probably not a block device */
+       if (!is_lvm_device(devno))
+               goto nothing;
+
+       for (i = 0; i < ARRAY_SIZE(paths); i++) {
+               struct stat sb;
+               if (stat(paths[i], &sb) == 0) {
+                       cmd = (char *) paths[i];
+                       break;
+               }
+       }
+
+       if (!cmd)
+               goto nothing;
+
+       devname = blkid_devno_to_devname(devno);
+       if (!devname)
+               goto nothing;
+
+       if (pipe(lvpipe) < 0) {
+               DBG(DEBUG_LOWPROBE,
+                       printf("Failed to open pipe: errno=%d", errno));
+               goto nothing;
+       }
+
+       switch (fork()) {
+       case 0:
+       {
+               char *lvargv[3];
+
+               /* Plumbing */
+               close(lvpipe[0]);
+
+               if (lvpipe[1] != STDOUT_FILENO)
+                       dup2(lvpipe[1], STDOUT_FILENO);
+
+               /* The libblkid library could linked with setuid programs */
+               if (setgid(getgid()) < 0)
+                        exit(1);
+               if (setuid(getuid()) < 0)
+                        exit(1);
+
+               lvargv[0] = cmd;
+               lvargv[1] = devname;
+               lvargv[2] = NULL;
+
+               execv(lvargv[0], lvargv);
+
+               DBG(DEBUG_LOWPROBE,
+                       printf("Failed to execute %s: errno=%d", cmd, errno));
+               exit(1);
+       }
+       case -1:
+               DBG(DEBUG_LOWPROBE,
+                       printf("Failed to forking: errno=%d", errno));
+               goto nothing;
+       default:
+               break;
+       }
+
+       stream = fdopen(lvpipe[0], "r");
+       if (!stream)
+               goto nothing;
+
+       while (fgets(buf, sizeof(buf), stream) != NULL) {
+               if (!strncmp(buf, "Stripes", 7))
+                       sscanf(buf, "Stripes %d", &stripes);
+
+               if (!strncmp(buf, "Stripe size", 11))
+                       sscanf(buf, "Stripe size (KByte) %d", &stripesize);
+       }
+
+       if (!stripes)
+               goto nothing;
+
+       blkid_topology_set_minimum_io_size(pr, stripesize << 10);
+       blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
+
+       free(devname);
+       fclose(stream);
+       close(lvpipe[1]);
+       return 0;
+
+nothing:
+       free(devname);
+       if (stream)
+               fclose(stream);
+       else if (lvpipe[0] != -1)
+               close(lvpipe[0]);
+       if (lvpipe[1] != -1)
+               close(lvpipe[1]);
+       return 1;
+}
+
+const struct blkid_idinfo lvm_tp_idinfo =
+{
+       .name           = "lvm",
+       .probefunc      = probe_lvm_tp,
+       .magics         = BLKID_NONE_MAGIC
+};
+
index ab2ecd0d84dd42f2e1b97db5e62408718fc18a0f..f4cd3219187124a8ec562f5ee4819352381f5498 100644 (file)
@@ -62,6 +62,7 @@ static const struct blkid_idinfo *idinfos[] =
        &sysfs_tp_idinfo,
        &md_tp_idinfo,
        &dm_tp_idinfo,
+       &lvm_tp_idinfo,
        &evms_tp_idinfo
 };
 
index 48d3f26f13da29fce7279c90dd7251e9afbd30d3..98321394e8947b9455ac2c27c972a535b629e06f 100644 (file)
@@ -14,6 +14,7 @@ extern const struct blkid_idinfo sysfs_tp_idinfo;
 extern const struct blkid_idinfo md_tp_idinfo;
 extern const struct blkid_idinfo dm_tp_idinfo;
 extern const struct blkid_idinfo evms_tp_idinfo;
+extern const struct blkid_idinfo lvm_tp_idinfo;
 
 #endif /* BLKID_TOPOLOGY_H */