1 /*
2 * device-mapper (dm) topology
3 * -- this is fallback for old systems where the topology information is not
4 * exported by sysfs
5 *
6 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
7 *
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 *
11 */
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include "topology.h"
23
24 static int is_dm_device(dev_t devno)
25 {
26 return blkid_driver_has_major("device-mapper", major(devno));
27 }
28
29 static int probe_dm_tp(blkid_probe pr,
30 const struct blkid_idmag *mag __attribute__((__unused__)))
31 {
32 const char * const paths[] = {
33 "/usr/local/sbin/dmsetup",
34 "/usr/sbin/dmsetup",
35 "/sbin/dmsetup"
36 };
37 int dmpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
38 const char *cmd = NULL;
39 FILE *stream = NULL;
40 long long offset = 0, size = 0;
41 size_t i;
42 dev_t devno = blkid_probe_get_devno(pr);
43
44 if (!devno)
45 goto nothing; /* probably not a block device */
46 if (!is_dm_device(devno))
47 goto nothing;
48
49 for (i = 0; i < ARRAY_SIZE(paths); i++) {
50 struct stat sb;
51 if (stat(paths[i], &sb) == 0) {
52 cmd = paths[i];
53 break;
54 }
55 }
56
57 if (!cmd)
58 goto nothing;
59 if (pipe(dmpipe) < 0) {
60 DBG(LOWPROBE, ul_debug("Failed to open pipe: errno=%d", errno));
61 goto nothing;
62 }
63
64 switch (fork()) {
65 case 0:
66 {
67 const char *dmargv[7];
68 char maj[16], min[16];
69
70 /* Plumbing */
71 close(dmpipe[0]);
72
73 if (dmpipe[1] != STDOUT_FILENO)
74 dup2(dmpipe[1], STDOUT_FILENO);
75
76 if (drop_permissions() != 0)
77 exit(1);
78
79 snprintf(maj, sizeof(maj), "%d", major(devno));
80 snprintf(min, sizeof(min), "%d", minor(devno));
81
82 dmargv[0] = cmd;
83 dmargv[1] = "table";
84 dmargv[2] = "-j";
85 dmargv[3] = maj;
86 dmargv[4] = "-m";
87 dmargv[5] = min;
88 dmargv[6] = NULL;
89
90 execv(dmargv[0], (char * const *) dmargv);
91
92 DBG(LOWPROBE, ul_debug("Failed to execute %s: errno=%d", cmd, errno));
93 exit(1);
94 }
95 case -1:
96 DBG(LOWPROBE, ul_debug("Failed to forking: errno=%d", errno));
97 goto nothing;
98 default:
99 break;
100 }
101
102 stream = fdopen(dmpipe[0], "r" UL_CLOEXECSTR);
103 if (!stream)
104 goto nothing;
105
106 if (dmpipe[1] != -1) {
107 close(dmpipe[1]);
108 }
109
110 if (fscanf(stream, "%lld %lld striped %d %d ",
111 &offset, &size, &stripes, &stripesize) != 0)
112 goto nothing;
113
114 blkid_topology_set_minimum_io_size(pr, stripesize << 9);
115 blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 9);
116
117 fclose(stream);
118 return 0;
119
120 nothing:
121 if (stream)
122 fclose(stream);
123 else if (dmpipe[0] != -1)
124 close(dmpipe[0]);
125 return 1;
126 }
127
128 const struct blkid_idinfo dm_tp_idinfo =
129 {
130 .name = "dm",
131 .probefunc = probe_dm_tp,
132 .magics = BLKID_NONE_MAGIC
133 };
134