diff options
-rw-r--r-- | daemon/md.c | 172 | ||||
-rw-r--r-- | generator/generator_actions.ml | 49 | ||||
-rw-r--r-- | generator/generator_structs.ml | 8 | ||||
-rw-r--r-- | java/Makefile.inc | 1 | ||||
-rw-r--r-- | java/com/redhat/et/libguestfs/.gitignore | 1 | ||||
-rw-r--r-- | src/MAX_PROC_NR | 2 |
6 files changed, 232 insertions, 1 deletions
diff --git a/daemon/md.c b/daemon/md.c index 265f4f4c..0e2f7048 100644 --- a/daemon/md.c +++ b/daemon/md.c @@ -329,3 +329,175 @@ do_md_stop(const char *md) free (err); return 0; } + +static size_t +count_spaces (const char *line) +{ + size_t r = 0; + while (*line) { + if (*line == ' ') + r++; + line++; + } + return r; +} + +/* Parse a line like: "active raid1 sdb1[0] sdc1[1](F)" */ +static guestfs_int_mdstat_list * +parse_md_stat_line (char *line) +{ + guestfs_int_mdstat_list *ret; + guestfs_int_mdstat *t; + size_t spaces, n, i, len; + char *next; + char *p, *q; + + ret = malloc (sizeof *ret); + if (!ret) { + reply_with_perror ("malloc"); + return NULL; + } + + /* We don't know exactly how many entries we will need yet, but we + * can estimate it, and this will always be an over-estimate. + */ + spaces = count_spaces (line); + ret->guestfs_int_mdstat_list_val = + calloc (spaces+1, sizeof (struct guestfs_int_mdstat)); + if (ret->guestfs_int_mdstat_list_val == NULL) { + reply_with_perror ("malloc"); + free (ret); + return NULL; + } + + for (n = 0; *line; line = next) { + len = strcspn (line, " "); + if (line[len] == '\0') + next = &line[len]; + else { + line[len] = '\0'; + next = &line[len+1]; + } + + if (verbose) + printf ("mdstat: %s\n", line); + + /* Looking for entries that contain "[..]", skip ones which don't. */ + p = strchr (line, '['); + if (p == NULL) + continue; + q = strchr (line, ']'); + if (q == NULL) + continue; + if (p > q) + continue; + + ret->guestfs_int_mdstat_list_len = n+1; + t = &ret->guestfs_int_mdstat_list_val[n]; + + /* Device name is everything before the '[' character, but we + * need to prefix with /dev/. + */ + if (p == line) { + reply_with_error ("device entry is too short: %s", line); + goto error; + } + + *p = '\0'; + if (asprintf (&t->mdstat_device, "/dev/%s", line) == -1) { + reply_with_perror ("asprintf"); + goto error; + } + + /* Device index is the number after '['. */ + line = p+1; + *q = '\0'; + if (sscanf (line, "%" SCNi32, &t->mdstat_index) != 1) { + reply_with_error ("not a device number: %s", line); + goto error; + } + + /* Looking for flags "(F)(S)...". */ + line = q+1; + len = strlen (line); + t->mdstat_flags = malloc (len+1); + if (!t->mdstat_flags) { + reply_with_error ("malloc"); + goto error; + } + + for (i = 0; *line; line++) { + if (c_isalpha (*line)) + t->mdstat_flags[i++] = *line; + } + t->mdstat_flags[i] = '\0'; + + n++; + } + + return ret; + + error: + for (i = 0; i <= spaces; ++i) { + free (ret->guestfs_int_mdstat_list_val[i].mdstat_device); + free (ret->guestfs_int_mdstat_list_val[i].mdstat_flags); + } + free (ret->guestfs_int_mdstat_list_val); + free (ret); + return NULL; +} + +extern guestfs_int_mdstat_list * +do_md_stat (const char *md) +{ + size_t mdlen; + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t n; + guestfs_int_mdstat_list *ret = NULL; + + if (STRPREFIX (md, "/dev/")) + md += 5; + mdlen = strlen (md); + + fp = fopen ("/proc/mdstat", "r"); + if (fp == NULL) { + reply_with_perror ("fopen: %s", "/proc/mdstat"); + return NULL; + } + + /* Search for a line which begins with "<md> : ". */ + while ((n = getline (&line, &len, fp)) != -1) { + if (STRPREFIX (line, md) && + line[mdlen] == ' ' && line[mdlen+1] == ':' && line[mdlen+2] == ' ') { + /* Found it. */ + ret = parse_md_stat_line (&line[mdlen+3]); + if (!ret) { + free (line); + fclose (fp); + return NULL; + } + + /* Stop parsing the mdstat file after we've found the line + * we are interested in. + */ + break; + } + } + + free (line); + + if (fclose (fp) == EOF) { + reply_with_perror ("fclose: %s", "/proc/mdstat"); + return NULL; + } + + /* Did we find the line? */ + if (!ret) { + reply_with_error ("%s: MD device not found", md); + return NULL; + } + + return ret; +} diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 8c074ca9..68a7bf69 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -6822,6 +6822,55 @@ volume group and returns its metadata. Note that the metadata is an internal structure used by LVM, subject to change at any time, and is provided for information only."); + ("md_stat", (RStructList ("devices", "mdstat"), [Device "md"], []), 316, [Optional "mdadm"], + [], + "get underlying devices from an MD device", + "\ +This call returns a list of the underlying devices which make +up the single software RAID array device C<md>. + +To get a list of software RAID devices, call C<guestfs_list_md_devices>. + +Each structure returned corresponds to one device along with +additional status information: + +=over 4 + +=item C<mdstat_device> + +The name of the underlying device. + +=item C<mdstat_index> + +The index of this device within the array. + +=item C<mdstat_flags> + +Flags associated with this device. This is a string containing +(in no specific order) zero or more of the following flags: + +=over 4 + +=item C<W> + +write-mostly + +=item C<F> + +device is faulty + +=item C<S> + +device is a RAID spare + +=item C<R> + +replacement + +=back + +=back"); + ] let all_functions = non_daemon_functions @ daemon_functions diff --git a/generator/generator_structs.ml b/generator/generator_structs.ml index 61228a4b..8c862ae3 100644 --- a/generator/generator_structs.ml +++ b/generator/generator_structs.ml @@ -212,6 +212,13 @@ let structs = [ "iso_volume_expiration_t", FInt64; "iso_volume_effective_t", FInt64; ]; + + (* /proc/mdstat information. See linux.git/drivers/md/md.c *) + "mdstat", [ + "mdstat_device", FString; + "mdstat_index", FInt32; + "mdstat_flags", FString; + ]; ] (* end of structs *) (* For bindings which want camel case *) @@ -229,6 +236,7 @@ let camel_structs = [ "partition", "Partition"; "application", "Application"; "isoinfo", "ISOInfo"; + "mdstat", "MDStat"; ] let camel_structs = List.sort (fun (_,a) (_,b) -> compare a b) camel_structs diff --git a/java/Makefile.inc b/java/Makefile.inc index c6ec02c2..64c6dcc2 100644 --- a/java/Makefile.inc +++ b/java/Makefile.inc @@ -26,6 +26,7 @@ java_built_sources = \ com/redhat/et/libguestfs/ISOInfo.java \ com/redhat/et/libguestfs/IntBool.java \ com/redhat/et/libguestfs/LV.java \ + com/redhat/et/libguestfs/MDStat.java \ com/redhat/et/libguestfs/PV.java \ com/redhat/et/libguestfs/Partition.java \ com/redhat/et/libguestfs/Stat.java \ diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore index 8673379c..c7cc3020 100644 --- a/java/com/redhat/et/libguestfs/.gitignore +++ b/java/com/redhat/et/libguestfs/.gitignore @@ -4,6 +4,7 @@ INotifyEvent.java ISOInfo.java IntBool.java LV.java +MDStat.java PV.java Partition.java Stat.java diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 66953656..47eb669b 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -315 +316 |