]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdstat.c
Remove scattered checks for malloc success.
[thirdparty/mdadm.git] / mdstat.c
index bb030bf391774fe491a9c8e70c3b6156a7c59c33..5f690e5dfdbd4093c275d9a49bd128a630718257 100644 (file)
--- a/mdstat.c
+++ b/mdstat.c
@@ -103,7 +103,7 @@ static int add_member_devname(struct dev_member **m, char *name)
                /* not a device */
                return 0;
 
-       new = malloc(sizeof(*new));
+       new = xmalloc(sizeof(*new));
        new->name = strndup(name, t - name);
        new->next = *m;
        *m = new;
@@ -131,10 +131,15 @@ struct mdstat_ent *mdstat_read(int hold, int start)
        FILE *f;
        struct mdstat_ent *all, *rv, **end, **insert_here;
        char *line;
+       int fd;
 
        if (hold && mdstat_fd != -1) {
                lseek(mdstat_fd, 0L, 0);
-               f = fdopen(dup(mdstat_fd), "r");
+               fd = dup(mdstat_fd);
+               if (fd >= 0)
+                       f = fdopen(fd, "r");
+               else
+                       return NULL;
        } else
                f = fopen("/proc/mdstat", "r");
        if (f == NULL)
@@ -168,28 +173,22 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                else
                        continue;
                if (ep == NULL || *ep ) {
-                       /* fprintf(stderr, Name ": bad /proc/mdstat line starts: %s\n", line); */
+                       /* pr_err("bad /proc/mdstat line starts: %s\n", line); */
                        continue;
                }
 
-               ent = malloc(sizeof(*ent));
-               if (!ent) {
-                       fprintf(stderr, Name ": malloc failed reading /proc/mdstat.\n");
-                       free_line(line);
-                       break;
-               }
+               ent = xmalloc(sizeof(*ent));
                ent->dev = ent->level = ent->pattern= NULL;
                ent->next = NULL;
-               ent->percent = -1;
+               ent->percent = RESYNC_NONE;
                ent->active = -1;
                ent->resync = 0;
                ent->metadata_version = NULL;
                ent->raid_disks = 0;
-               ent->chunk_size = 0;
                ent->devcnt = 0;
                ent->members = NULL;
 
-               ent->dev = strdup(line);
+               ent->dev = xstrdup(line);
                ent->devnum = devnum;
 
                for (w=dl_next(line); w!= line ; w=dl_next(w)) {
@@ -203,7 +202,7 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                        } else if (ent->active > 0 &&
                                 ent->level == NULL &&
                                 w[0] != '(' /*readonly*/) {
-                               ent->level = strdup(w);
+                               ent->level = xstrdup(w);
                                in_devs = 1;
                        } else if (in_devs && strcmp(w, "blocks")==0)
                                in_devs = 0;
@@ -227,16 +226,16 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                        } else if (strcmp(w, "super") == 0 &&
                                   dl_next(w) != line) {
                                w = dl_next(w);
-                               ent->metadata_version = strdup(w);
+                               ent->metadata_version = xstrdup(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);
+                               ent->pattern = xstrdup(w+1);
                                if (ent->pattern[l-2]==']')
                                        ent->pattern[l-2] = '\0';
-                       } else if (ent->percent == -1 &&
+                       } else if (ent->percent == RESYNC_NONE &&
                                   strncmp(w, "re", 2)== 0 &&
                                   w[l-1] == '%' &&
                                   (eq=strchr(w, '=')) != NULL ) {
@@ -247,22 +246,22 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                                        ent->resync = 2;
                                else
                                        ent->resync = 0;
-                       } else if (ent->percent == -1 &&
+                       } else if (ent->percent == RESYNC_NONE &&
                                   (w[0] == 'r' || w[0] == 'c')) {
                                if (strncmp(w, "resync", 4)==0)
                                        ent->resync = 1;
                                if (strncmp(w, "reshape", 7)==0)
                                        ent->resync = 2;
                                if (strncmp(w, "recovery", 8)==0)
-                                       ent->resync = 2;
+                                       ent->resync = 0;
                                if (strncmp(w, "check", 5)==0)
                                        ent->resync = 3;
 
-                               if (l > 8 && strcmp(w+l-8, "=DELAYED"))
-                                       ent->percent = 0;
-                               if (l > 8 && strcmp(w+l-8, "=PENDING"))
-                                       ent->percent = 0;
-                       } else if (ent->percent == -1 &&
+                               if (l > 8 && strcmp(w+l-8, "=DELAYED") == 0)
+                                       ent->percent = RESYNC_DELAYED;
+                               if (l > 8 && strcmp(w+l-8, "=PENDING") == 0)
+                                       ent->percent = RESYNC_PENDING;
+                       } else if (ent->percent == RESYNC_NONE &&
                                   w[0] >= '0' &&
                                   w[0] <= '9' &&
                                   w[l-1] == '%') {
@@ -384,3 +383,36 @@ struct mdstat_ent *mdstat_by_component(char *name)
        }
        return NULL;
 }
+
+struct mdstat_ent *mdstat_by_subdev(char *subdev, int container)
+{
+       struct mdstat_ent *mdstat = mdstat_read(0, 0);
+
+       while (mdstat) {
+               struct mdstat_ent *ent;
+               char *pos;
+               /* metadata version must match:
+                *   external:[/-]md%d/%s
+                * where %d is 'container' and %s is 'subdev'
+                */
+               if (mdstat->metadata_version &&
+                   strncmp(mdstat->metadata_version, "external:", 9) == 0 &&
+                   strchr("/-", mdstat->metadata_version[9]) != NULL &&
+                   strncmp(mdstat->metadata_version+10, "md", 2) == 0 &&
+                   strtoul(mdstat->metadata_version+12, &pos, 10)
+                   == (unsigned)container &&
+                   pos > mdstat->metadata_version+12 &&
+                   *pos == '/' &&
+                   strcmp(pos+1, subdev) == 0
+                       ) {
+                       free_mdstat(mdstat->next);
+                       mdstat->next = NULL;
+                       return mdstat;
+               }
+               ent = mdstat;
+               mdstat = mdstat->next;
+               ent->next = NULL;
+               free_mdstat(ent);
+       }
+       return NULL;
+}