X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;ds=sidebyside;f=mdstat.c;h=ebdfc67bf6d46705e1ebcb74212299b2aa47b66c;hb=1ee1e9fc62e74f56ca6786690f4247c4c7a8c1bb;hp=3204d2e468f08d30e4f5753ef2e10115d365f121;hpb=dd0781e50555c32ff2f808ec46f4b03a5693ea47;p=thirdparty%2Fmdadm.git diff --git a/mdstat.c b/mdstat.c index 3204d2e4..ebdfc67b 100644 --- a/mdstat.c +++ b/mdstat.c @@ -2,7 +2,7 @@ * mdstat - parse /proc/mdstat file. Part of: * mdadm - manage Linux "md" devices aka RAID arrays. * - * Copyright (C) 2002 Neil Brown + * Copyright (C) 2002-2006 Neil Brown * * * This program is free software; you can redistribute it and/or modify @@ -43,7 +43,7 @@ * read_ahead {not set|%d sectors} * mdN : {in}active {(readonly)} raidX dev[%d]{(F)} ... %d blocks STATUS RESYNC * ... Only initialised arrays listed - * unused: dev dev dev | + * unused devices: {dev dev ... | } * * STATUS is personality dependant: * linear: %dk rounding @@ -62,7 +62,7 @@ * mdN : {in}active {(read-only)} raidX dev[%d]{(F)} ... * %d blocks STATUS * RESYNC - * unused: dev dev .. | + * unused devices: {dev dev .. | } * * STATUS matches 0.90.0/2.2 * RESYNC includes [===>....], @@ -86,6 +86,7 @@ #include "mdadm.h" #include "dlink.h" #include +#include void free_mdstat(struct mdstat_ent *ms) { @@ -94,6 +95,7 @@ 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); @@ -101,10 +103,10 @@ void free_mdstat(struct mdstat_ent *ms) } static int mdstat_fd = -1; -struct mdstat_ent *mdstat_read(int hold) +struct mdstat_ent *mdstat_read(int hold, int start) { FILE *f; - struct mdstat_ent *all, **end; + struct mdstat_ent *all, *rv, **end, **insert_here; char *line; if (hold && mdstat_fd != -1) { @@ -114,6 +116,8 @@ struct mdstat_ent *mdstat_read(int hold) f = fopen("/proc/mdstat", "r"); if (f == NULL) return NULL; + else + fcntl(fileno(f), F_SETFD, FD_CLOEXEC); all = NULL; end = &all; @@ -121,6 +125,7 @@ struct mdstat_ent *mdstat_read(int hold) struct mdstat_ent *ent; char *w; int devnum; + int in_devs = 0; char *ep; if (strcmp(line, "Personalities")==0) @@ -129,6 +134,7 @@ struct mdstat_ent *mdstat_read(int hold) continue; if (strcmp(line, "unused")==0) continue; + insert_here = NULL; /* Better be an md line.. */ if (strncmp(line, "md", 2)!= 0) continue; @@ -153,10 +159,15 @@ struct mdstat_ent *mdstat_read(int hold) ent->next = NULL; 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; @@ -166,9 +177,34 @@ struct mdstat_ent *mdstat_read(int hold) ent->active = 0; else if (ent->active >=0 && ent->level == NULL && - w[0] != '(' /*readonly*/) + w[0] != '(' /*readonly*/) { ent->level = strdup(w); - else if (!ent->pattern && + in_devs = 1; + } else if (in_devs && strcmp(w, "blocks")==0) + in_devs = 0; + 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] == '_')) { ent->pattern = strdup(w+1); @@ -179,30 +215,88 @@ struct mdstat_ent *mdstat_read(int hold) w[l-1] == '%' && (eq=strchr(w, '=')) != NULL ) { ent->percent = atoi(eq+1); + if (strncmp(w,"resync", 4)==0) + ent->resync = 1; + } else if (ent->percent == -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; - end = &ent->next; + if (insert_here && (*insert_here)) { + ent->next = *insert_here; + *insert_here = ent; + } else { + *end = ent; + 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); - return all; + + /* If we might want to start array, + * reverse the order, so that components comes before composites + */ + if (start) { + rv = NULL; + while (all) { + struct mdstat_ent *e = all; + all = all->next; + e->next = rv; + rv = e; + } + } else rv = all; + return rv; } void mdstat_wait(int seconds) { 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) + FD_SET(fd, &rfds); + if (mdstat_fd > maxfd) + maxfd = mdstat_fd; + + pselect(maxfd + 1, &rfds, NULL, &fds, + NULL, sigmask); +} + +int mddev_busy(int devnum) +{ + struct mdstat_ent *mdstat = mdstat_read(0, 0); + struct mdstat_ent *me; + + for (me = mdstat ; me ; me = me->next) + if (me->devnum == devnum) + break; + free_mdstat(mdstat); + return me != NULL; }