diff options
author | NeilBrown <neilb@suse.de> | 2010-04-09 07:25:07 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-04-09 07:25:07 +1000 |
commit | c81c0cab6ea8ee5fd0eccefba9e64a77ad18df30 (patch) | |
tree | 0a49101fe8bd18f4199340cf05b0804fd6051610 /mdstat.c | |
parent | 94fcb80a8e0c6311636b2ee689a6ac5b7125afe6 (diff) | |
download | mdadm-c81c0cab6ea8ee5fd0eccefba9e64a77ad18df30.tar.gz mdadm-c81c0cab6ea8ee5fd0eccefba9e64a77ad18df30.tar.xz mdadm-c81c0cab6ea8ee5fd0eccefba9e64a77ad18df30.zip |
Add mdstat_by_component
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>
Diffstat (limited to 'mdstat.c')
-rw-r--r-- | mdstat.c | 69 |
1 files changed, 63 insertions, 6 deletions
@@ -83,14 +83,41 @@ #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; @@ -168,9 +196,10 @@ struct mdstat_ent *mdstat_read(int hold, int start) char *eq; if (strcmp(w, "active")==0) ent->active = 1; - else if (strcmp(w, "inactive")==0) + else if (strcmp(w, "inactive")==0) { ent->active = 0; - else if (ent->active >=0 && + in_devs = 1; + } else if (ent->active > 0 && ent->level == NULL && w[0] != '(' /*readonly*/) { ent->level = strdup(w); @@ -179,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 @@ -310,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 (ent->metadata_version && + strncmp(ent->metadata_version, "external:", 9) == 0 && + is_subarray(ent->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; +} |