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