#include "mdadm.h"
#include "dlink.h"
#include <sys/select.h>
+#include <ctype.h>
void free_mdstat(struct mdstat_ent *ms)
{
if (ms->dev) free(ms->dev);
if (ms->level) free(ms->level);
if (ms->pattern) free(ms->pattern);
+ if (ms->metadata_version) free(ms->metadata_version);
t = ms;
ms = ms->next;
free(t);
f = fopen("/proc/mdstat", "r");
if (f == NULL)
return NULL;
+ else
+ fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
all = NULL;
end = &all;
ent->percent = -1;
ent->active = -1;
ent->resync = 0;
+ ent->metadata_version = NULL;
+ ent->raid_disks = 0;
+ ent->chunk_size = 0;
+ ent->devcnt = 0;
ent->dev = strdup(line);
ent->devnum = devnum;
-
+
for (w=dl_next(line); w!= line ; w=dl_next(w)) {
int l = strlen(w);
char *eq;
in_devs = 1;
} else if (in_devs && strcmp(w, "blocks")==0)
in_devs = 0;
- else if (in_devs && strncmp(w, "md", 2)==0) {
- /* This has an md device as a component.
- * If that device is already in the list,
- * make sure we insert before there.
- */
- struct mdstat_ent **ih;
- int dn2;
- if (strncmp(w, "md_d", 4)==0)
- dn2 = -1-strtoul(w+4, &ep, 10);
- else
- dn2 = strtoul(w+2, &ep, 10);
- ih = &all;
- while (ih != insert_here && *ih &&
- (*ih)->devnum != dn2)
- ih = & (*ih)->next;
- insert_here = ih;
+ else if (in_devs) {
+ ent->devcnt++;
+ if (strncmp(w, "md", 2)==0) {
+ /* This has an md device as a component.
+ * If that device is already in the
+ * list, make sure we insert before
+ * there.
+ */
+ struct mdstat_ent **ih;
+ int dn2 = devname2devnum(w);
+ ih = &all;
+ while (ih != insert_here && *ih &&
+ (*ih)->devnum != dn2)
+ ih = & (*ih)->next;
+ insert_here = ih;
+ }
+ } else if (strcmp(w, "super") == 0 &&
+ dl_next(w) != line) {
+ w = dl_next(w);
+ ent->metadata_version = strdup(w);
+ } else if (w[0] == '[' && isdigit(w[1])) {
+ ent->raid_disks = atoi(w+1);
} else if (!ent->pattern &&
w[0] == '[' &&
(w[1] == 'U' || w[1] == '_')) {
strncmp(w, "resync", 4)==0) {
ent->resync = 1;
} else if (ent->percent == -1 &&
- w[0] >= '0' &&
+ w[0] >= '0' &&
w[0] <= '9' &&
w[l-1] == '%') {
ent->percent = atoi(w);
end = &ent->next;
}
}
- if (hold && mdstat_fd == -1)
+ if (hold && mdstat_fd == -1) {
mdstat_fd = dup(fileno(f));
+ fcntl(mdstat_fd, F_SETFD, FD_CLOEXEC);
+ }
fclose(f);
/* If we might want to start array,
{
fd_set fds;
struct timeval tm;
+ int maxfd = 0;
FD_ZERO(&fds);
- if (mdstat_fd >= 0)
+ if (mdstat_fd >= 0) {
FD_SET(mdstat_fd, &fds);
+ maxfd = mdstat_fd;
+ }
tm.tv_sec = seconds;
tm.tv_usec = 0;
- select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm);
+ select(maxfd + 1, NULL, NULL, &fds, &tm);
+}
+
+void mdstat_wait_fd(int fd, const sigset_t *sigmask)
+{
+ fd_set fds, rfds;
+ int maxfd = fd;
+
+ FD_ZERO(&fds);
+ FD_ZERO(&rfds);
+ if (mdstat_fd >= 0)
+ FD_SET(mdstat_fd, &fds);
+ if (fd >= 0) {
+ struct stat stb;
+ fstat(fd, &stb);
+ if ((stb.st_mode & S_IFMT) == S_IFREG)
+ /* Must be a /proc or /sys fd, so expect
+ * POLLPRI
+ * i.e. an 'exceptional' event.
+ */
+ FD_SET(fd, &fds);
+ else
+ FD_SET(fd, &rfds);
+ }
+ if (mdstat_fd > maxfd)
+ maxfd = mdstat_fd;
+
+ pselect(maxfd + 1, &rfds, NULL, &fds,
+ NULL, sigmask);
}
int mddev_busy(int devnum)