]> git.ipfire.org Git - thirdparty/mdadm.git/blame - sysfs.c
Remove spaces/tabs from ends of lines.
[thirdparty/mdadm.git] / sysfs.c
CommitLineData
e86c9dd6
NB
1/*
2 * sysfs - extract md related information from sysfs. Part of:
3 * mdadm - manage Linux "md" devices aka RAID arrays.
4 *
5 * Copyright (C) 2006 Neil Brown <neilb@suse.de>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Author: Neil Brown
23 * Email: <neilb@suse.de>
24 */
25
26#include "mdadm.h"
27#include <dirent.h>
28
29int load_sys(char *path, char *buf)
30{
31 int fd = open(path, O_RDONLY);
32 int n;
33 if (fd < 0)
34 return -1;
35 n = read(fd, buf, 1024);
36 close(fd);
37 if (n <=0 || n >= 1024)
38 return -1;
39 buf[n] = 0;
40 if (buf[n-1] == '\n')
41 buf[n-1] = 0;
42 return 0;
43}
44
8382f19b
NB
45void sysfs_free(struct sysarray *sra)
46{
47 if (!sra)
48 return;
49 while (sra->devs) {
50 struct sysdev *d = sra->devs;
51 sra->devs = d->next;
52 free(d);
53 }
54 free(sra);
55}
56
e86c9dd6
NB
57struct sysarray *sysfs_read(int fd, int devnum, unsigned long options)
58{
59 /* Longest possible name in sysfs, mounted at /sys, is
60 * /sys/block/md_dXXX/md/dev-XXXXX/block/dev
61 * /sys/block/md_dXXX/md/metadata_version
62 * which is about 41 characters. 50 should do for now
63 */
64 char fname[50];
65 char buf[1024];
66 char *base;
67 char *dbase;
68 struct sysarray *sra;
69 struct sysdev *dev;
70 DIR *dir;
71 struct dirent *de;
72
73 sra = malloc(sizeof(*sra));
74 if (sra == NULL)
75 return sra;
76
77 if (fd >= 0) {
78 struct stat stb;
79 if (fstat(fd, &stb)) return NULL;
80 if (major(stb.st_rdev)==9)
81 sprintf(sra->name, "md%d", minor(stb.st_rdev));
82 else
83 sprintf(sra->name, "md_d%d",
7fa42a0b 84 minor(stb.st_rdev)>>MdpMinorShift);
e86c9dd6
NB
85 } else {
86 if (devnum >= 0)
87 sprintf(sra->name, "md%d", devnum);
88 else
89 sprintf(sra->name, "md_d%d",
90 -1-devnum);
91 }
92 sprintf(fname, "/sys/block/%s/md/", sra->name);
93 base = fname + strlen(fname);
94
95 sra->devs = NULL;
8382f19b
NB
96 if (options & GET_VERSION) {
97 strcpy(base, "metadata_version");
98 if (load_sys(fname, buf))
99 goto abort;
100 if (strncmp(buf, "none", 4) == 0)
101 sra->major_version = sra->minor_version = -1;
102 else
103 sscanf(buf, "%d.%d",
104 &sra->major_version, &sra->minor_version);
105 }
e86c9dd6
NB
106 if (options & GET_LEVEL) {
107 strcpy(base, "level");
108 if (load_sys(fname, buf))
109 goto abort;
110 sra->level = map_name(pers, buf);
111 }
112 if (options & GET_LAYOUT) {
113 strcpy(base, "layout");
114 if (load_sys(fname, buf))
115 goto abort;
116 sra->layout = strtoul(buf, NULL, 0);
117 }
118 if (options & GET_COMPONENT) {
119 strcpy(base, "component_size");
120 if (load_sys(fname, buf))
121 goto abort;
122 sra->component_size = strtoull(buf, NULL, 0);
353632d9
NB
123 /* sysfs reports "K", but we want sectors */
124 sra->component_size *= 2;
e86c9dd6
NB
125 }
126 if (options & GET_CHUNK) {
127 strcpy(base, "chunk_size");
128 if (load_sys(fname, buf))
129 goto abort;
130 sra->chunk = strtoul(buf, NULL, 0);
131 }
758d3a8e
NB
132 if (options & GET_CACHE) {
133 strcpy(base, "stripe_cache_size");
134 if (load_sys(fname, buf))
135 goto abort;
136 sra->cache_size = strtoul(buf, NULL, 0);
137 }
37dfc3d6
NB
138 if (options & GET_MISMATCH) {
139 strcpy(base, "mismatch_cnt");
140 if (load_sys(fname, buf))
141 goto abort;
142 sra->mismatch_cnt = strtoul(buf, NULL, 0);
143 }
e86c9dd6
NB
144
145 if (! (options & GET_DEVS))
146 return sra;
147
148 /* Get all the devices as well */
149 *base = 0;
150 dir = opendir(fname);
151 if (!dir)
152 goto abort;
153 sra->spares = 0;
154
155 while ((de = readdir(dir)) != NULL) {
156 char *ep;
157 if (de->d_ino == 0 ||
158 strncmp(de->d_name, "dev-", 4) != 0)
159 continue;
160 strcpy(base, de->d_name);
161 dbase = base + strlen(base);
162 *dbase++ = '/';
163
164 dev = malloc(sizeof(*dev));
165 if (!dev)
166 goto abort;
167 dev->next = sra->devs;
168 sra->devs = dev;
8382f19b 169 strcpy(dev->name, de->d_name);
e86c9dd6
NB
170
171 /* Always get slot, major, minor */
172 strcpy(dbase, "slot");
173 if (load_sys(fname, buf))
174 goto abort;
175 dev->role = strtoul(buf, &ep, 10);
176 if (*ep) dev->role = -1;
177
178 strcpy(dbase, "block/dev");
179 if (load_sys(fname, buf))
180 goto abort;
181 sscanf(buf, "%d:%d", &dev->major, &dev->minor);
182
183 if (options & GET_OFFSET) {
184 strcpy(dbase, "offset");
185 if (load_sys(fname, buf))
186 goto abort;
187 dev->offset = strtoull(buf, NULL, 0);
188 }
189 if (options & GET_SIZE) {
190 strcpy(dbase, "size");
191 if (load_sys(fname, buf))
192 goto abort;
193 dev->size = strtoull(buf, NULL, 0);
194 }
195 if (options & GET_STATE) {
196 dev->state = 0;
197 strcpy(dbase, "state");
198 if (load_sys(fname, buf))
199 goto abort;
200 if (strstr(buf, "in_sync"))
201 dev->state |= (1<<MD_DISK_SYNC);
202 if (strstr(buf, "faulty"))
203 dev->state |= (1<<MD_DISK_FAULTY);
204 if (dev->state == 0)
205 sra->spares++;
206 }
207 if (options & GET_ERROR) {
208 strcpy(buf, "errors");
209 if (load_sys(fname, buf))
210 goto abort;
211 dev->errors = strtoul(buf, NULL, 0);
212 }
213 }
214 return sra;
215
216 abort:
8382f19b 217 sysfs_free(sra);
e86c9dd6
NB
218 return NULL;
219}
220
221unsigned long long get_component_size(int fd)
222{
223 /* Find out the component size of the array.
224 * We cannot trust GET_ARRAY_INFO ioctl as it's
225 * size field is only 32bits.
226 * So look in /sys/block/mdXXX/md/component_size
353632d9 227 *
8686f3ed 228 * This returns in units of sectors.
e86c9dd6
NB
229 */
230 struct stat stb;
231 char fname[50];
232 int n;
233 if (fstat(fd, &stb)) return 0;
234 if (major(stb.st_rdev) == 9)
235 sprintf(fname, "/sys/block/md%d/md/component_size",
236 minor(stb.st_rdev));
237 else
238 sprintf(fname, "/sys/block/md_d%d/md/component_size",
7fa42a0b 239 minor(stb.st_rdev)>>MdpMinorShift);
e86c9dd6
NB
240 fd = open(fname, O_RDONLY);
241 if (fd < 0)
242 return 0;
243 n = read(fd, fname, sizeof(fname));
244 close(fd);
245 if (n == sizeof(fname))
246 return 0;
247 fname[n] = 0;
8686f3ed 248 return strtoull(fname, NULL, 10) * 2;
e86c9dd6
NB
249}
250
251int sysfs_set_str(struct sysarray *sra, struct sysdev *dev,
252 char *name, char *val)
253{
254 char fname[50];
255 int n;
256 int fd;
257 sprintf(fname, "/sys/block/%s/md/%s/%s",
258 sra->name, dev?dev->name:"", name);
259 fd = open(fname, O_WRONLY);
260 if (fd < 0)
261 return -1;
262 n = write(fd, val, strlen(val));
263 close(fd);
264 if (n != strlen(val))
265 return -1;
266 return 0;
267}
268
269int sysfs_set_num(struct sysarray *sra, struct sysdev *dev,
270 char *name, unsigned long long val)
271{
272 char valstr[50];
273 sprintf(valstr, "%llu", val);
274 return sysfs_set_str(sra, dev, name, valstr);
275}
276
277int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev,
278 char *name, unsigned long long *val)
279{
280 char fname[50];
281 char buf[50];
282 int n;
283 int fd;
284 char *ep;
285 sprintf(fname, "/sys/block/%s/md/%s/%s",
286 sra->name, dev?dev->name:"", name);
287 fd = open(fname, O_RDONLY);
288 if (fd < 0)
289 return -1;
290 n = read(fd, buf, sizeof(buf));
291 close(fd);
292 if (n <= 0)
293 return -1;
294 buf[n] = 0;
295 *val = strtoull(buf, &ep, 0);
296 if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' '))
297 return -1;
298 return 0;
299}