]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add mdstat_by_component
authorNeilBrown <neilb@suse.de>
Wed, 30 Jun 2010 06:55:17 +0000 (16:55 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 30 Jun 2010 06:55:17 +0000 (16:55 +1000)
This allows finding the array which contains a given component.
Components are named using the kernel-internal string name such
as "sda1" or "hdb".
Don't return member arrays, only the contain that contains them.

Also tidy up the parsing of 'inactive' arrays in /proc/mdstat.
If we see 'inactive' we need to set 'in_devs' immediately as there
is no level coming.

Signed-off-by: NeilBrown <neilb@suse.de>
mdadm.h
mdstat.c

diff --git a/mdadm.h b/mdadm.h
index a0797e8c9be26eeb9a63246b1e2ba7bdd89d745d..cdf6acbf44d43989c4020fa7b55c9e64ac3ebd3d 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -355,6 +355,10 @@ struct mdstat_ent {
        int             raid_disks;
        int             chunk_size;
        char *          metadata_version;
+       struct dev_member {
+               char                    *name;
+               struct dev_member       *next;
+       }               *members;
        struct mdstat_ent *next;
 };
 
@@ -363,6 +367,7 @@ extern void free_mdstat(struct mdstat_ent *ms);
 extern void mdstat_wait(int seconds);
 extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
 extern int mddev_busy(int devnum);
+extern struct mdstat_ent *mdstat_by_component(char *name);
 
 struct map_ent {
        struct map_ent *next;
index fdca877b741819020767d903410fb0abb5c3b6e3..3bb74fa27410c48feb6a0cad285da1ce23388852 100644 (file)
--- a/mdstat.c
+++ b/mdstat.c
 #include       <sys/select.h>
 #include       <ctype.h>
 
+static void free_member_devnames(struct dev_member *m)
+{
+       while(m) {
+               struct dev_member *t = m;
+
+               m = m->next;
+               free(t->name);
+               free(t);
+       }
+}
+
+static void add_member_devname(struct dev_member **m, char *name)
+{
+       struct dev_member *new;
+       char *t;
+
+       if ((t = strchr(name, '[')) == NULL)
+               /* not a device */
+               return;
+
+       new = malloc(sizeof(*new));
+       new->name = strndup(name, t - name);
+       new->next = *m;
+       *m = new;
+}
+
 void free_mdstat(struct mdstat_ent *ms)
 {
        while (ms) {
                struct mdstat_ent *t;
-               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);
+               free(ms->dev);
+               free(ms->level);
+               free(ms->pattern);
+               free(ms->metadata_version);
+               free_member_devnames(ms->members);
                t = ms;
                ms = ms->next;
                free(t);
@@ -159,6 +186,7 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                ent->raid_disks = 0;
                ent->chunk_size = 0;
                ent->devcnt = 0;
+               ent->members = NULL;
 
                ent->dev = strdup(line);
                ent->devnum = devnum;
@@ -180,6 +208,7 @@ struct mdstat_ent *mdstat_read(int hold, int start)
                                in_devs = 0;
                        else if (in_devs) {
                                ent->devcnt++;
+                               add_member_devname(&ent->members, w);
                                if (strncmp(w, "md", 2)==0) {
                                        /* This has an md device as a component.
                                         * If that device is already in the
@@ -311,3 +340,30 @@ int mddev_busy(int devnum)
        free_mdstat(mdstat);
        return me != NULL;
 }
+
+struct mdstat_ent *mdstat_by_component(char *name)
+{
+       struct mdstat_ent *mdstat = mdstat_read(0, 0);
+
+       while (mdstat) {
+               struct dev_member *m;
+               struct mdstat_ent *ent;
+               if (mdstat->metadata_version &&
+                   strncmp(mdstat->metadata_version, "external:", 9) == 0 &&
+                   is_subarray(mdstat->metadata_version+9))
+                       /* don't return subarrays, only containers */
+                       ;
+               else for (m = mdstat->members; m; m = m->next) {
+                               if (strcmp(m->name, name) == 0) {
+                                       free_mdstat(mdstat->next);
+                                       mdstat->next = NULL;
+                                       return mdstat;
+                               }
+                       }
+               ent = mdstat;
+               mdstat = mdstat->next;
+               ent->next = NULL;
+               free_mdstat(ent);
+       }
+       return NULL;
+}