blob: 20a66b4eafac7827b4396660aaf697551829df3c [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
2 * lvm 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>
Ethan Yonkerfefe5912017-09-30 22:22:13 -050019#include <sys/sysmacros.h>
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050020#include <sys/types.h>
21#include <unistd.h>
22
23#include "topology.h"
24
25#ifndef LVM_BLK_MAJOR
26# define LVM_BLK_MAJOR 58
27#endif
28
29static int is_lvm_device(dev_t devno)
30{
31 if (major(devno) == LVM_BLK_MAJOR)
32 return 1;
33 return blkid_driver_has_major("lvm", major(devno));
34}
35
36static int probe_lvm_tp(blkid_probe pr,
37 const struct blkid_idmag *mag __attribute__((__unused__)))
38{
39 const char *paths[] = {
40 "/usr/local/sbin/lvdisplay",
41 "/usr/sbin/lvdisplay",
42 "/sbin/lvdisplay"
43 };
44 int lvpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
45 FILE *stream = NULL;
46 char *cmd = NULL, *devname = NULL, buf[1024];
47 size_t i;
48 dev_t devno = blkid_probe_get_devno(pr);
49
50 if (!devno)
51 goto nothing; /* probably not a block device */
52 if (!is_lvm_device(devno))
53 goto nothing;
54
55 for (i = 0; i < ARRAY_SIZE(paths); i++) {
56 struct stat sb;
57 if (stat(paths[i], &sb) == 0) {
58 cmd = (char *) paths[i];
59 break;
60 }
61 }
62
63 if (!cmd)
64 goto nothing;
65
66 devname = blkid_devno_to_devname(devno);
67 if (!devname)
68 goto nothing;
69
70 if (pipe(lvpipe) < 0) {
bigbiff7b4c7a62015-01-01 19:44:14 -050071 DBG(LOWPROBE, ul_debug("Failed to open pipe: errno=%d", errno));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050072 goto nothing;
73 }
74
75 switch (fork()) {
76 case 0:
77 {
78 char *lvargv[3];
79
80 /* Plumbing */
81 close(lvpipe[0]);
82
83 if (lvpipe[1] != STDOUT_FILENO)
84 dup2(lvpipe[1], STDOUT_FILENO);
85
86 /* The libblkid library could linked with setuid programs */
87 if (setgid(getgid()) < 0)
88 exit(1);
89 if (setuid(getuid()) < 0)
90 exit(1);
91
92 lvargv[0] = cmd;
93 lvargv[1] = devname;
94 lvargv[2] = NULL;
95
96 execv(lvargv[0], lvargv);
97
bigbiff7b4c7a62015-01-01 19:44:14 -050098 DBG(LOWPROBE, ul_debug("Failed to execute %s: errno=%d", cmd, errno));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050099 exit(1);
100 }
101 case -1:
bigbiff7b4c7a62015-01-01 19:44:14 -0500102 DBG(LOWPROBE, ul_debug("Failed to forking: errno=%d", errno));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500103 goto nothing;
104 default:
105 break;
106 }
107
bigbiff7b4c7a62015-01-01 19:44:14 -0500108 stream = fdopen(lvpipe[0], "r" UL_CLOEXECSTR);
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500109 if (!stream)
110 goto nothing;
111
112 while (fgets(buf, sizeof(buf), stream) != NULL) {
113 if (!strncmp(buf, "Stripes", 7))
114 sscanf(buf, "Stripes %d", &stripes);
115
116 if (!strncmp(buf, "Stripe size", 11))
117 sscanf(buf, "Stripe size (KByte) %d", &stripesize);
118 }
119
120 if (!stripes)
121 goto nothing;
122
123 blkid_topology_set_minimum_io_size(pr, stripesize << 10);
124 blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
125
126 free(devname);
127 fclose(stream);
128 close(lvpipe[1]);
129 return 0;
130
131nothing:
132 free(devname);
133 if (stream)
134 fclose(stream);
135 else if (lvpipe[0] != -1)
136 close(lvpipe[0]);
137 if (lvpipe[1] != -1)
138 close(lvpipe[1]);
139 return 1;
140}
141
142const struct blkid_idinfo lvm_tp_idinfo =
143{
144 .name = "lvm",
145 .probefunc = probe_lvm_tp,
146 .magics = BLKID_NONE_MAGIC
147};
148