summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemon/md.c172
-rw-r--r--generator/generator_actions.ml49
-rw-r--r--generator/generator_structs.ml8
-rw-r--r--java/Makefile.inc1
-rw-r--r--java/com/redhat/et/libguestfs/.gitignore1
-rw-r--r--src/MAX_PROC_NR2
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