blob: 632c42b713118331b3e885f55fa58c29ce377f1a [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) {
70 DBG(DEBUG_LOWPROBE,
71 printf("Failed to open pipe: errno=%d", errno));
72 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
98 DBG(DEBUG_LOWPROBE,
99 printf("Failed to execute %s: errno=%d", cmd, errno));
100 exit(1);
101 }
102 case -1:
103 DBG(DEBUG_LOWPROBE,
104 printf("Failed to forking: errno=%d", errno));
105 goto nothing;
106 default:
107 break;
108 }
109
110 stream = fdopen(lvpipe[0], "r");
111 if (!stream)
112 goto nothing;
113
114 while (fgets(buf, sizeof(buf), stream) != NULL) {
115 if (!strncmp(buf, "Stripes", 7))
116 sscanf(buf, "Stripes %d", &stripes);
117
118 if (!strncmp(buf, "Stripe size", 11))
119 sscanf(buf, "Stripe size (KByte) %d", &stripesize);
120 }
121
122 if (!stripes)
123 goto nothing;
124
125 blkid_topology_set_minimum_io_size(pr, stripesize << 10);
126 blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
127
128 free(devname);
129 fclose(stream);
130 close(lvpipe[1]);
131 return 0;
132
133nothing:
134 free(devname);
135 if (stream)
136 fclose(stream);
137 else if (lvpipe[0] != -1)
138 close(lvpipe[0]);
139 if (lvpipe[1] != -1)
140 close(lvpipe[1]);
141 return 1;
142}
143
144const struct blkid_idinfo lvm_tp_idinfo =
145{
146 .name = "lvm",
147 .probefunc = probe_lvm_tp,
148 .magics = BLKID_NONE_MAGIC
149};
150