--- /dev/null
+/*
+ * device-mapper (dm) 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"
+
+
+static int is_dm_device(dev_t devno)
+{
+ if (blkid_driver_has_major("device-mapper", major(devno)))
+ return 1;
+ return 0;
+}
+
+static int probe_dm_tp(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ const char *paths[] = {
+ "/usr/local/sbin/dmsetup",
+ "/usr/sbin/dmsetup",
+ "/sbin/dmsetup"
+ };
+ int i, dmpipe[] = { -1, -1 }, stripes, stripesize;
+ char *cmd = NULL;
+ FILE *stream;
+ long long offset, size;
+ dev_t devno = blkid_probe_get_devno(pr);
+
+ if (!devno)
+ goto nothing; /* probably not a block device */
+ if (!is_dm_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;
+ if (pipe(dmpipe) < 0) {
+ DBG(DEBUG_LOWPROBE,
+ printf("Failed to open pipe: errno=%d", errno));
+ goto nothing;
+ }
+
+ switch (fork()) {
+ case 0:
+ {
+ char *dmargv[7], maj[16], min[16];
+
+ /* Plumbing */
+ close(dmpipe[0]);
+
+ if (dmpipe[1] != STDOUT_FILENO)
+ dup2(dmpipe[1], STDOUT_FILENO);
+
+ /* The libblkid library could linked with setuid programs */
+ if (setgid(getgid()) < 0)
+ exit(1);
+ if (setuid(getuid()) < 0)
+ exit(1);
+
+ snprintf(maj, sizeof(maj), "%d", major(devno));
+ snprintf(min, sizeof(min), "%d", minor(devno));
+
+ dmargv[0] = cmd;
+ dmargv[1] = "table";
+ dmargv[2] = "-j";
+ dmargv[3] = maj;
+ dmargv[4] = "-m";
+ dmargv[5] = min;
+ dmargv[6] = NULL;
+
+ execv(dmargv[0], dmargv);
+
+ 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;
+ }
+
+ close(dmpipe[1]);
+ dmpipe[1] = -1;
+
+ stream = fdopen(dmpipe[0], "r");
+ if (!stream)
+ goto nothing;
+
+ i = fscanf(stream, "%lld %lld striped %d %d ",
+ &offset, &size, &stripes, &stripesize);
+ fclose(stream);
+ dmpipe[0] = -1;
+
+ if (i != 4)
+ goto nothing;
+
+ blkid_topology_set_minimum_io_size(pr, stripesize << 9);
+ blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 9);
+
+ return 0;
+
+nothing:
+ if (dmpipe[0] != -1)
+ close(dmpipe[0]);
+ if (dmpipe[1] != -1)
+ close(dmpipe[1]);
+ return 1;
+}
+
+const struct blkid_idinfo dm_tp_idinfo =
+{
+ .name = "dm",
+ .probefunc = probe_dm_tp,
+ .magics = BLKID_NONE_MAGIC
+};
+