]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdstat.c
Release devel-2
[thirdparty/mdadm.git] / mdstat.c
index c5b8f1e565d5f26f61acbad964ffd6e65ccd30f6..9a7327988e198bf5f74a9a5d4ed0ba7e11733485 100644 (file)
--- a/mdstat.c
+++ b/mdstat.c
@@ -85,6 +85,7 @@
 
 #include       "mdadm.h"
 #include       "dlink.h"
+#include       <sys/select.h>
 
 void free_mdstat(struct mdstat_ent *ms)
 {
@@ -99,13 +100,18 @@ void free_mdstat(struct mdstat_ent *ms)
        }
 }
 
-struct mdstat_ent *mdstat_read()
+static int mdstat_fd = -1;
+struct mdstat_ent *mdstat_read(int hold)
 {
        FILE *f;
        struct mdstat_ent *all, **end;
        char *line;
 
-       f = fopen("/proc/mdstat", "r");
+       if (hold && mdstat_fd != -1) {
+               lseek(mdstat_fd, 0L, 0);
+               f = fdopen(dup(mdstat_fd), "r");
+       } else
+               f = fopen("/proc/mdstat", "r");
        if (f == NULL)
                return NULL;
 
@@ -114,6 +120,8 @@ struct mdstat_ent *mdstat_read()
        for (; (line = conf_line(f)) ; free_line(line)) {
                struct mdstat_ent *ent;
                char *w;
+               int devnum;
+               char *ep;
 
                if (strcmp(line, "Personalities")==0)
                        continue;
@@ -122,9 +130,16 @@ struct mdstat_ent *mdstat_read()
                if (strcmp(line, "unused")==0)
                        continue;
                /* Better be an md line.. */
-               if (strncmp(line, "md", 2)!= 0
-                   || atoi(line+2)<0) {
-                       fprintf(stderr, Name ": bad /proc/mdstat line starts: %s\n", line);
+               if (strncmp(line, "md", 2)!= 0)
+                       continue;
+               if (strncmp(line, "md_d", 4) == 0)
+                       devnum = -1-strtoul(line+4, &ep, 10);
+               else if (strncmp(line, "md", 2) == 0)
+                       devnum = strtoul(line+2, &ep, 10);
+               else
+                       continue;
+               if (ep == NULL || *ep ) {
+                       /* fprintf(stderr, Name ": bad /proc/mdstat line starts: %s\n", line); */
                        continue;
                }
 
@@ -132,16 +147,16 @@ struct mdstat_ent *mdstat_read()
                if (!ent) {
                        fprintf(stderr, Name ": malloc failed reading /proc/mdstat.\n");
                        free_line(line);
-                       fclose(f);
-                       return all;
+                       break;
                }
                ent->dev = ent->level = ent->pattern= NULL;
                ent->next = NULL;
                ent->percent = -1;
                ent->active = -1;
+               ent->resync = 0;
 
                ent->dev = strdup(line);
-               ent->devnum = atoi(line+2);
+               ent->devnum = devnum;
                
                for (w=dl_next(line); w!= line ; w=dl_next(w)) {
                        int l = strlen(w);
@@ -165,6 +180,11 @@ struct mdstat_ent *mdstat_read()
                                   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] <= '9' &&
@@ -175,6 +195,20 @@ struct mdstat_ent *mdstat_read()
                *end = ent;
                end = &ent->next;
        }
+       if (hold && mdstat_fd == -1)
+               mdstat_fd = dup(fileno(f));
        fclose(f);
        return all;
 }
+
+void mdstat_wait(int seconds)
+{
+       fd_set fds;
+       struct timeval tm;
+       FD_ZERO(&fds);
+       if (mdstat_fd >= 0)
+               FD_SET(mdstat_fd, &fds);
+       tm.tv_sec = seconds;
+       tm.tv_usec = 0;
+       select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm);
+}