Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
---
These two patches are refactored to parse the output info structures.
daemon/btrfs.c | 109 +++++++++++++++++++++++++++++++
generator/actions.ml | 10 +++
generator/structs.ml | 12 ++++
gobject/Makefile.inc | 2 +
java/Makefile.inc | 1 +
java/com/redhat/et/libguestfs/.gitignore | 1 +
po/POTFILES | 1 +
src/MAX_PROC_NR | 2 +-
8 files changed, 137 insertions(+), 1 deletion(-)
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index 796eaff..bb82f32 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -1659,3 +1659,112 @@ do_btrfs_rescue_super_recover (const char *device)
return 0;
}
+
+guestfs_int_btrfsbalance *
+do_btrfs_balance_status (const char *path)
+{
+ const size_t MAX_ARGS = 64;
+ const char *argv[MAX_ARGS];
+ size_t i = 0;
+ CLEANUP_FREE char *path_buf = NULL;
+ CLEANUP_FREE char *err = NULL;
+ char *out;
+ int r;
+ guestfs_int_btrfsbalance *ret;
+ char **lines;
+ const char *errptr;
+ int erroffset;
+#define N_MATCH 2
+ int ovector[N_MATCH * 3];
+ pcre *re = NULL;
+
+ path_buf = sysroot_path (path);
+ if (path_buf == NULL) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+
+ ADD_ARG (argv, i, str_btrfs);
+ ADD_ARG (argv, i, "balance");
+ ADD_ARG (argv, i, "status");
+ ADD_ARG (argv, i, path_buf);
+ ADD_ARG (argv, i, NULL);
+
+ r = commandv (&out, &err, argv);
+ if (r == -1) {
+ reply_with_error ("%s: %s", path, err);
+ return NULL;
+ }
+
+ lines = split_lines (out);
+ if (!lines)
+ return NULL;
+
+ ret = malloc(sizeof *ret);
+ if (ret == NULL) {
+ reply_with_perror ("malloc");
+ goto error;
+ }
+ memset (ret, 0, sizeof(*ret));
+
+ /* Output of `btrfs balance status' is like:
+ *
+ * running:
+ *
+ * Balance on '/' is running
+ * 3 out of about 8 chunks balanced (3 considered), 62% left
+ *
+ * paused:
+ *
+ * Balance on '/' is paused
+ * 3 out of about 8 chunks balanced (3 considered), 62% left
+ *
+ * no balance running:
+ *
+ * No Balance found on '/'
+ *
+ */
+ if (strstr (lines[0], "No balance found on")) {
+ ret->btrfsbalance_status = strdup("none");
+ return ret;
+ }
+
+ re = pcre_compile ("Balance on '.*' is (.*)", 0,
&errptr, &erroffset, NULL);
+ if (re == NULL) {
+ reply_with_error ("pcre_compile (%i): %s", erroffset, errptr);
+ goto error;
+ }
+ if (pcre_exec (re, NULL, lines[0], strlen (lines[0]), 0, 0,
+ ovector, N_MATCH * 3) < 0) {
+ reply_with_error ("unexpected output from 'btrfs balance
status' command: %s", lines[0]);
+ goto error;
+ }
+#undef N_MATCH
+
+ if (STREQ (lines[0] + ovector[2], "running"))
+ ret->btrfsbalance_status = strdup("running");
+ else if (STREQ (lines[0] + ovector[2], "paused"))
+ ret->btrfsbalance_status = strdup("paused");
+ else {
+ reply_with_error ("unexpected output from 'btrfs balance
status' command: %s", lines[0]);
+ goto error;
+ }
+
+ if (sscanf (lines[1], "%" SCNu64 " out of about %" SCNu64
+ " chunks balanced (%" SCNu64 " considered),
%" SCNu64 "%% left",
+ &ret->btrfsbalance_balanced,
&ret->btrfsbalance_total,
+ &ret->btrfsbalance_considered,
&ret->btrfsbalance_left) != 4) {
+ reply_with_perror ("sscanf");
+ goto error;
+ }
+
+ pcre_free (re);
+ return ret;
+
+error:
+ free (ret->btrfsbalance_status);
+ free (ret);
+ pcre_free (re);
+
+ return NULL;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index c0beaae..f943ecb 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12385,6 +12385,16 @@ Recover the chunk tree of btrfs filesystem by scannning
the devices one by one."
longdesc = "\
Recover bad superblocks from good copies." };
+{ defaults with
+ name = "btrfs_balance_status";
+ style = RStruct ("status", "btrfsbalance"), [Pathname
"path"], [];
+ proc_nr = Some 446;
+ optional = Some "btrfs"; camel_name =
"BTRFSBalanceStatus";
+ test_excuse = "test disk isn't large enough that btrfs_balance
completes before we can get its status";
+ shortdesc = "show the status of a running or paused balance";
+ longdesc = "\
+Show the status of a running or paused balance on a btrfs filesystem." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/generator/structs.ml b/generator/structs.ml
index 5b466a2..af42529 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -340,6 +340,18 @@ let structs = [
];
s_camel_name = "BTRFSQgroup" };
+ (* btrfs balance status output *)
+ { defaults with
+ s_name = "btrfsbalance";
+ s_cols = [
+ "btrfsbalance_status", FString;
+ "btrfsbalance_total", FUInt64;
+ "btrfsbalance_balanced", FUInt64;
+ "btrfsbalance_considered", FUInt64;
+ "btrfsbalance_left", FUInt64;
+ ];
+ s_camel_name = "BTRFSBalance" };
+
(* XFS info descriptor. *)
{ defaults with
s_name = "xfsinfo";
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index e0c0a5f..3ce10f9 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -25,6 +25,7 @@ guestfs_gobject_headers= \
include/guestfs-gobject/tristate.h \
include/guestfs-gobject/struct-application.h \
include/guestfs-gobject/struct-application2.h \
+ include/guestfs-gobject/struct-btrfsbalance.h \
include/guestfs-gobject/struct-btrfsqgroup.h \
include/guestfs-gobject/struct-btrfssubvolume.h \
include/guestfs-gobject/struct-dirent.h \
@@ -108,6 +109,7 @@ guestfs_gobject_sources= \
src/tristate.c \
src/struct-application.c \
src/struct-application2.c \
+ src/struct-btrfsbalance.c \
src/struct-btrfsqgroup.c \
src/struct-btrfssubvolume.c \
src/struct-dirent.c \
diff --git a/java/Makefile.inc b/java/Makefile.inc
index 103010f..499d3de 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -22,6 +22,7 @@
java_built_sources = \
com/redhat/et/libguestfs/Application.java \
com/redhat/et/libguestfs/Application2.java \
+ com/redhat/et/libguestfs/BTRFSBalance.java \
com/redhat/et/libguestfs/BTRFSQgroup.java \
com/redhat/et/libguestfs/BTRFSSubvolume.java \
com/redhat/et/libguestfs/Dirent.java \
diff --git a/java/com/redhat/et/libguestfs/.gitignore
b/java/com/redhat/et/libguestfs/.gitignore
index 1d4accc..b2b1b22 100644
--- a/java/com/redhat/et/libguestfs/.gitignore
+++ b/java/com/redhat/et/libguestfs/.gitignore
@@ -1,5 +1,6 @@
Application.java
Application2.java
+BTRFSBalance.java
BTRFSQgroup.java
BTRFSSubvolume.java
Dirent.java
diff --git a/po/POTFILES b/po/POTFILES
index 4194e5f..9330256 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -230,6 +230,7 @@ gobject/src/optargs-xfs_repair.c
gobject/src/session.c
gobject/src/struct-application.c
gobject/src/struct-application2.c
+gobject/src/struct-btrfsbalance.c
gobject/src/struct-btrfsqgroup.c
gobject/src/struct-btrfssubvolume.c
gobject/src/struct-dirent.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index e5a135a..0187835 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-445
+446
--
2.1.0
Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
---
daemon/btrfs.c | 142 +++++++++++++++++++++++++++++++
generator/actions.ml | 16 ++++
generator/structs.ml | 22 +++++
gobject/Makefile.inc | 2 +
java/Makefile.inc | 1 +
java/com/redhat/et/libguestfs/.gitignore | 1 +
po/POTFILES | 1 +
src/MAX_PROC_NR | 2 +-
8 files changed, 186 insertions(+), 1 deletion(-)
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index bb82f32..0f49fb5 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -1768,3 +1768,145 @@ error:
return NULL;
}
+
+guestfs_int_btrfsscrub *
+do_btrfs_scrub_status (const char *path)
+{
+ const size_t MAX_ARGS = 64;
+ const char *argv[MAX_ARGS];
+ size_t i = 0;
+ CLEANUP_FREE char *path_buf = NULL;
+ CLEANUP_FREE char *err = NULL;
+ char *out;
+ int r;
+ guestfs_int_btrfsscrub *ret;
+ char **lines;
+ char *line;
+
+ path_buf = sysroot_path (path);
+ if (path_buf == NULL) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+
+ ADD_ARG (argv, i, str_btrfs);
+ ADD_ARG (argv, i, "scrub");
+ ADD_ARG (argv, i, "status");
+ ADD_ARG (argv, i, "-R");
+ ADD_ARG (argv, i, path_buf);
+ ADD_ARG (argv, i, NULL);
+
+ r = commandv (&out, &err, argv);
+ if (r == -1) {
+ reply_with_error ("%s: %s", path, err);
+ return NULL;
+ }
+
+ lines = split_lines (out);
+ if (!lines)
+ return NULL;
+
+ ret = malloc (sizeof *ret);
+ if (ret == NULL) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+ memset (ret, 0, sizeof(*ret));
+
+ /* Output of `btrfs scrub -R status' is like:
+ *
+ * strub status for 346121d1-1847-40f8-9b7b-2bf3d539c68f
+ * scrub started at Mon Feb 2 17:39:38 2015, running for 93
seconds
+ * data_extents_scrubbed: 136670
+ * tree_extents_scrubbed: 30023
+ * data_bytes_scrubbed: 4474441728
+ * tree_bytes_scrubbed: 491896832
+ * read_errors: 0
+ * csum_errors: 0
+ * verify_errors: 0
+ * no_csum: 17760
+ * csum_discards: 197622
+ * super_errors: 0
+ * malloc_errors: 0
+ * uncorrectable_errors: 0
+ * unverified_errors: 0
+ * corrected_errors: 0
+ * last_physical: 10301341696
+ *
+ * or:
+ *
+ * strub status for 346121d1-1847-40f8-9b7b-2bf3d539c68f
+ * no stats available
+ */
+ line = lines[1];
+ if (STREQ (line, "\tno stats available"))
+ return ret;
+
+ line = lines[2];
+ if (sscanf (line, "\tdata_extents_scrubbed: %" SCNu64,
+ &ret->btrfsscrub_data_extents_scrubbed) != 1)
+ goto error;
+ line = lines[3];
+ if (sscanf (line, "\ttree_extents_scrubbed: %" SCNu64,
+ &ret->btrfsscrub_tree_extents_scrubbed) != 1)
+ goto error;
+ line = lines[4];
+ if (sscanf (line, "\tdata_bytes_scrubbed: %" SCNu64,
+ &ret->btrfsscrub_data_bytes_scrubbed) != 1)
+ goto error;
+ line = lines[5];
+ if (sscanf (line, "\ttree_bytes_scrubbed: %" SCNu64,
+ &ret->btrfsscrub_tree_bytes_scrubbed) != 1)
+ goto error;
+ line = lines[6];
+ if (sscanf (line, "\tread_errors: %" SCNu64,
+ &ret->btrfsscrub_read_errors) != 1)
+ goto error;
+ line = lines[7];
+ if (sscanf (line, "\tcsum_errors: %" SCNu64,
+ &ret->btrfsscrub_csum_errors) != 1)
+ goto error;
+ line = lines[8];
+ if (sscanf (line, "\tverify_errors: %" SCNu64,
+ &ret->btrfsscrub_verify_errors) != 1)
+ goto error;
+ line = lines[9];
+ if (sscanf (line, "\tno_csum: %" SCNu64,
+ &ret->btrfsscrub_no_csum) != 1)
+ goto error;
+ line = lines[10];
+ if (sscanf (line, "\tcsum_discards: %" SCNu64,
+ &ret->btrfsscrub_csum_discards) != 1)
+ goto error;
+ line = lines[11];
+ if (sscanf (line, "\tsuper_errors: %" SCNu64,
+ &ret->btrfsscrub_super_errors) != 1)
+ goto error;
+ line = lines[12];
+ if (sscanf (line, "\tmalloc_errors: %" SCNu64,
+ &ret->btrfsscrub_malloc_errors) != 1)
+ goto error;
+ line = lines[13];
+ if (sscanf (line, "\tuncorrectable_errors: %" SCNu64,
+ &ret->btrfsscrub_uncorrectable_errors) != 1)
+ goto error;
+ line = lines[14];
+ if (sscanf (line, "\tunverified_errors: %" SCNu64,
+ &ret->btrfsscrub_unverified_errors) != 1)
+ goto error;
+ line = lines[15];
+ if (sscanf (line, "\tcorrected_errors: %" SCNu64,
+ &ret->btrfsscrub_corrected_errors) != 1)
+ goto error;
+ line = lines[16];
+ if (sscanf (line, "\tlast_physical: %" SCNu64,
+ &ret->btrfsscrub_last_physical) != 1)
+ goto error;
+
+ return ret;
+
+error:
+ reply_with_error ("%s: could not parse btrfs scrub status.", line);
+ free (ret);
+ return NULL;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index f943ecb..a2d43e4 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12395,6 +12395,22 @@ Recover bad superblocks from good copies." };
longdesc = "\
Show the status of a running or paused balance on a btrfs filesystem." };
+ { defaults with
+ name = "btrfs_scrub_status";
+ style = RStruct ("status", "btrfsscrub"), [Pathname
"path"], [];
+ proc_nr = Some 447;
+ optional = Some "btrfs"; camel_name =
"BTRFSScrubStatus";
+ tests = [
+ InitPartition, Always, TestRun (
+ [["mkfs_btrfs"; "/dev/sda1"; "";
""; "NOARG"; ""; "NOARG";
"NOARG"; ""; ""];
+ ["mount"; "/dev/sda1"; "/"];
+ ["btrfs_scrub_start"; "/"];
+ ["btrfs_scrub_status"; "/"]]), [];
+ ];
+ shortdesc = "show status of running or finished scrub";
+ longdesc = "\
+Show status of running or finished scrub on a btrfs filesystem." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/generator/structs.ml b/generator/structs.ml
index af42529..ea110a1 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -352,6 +352,28 @@ let structs = [
];
s_camel_name = "BTRFSBalance" };
+ (* btrfs scrub status output *)
+ { defaults with
+ s_name = "btrfsscrub";
+ s_cols = [
+ "btrfsscrub_data_extents_scrubbed", FUInt64;
+ "btrfsscrub_tree_extents_scrubbed", FUInt64;
+ "btrfsscrub_data_bytes_scrubbed", FUInt64;
+ "btrfsscrub_tree_bytes_scrubbed", FUInt64;
+ "btrfsscrub_read_errors", FUInt64;
+ "btrfsscrub_csum_errors", FUInt64;
+ "btrfsscrub_verify_errors", FUInt64;
+ "btrfsscrub_no_csum", FUInt64;
+ "btrfsscrub_csum_discards", FUInt64;
+ "btrfsscrub_super_errors", FUInt64;
+ "btrfsscrub_malloc_errors", FUInt64;
+ "btrfsscrub_uncorrectable_errors", FUInt64;
+ "btrfsscrub_unverified_errors", FUInt64;
+ "btrfsscrub_corrected_errors", FUInt64;
+ "btrfsscrub_last_physical", FUInt64;
+ ];
+ s_camel_name = "BTRFSScrub" };
+
(* XFS info descriptor. *)
{ defaults with
s_name = "xfsinfo";
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index 3ce10f9..6bbd72c 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -27,6 +27,7 @@ guestfs_gobject_headers= \
include/guestfs-gobject/struct-application2.h \
include/guestfs-gobject/struct-btrfsbalance.h \
include/guestfs-gobject/struct-btrfsqgroup.h \
+ include/guestfs-gobject/struct-btrfsscrub.h \
include/guestfs-gobject/struct-btrfssubvolume.h \
include/guestfs-gobject/struct-dirent.h \
include/guestfs-gobject/struct-hivex_node.h \
@@ -111,6 +112,7 @@ guestfs_gobject_sources= \
src/struct-application2.c \
src/struct-btrfsbalance.c \
src/struct-btrfsqgroup.c \
+ src/struct-btrfsscrub.c \
src/struct-btrfssubvolume.c \
src/struct-dirent.c \
src/struct-hivex_node.c \
diff --git a/java/Makefile.inc b/java/Makefile.inc
index 499d3de..477842a 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -24,6 +24,7 @@ java_built_sources = \
com/redhat/et/libguestfs/Application2.java \
com/redhat/et/libguestfs/BTRFSBalance.java \
com/redhat/et/libguestfs/BTRFSQgroup.java \
+ com/redhat/et/libguestfs/BTRFSScrub.java \
com/redhat/et/libguestfs/BTRFSSubvolume.java \
com/redhat/et/libguestfs/Dirent.java \
com/redhat/et/libguestfs/HivexNode.java \
diff --git a/java/com/redhat/et/libguestfs/.gitignore
b/java/com/redhat/et/libguestfs/.gitignore
index b2b1b22..8389269 100644
--- a/java/com/redhat/et/libguestfs/.gitignore
+++ b/java/com/redhat/et/libguestfs/.gitignore
@@ -2,6 +2,7 @@ Application.java
Application2.java
BTRFSBalance.java
BTRFSQgroup.java
+BTRFSScrub.java
BTRFSSubvolume.java
Dirent.java
HivexNode.java
diff --git a/po/POTFILES b/po/POTFILES
index 9330256..5d089ac 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -232,6 +232,7 @@ gobject/src/struct-application.c
gobject/src/struct-application2.c
gobject/src/struct-btrfsbalance.c
gobject/src/struct-btrfsqgroup.c
+gobject/src/struct-btrfsscrub.c
gobject/src/struct-btrfssubvolume.c
gobject/src/struct-dirent.c
gobject/src/struct-hivex_node.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 0187835..e9b7520 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-446
+447
--
2.1.0
Richard W.M. Jones
2015-Feb-02 13:00 UTC
[Libguestfs] [PATCH 1/2] New API: btrfs_balance_status
On Mon, Feb 02, 2015 at 02:11:31PM +0800, Hu Tao wrote:> Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>I'm just running some manual tests on this patch series, but it looks good and if I find no compile/test problems then I'll commit both. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
Richard W.M. Jones
2015-Feb-02 13:29 UTC
Re: [Libguestfs] [PATCH 1/2] New API: btrfs_balance_status
On Mon, Feb 02, 2015 at 02:11:31PM +0800, Hu Tao wrote: [..] So in fact there are a few problems. I couldn't get btrfs balance to actually do anything at all (perhaps it doesn't work on empty filesystems), so this come only from code inspection.> + lines = split_lines (out); > + if (!lines) > + return NULL; > + > + ret = malloc(sizeof *ret); > + if (ret == NULL) { > + reply_with_perror ("malloc"); > + goto error; > + } > + memset (ret, 0, sizeof(*ret)); > + > + /* Output of `btrfs balance status' is like: > + * > + * running: > + * > + * Balance on '/' is running > + * 3 out of about 8 chunks balanced (3 considered), 62% left > + * > + * paused: > + * > + * Balance on '/' is paused > + * 3 out of about 8 chunks balanced (3 considered), 62% left > + * > + * no balance running: > + * > + * No Balance found on '/' > + * > + */ > + if (strstr (lines[0], "No balance found on")) {In case the output of the btrfs command changes in future, you need to check that the length of the lines[] array is >= 1 here, and >= 2 below. Otherwise this code will segfault.> + ret->btrfsbalance_status = strdup("none");Where you call strdup, you have to check that the return value is not NULL, and if it is call reply_with_perror ("strdup").> + return ret; > + } > + > + re = pcre_compile ("Balance on '.*' is (.*)", 0, &errptr, &erroffset, NULL); > + if (re == NULL) { > + reply_with_error ("pcre_compile (%i): %s", erroffset, errptr); > + goto error; > + } > + if (pcre_exec (re, NULL, lines[0], strlen (lines[0]), 0, 0, > + ovector, N_MATCH * 3) < 0) { > + reply_with_error ("unexpected output from 'btrfs balance status' command: %s", lines[0]); > + goto error; > + } > +#undef N_MATCH > + > + if (STREQ (lines[0] + ovector[2], "running")) > + ret->btrfsbalance_status = strdup("running"); > + else if (STREQ (lines[0] + ovector[2], "paused")) > + ret->btrfsbalance_status = strdup("paused"); > + else { > + reply_with_error ("unexpected output from 'btrfs balance status' command: %s", lines[0]); > + goto error; > + } > + > + if (sscanf (lines[1], "%" SCNu64 " out of about %" SCNu64 > + " chunks balanced (%" SCNu64 " considered), %" SCNu64 "%% left", > + &ret->btrfsbalance_balanced, &ret->btrfsbalance_total, > + &ret->btrfsbalance_considered, &ret->btrfsbalance_left) != 4) { > + reply_with_perror ("sscanf"); > + goto error; > + } > + > + pcre_free (re); > + return ret; > + > +error: > + free (ret->btrfsbalance_status); > + free (ret); > + pcre_free (re); > + > + return NULL;Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
Richard W.M. Jones
2015-Feb-02 13:32 UTC
Re: [Libguestfs] [PATCH 2/2] New API: btfs_scrub_status.
On Mon, Feb 02, 2015 at 02:11:32PM +0800, Hu Tao wrote:> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > daemon/btrfs.c | 142 +++++++++++++++++++++++++++++++ > generator/actions.ml | 16 ++++ > generator/structs.ml | 22 +++++ > gobject/Makefile.inc | 2 + > java/Makefile.inc | 1 + > java/com/redhat/et/libguestfs/.gitignore | 1 + > po/POTFILES | 1 + > src/MAX_PROC_NR | 2 +- > 8 files changed, 186 insertions(+), 1 deletion(-) > > diff --git a/daemon/btrfs.c b/daemon/btrfs.c > index bb82f32..0f49fb5 100644 > --- a/daemon/btrfs.c > +++ b/daemon/btrfs.c > @@ -1768,3 +1768,145 @@ error: > > return NULL; > } > + > +guestfs_int_btrfsscrub * > +do_btrfs_scrub_status (const char *path) > +{ > + const size_t MAX_ARGS = 64; > + const char *argv[MAX_ARGS]; > + size_t i = 0; > + CLEANUP_FREE char *path_buf = NULL; > + CLEANUP_FREE char *err = NULL; > + char *out; > + int r; > + guestfs_int_btrfsscrub *ret; > + char **lines; > + char *line; > + > + path_buf = sysroot_path (path); > + if (path_buf == NULL) { > + reply_with_perror ("malloc"); > + return NULL; > + } > + > + ADD_ARG (argv, i, str_btrfs); > + ADD_ARG (argv, i, "scrub"); > + ADD_ARG (argv, i, "status"); > + ADD_ARG (argv, i, "-R"); > + ADD_ARG (argv, i, path_buf); > + ADD_ARG (argv, i, NULL); > + > + r = commandv (&out, &err, argv); > + if (r == -1) { > + reply_with_error ("%s: %s", path, err); > + return NULL; > + } > + > + lines = split_lines (out); > + if (!lines) > + return NULL; > + > + ret = malloc (sizeof *ret); > + if (ret == NULL) { > + reply_with_perror ("malloc"); > + return NULL; > + } > + memset (ret, 0, sizeof(*ret)); > + > + /* Output of `btrfs scrub -R status' is like: > + * > + * strub status for 346121d1-1847-40f8-9b7b-2bf3d539c68f > + * scrub started at Mon Feb 2 17:39:38 2015, running for 93 seconds > + * data_extents_scrubbed: 136670 > + * tree_extents_scrubbed: 30023 > + * data_bytes_scrubbed: 4474441728 > + * tree_bytes_scrubbed: 491896832 > + * read_errors: 0 > + * csum_errors: 0 > + * verify_errors: 0 > + * no_csum: 17760 > + * csum_discards: 197622 > + * super_errors: 0 > + * malloc_errors: 0 > + * uncorrectable_errors: 0 > + * unverified_errors: 0 > + * corrected_errors: 0 > + * last_physical: 10301341696 > + * > + * or: > + * > + * strub status for 346121d1-1847-40f8-9b7b-2bf3d539c68f > + * no stats available > + */ > + line = lines[1];Again, I doubt that the output of btrfs scrub -R status will remain the same forever. You need to at least check that lines[] is sufficiently long to avoid a possible segfault, and it's probably better to use a loop here. Compare the function xfs.c:parse_xfs_info() Rich.> + if (STREQ (line, "\tno stats available")) > + return ret; > + > + line = lines[2]; > + if (sscanf (line, "\tdata_extents_scrubbed: %" SCNu64, > + &ret->btrfsscrub_data_extents_scrubbed) != 1) > + goto error; > + line = lines[3]; > + if (sscanf (line, "\ttree_extents_scrubbed: %" SCNu64, > + &ret->btrfsscrub_tree_extents_scrubbed) != 1) > + goto error; > + line = lines[4]; > + if (sscanf (line, "\tdata_bytes_scrubbed: %" SCNu64, > + &ret->btrfsscrub_data_bytes_scrubbed) != 1) > + goto error; > + line = lines[5]; > + if (sscanf (line, "\ttree_bytes_scrubbed: %" SCNu64, > + &ret->btrfsscrub_tree_bytes_scrubbed) != 1) > + goto error; > + line = lines[6]; > + if (sscanf (line, "\tread_errors: %" SCNu64, > + &ret->btrfsscrub_read_errors) != 1) > + goto error; > + line = lines[7]; > + if (sscanf (line, "\tcsum_errors: %" SCNu64, > + &ret->btrfsscrub_csum_errors) != 1) > + goto error; > + line = lines[8]; > + if (sscanf (line, "\tverify_errors: %" SCNu64, > + &ret->btrfsscrub_verify_errors) != 1) > + goto error; > + line = lines[9]; > + if (sscanf (line, "\tno_csum: %" SCNu64, > + &ret->btrfsscrub_no_csum) != 1) > + goto error; > + line = lines[10]; > + if (sscanf (line, "\tcsum_discards: %" SCNu64, > + &ret->btrfsscrub_csum_discards) != 1) > + goto error; > + line = lines[11]; > + if (sscanf (line, "\tsuper_errors: %" SCNu64, > + &ret->btrfsscrub_super_errors) != 1) > + goto error; > + line = lines[12]; > + if (sscanf (line, "\tmalloc_errors: %" SCNu64, > + &ret->btrfsscrub_malloc_errors) != 1) > + goto error; > + line = lines[13]; > + if (sscanf (line, "\tuncorrectable_errors: %" SCNu64, > + &ret->btrfsscrub_uncorrectable_errors) != 1) > + goto error; > + line = lines[14]; > + if (sscanf (line, "\tunverified_errors: %" SCNu64, > + &ret->btrfsscrub_unverified_errors) != 1) > + goto error; > + line = lines[15]; > + if (sscanf (line, "\tcorrected_errors: %" SCNu64, > + &ret->btrfsscrub_corrected_errors) != 1) > + goto error; > + line = lines[16]; > + if (sscanf (line, "\tlast_physical: %" SCNu64, > + &ret->btrfsscrub_last_physical) != 1) > + goto error; > + > + return ret; > + > +error: > + reply_with_error ("%s: could not parse btrfs scrub status.", line); > + free (ret); > + return NULL; > +} > diff --git a/generator/actions.ml b/generator/actions.ml > index f943ecb..a2d43e4 100644 > --- a/generator/actions.ml > +++ b/generator/actions.ml > @@ -12395,6 +12395,22 @@ Recover bad superblocks from good copies." }; > longdesc = "\ > Show the status of a running or paused balance on a btrfs filesystem." }; > > + { defaults with > + name = "btrfs_scrub_status"; > + style = RStruct ("status", "btrfsscrub"), [Pathname "path"], []; > + proc_nr = Some 447; > + optional = Some "btrfs"; camel_name = "BTRFSScrubStatus"; > + tests = [ > + InitPartition, Always, TestRun ( > + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; > + ["mount"; "/dev/sda1"; "/"]; > + ["btrfs_scrub_start"; "/"]; > + ["btrfs_scrub_status"; "/"]]), []; > + ]; > + shortdesc = "show status of running or finished scrub"; > + longdesc = "\ > +Show status of running or finished scrub on a btrfs filesystem." }; > + > ] > > (* Non-API meta-commands available only in guestfish. > diff --git a/generator/structs.ml b/generator/structs.ml > index af42529..ea110a1 100644 > --- a/generator/structs.ml > +++ b/generator/structs.ml > @@ -352,6 +352,28 @@ let structs = [ > ]; > s_camel_name = "BTRFSBalance" }; > > + (* btrfs scrub status output *) > + { defaults with > + s_name = "btrfsscrub"; > + s_cols = [ > + "btrfsscrub_data_extents_scrubbed", FUInt64; > + "btrfsscrub_tree_extents_scrubbed", FUInt64; > + "btrfsscrub_data_bytes_scrubbed", FUInt64; > + "btrfsscrub_tree_bytes_scrubbed", FUInt64; > + "btrfsscrub_read_errors", FUInt64; > + "btrfsscrub_csum_errors", FUInt64; > + "btrfsscrub_verify_errors", FUInt64; > + "btrfsscrub_no_csum", FUInt64; > + "btrfsscrub_csum_discards", FUInt64; > + "btrfsscrub_super_errors", FUInt64; > + "btrfsscrub_malloc_errors", FUInt64; > + "btrfsscrub_uncorrectable_errors", FUInt64; > + "btrfsscrub_unverified_errors", FUInt64; > + "btrfsscrub_corrected_errors", FUInt64; > + "btrfsscrub_last_physical", FUInt64; > + ]; > + s_camel_name = "BTRFSScrub" }; > + > (* XFS info descriptor. *) > { defaults with > s_name = "xfsinfo"; > diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc > index 3ce10f9..6bbd72c 100644 > --- a/gobject/Makefile.inc > +++ b/gobject/Makefile.inc > @@ -27,6 +27,7 @@ guestfs_gobject_headers= \ > include/guestfs-gobject/struct-application2.h \ > include/guestfs-gobject/struct-btrfsbalance.h \ > include/guestfs-gobject/struct-btrfsqgroup.h \ > + include/guestfs-gobject/struct-btrfsscrub.h \ > include/guestfs-gobject/struct-btrfssubvolume.h \ > include/guestfs-gobject/struct-dirent.h \ > include/guestfs-gobject/struct-hivex_node.h \ > @@ -111,6 +112,7 @@ guestfs_gobject_sources= \ > src/struct-application2.c \ > src/struct-btrfsbalance.c \ > src/struct-btrfsqgroup.c \ > + src/struct-btrfsscrub.c \ > src/struct-btrfssubvolume.c \ > src/struct-dirent.c \ > src/struct-hivex_node.c \ > diff --git a/java/Makefile.inc b/java/Makefile.inc > index 499d3de..477842a 100644 > --- a/java/Makefile.inc > +++ b/java/Makefile.inc > @@ -24,6 +24,7 @@ java_built_sources = \ > com/redhat/et/libguestfs/Application2.java \ > com/redhat/et/libguestfs/BTRFSBalance.java \ > com/redhat/et/libguestfs/BTRFSQgroup.java \ > + com/redhat/et/libguestfs/BTRFSScrub.java \ > com/redhat/et/libguestfs/BTRFSSubvolume.java \ > com/redhat/et/libguestfs/Dirent.java \ > com/redhat/et/libguestfs/HivexNode.java \ > diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore > index b2b1b22..8389269 100644 > --- a/java/com/redhat/et/libguestfs/.gitignore > +++ b/java/com/redhat/et/libguestfs/.gitignore > @@ -2,6 +2,7 @@ Application.java > Application2.java > BTRFSBalance.java > BTRFSQgroup.java > +BTRFSScrub.java > BTRFSSubvolume.java > Dirent.java > HivexNode.java > diff --git a/po/POTFILES b/po/POTFILES > index 9330256..5d089ac 100644 > --- a/po/POTFILES > +++ b/po/POTFILES > @@ -232,6 +232,7 @@ gobject/src/struct-application.c > gobject/src/struct-application2.c > gobject/src/struct-btrfsbalance.c > gobject/src/struct-btrfsqgroup.c > +gobject/src/struct-btrfsscrub.c > gobject/src/struct-btrfssubvolume.c > gobject/src/struct-dirent.c > gobject/src/struct-hivex_node.c > diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR > index 0187835..e9b7520 100644 > --- a/src/MAX_PROC_NR > +++ b/src/MAX_PROC_NR > @@ -1 +1 @@ > -446 > +447 > -- > 2.1.0 > > _______________________________________________ > Libguestfs mailing list > Libguestfs@redhat.com > https://www.redhat.com/mailman/listinfo/libguestfs-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
On Mon, Feb 02, 2015 at 01:29:35PM +0000, Richard W.M. Jones wrote:> On Mon, Feb 02, 2015 at 02:11:31PM +0800, Hu Tao wrote: > [..] > > So in fact there are a few problems. I couldn't get btrfs balance to > actually do anything at all (perhaps it doesn't work on empty > filesystems), so this come only from code inspection.Thou I can get btrfs-balance run, but it seems like a sync operation, i.e. when it returns the balance operation has already completed. I tested btrfs-balance-status by faking the "out", both normal ones and malformed ones.> > > + lines = split_lines (out); > > + if (!lines) > > + return NULL; > > + > > + ret = malloc(sizeof *ret); > > + if (ret == NULL) { > > + reply_with_perror ("malloc"); > > + goto error; > > + } > > + memset (ret, 0, sizeof(*ret)); > > + > > + /* Output of `btrfs balance status' is like: > > + * > > + * running: > > + * > > + * Balance on '/' is running > > + * 3 out of about 8 chunks balanced (3 considered), 62% left > > + * > > + * paused: > > + * > > + * Balance on '/' is paused > > + * 3 out of about 8 chunks balanced (3 considered), 62% left > > + * > > + * no balance running: > > + * > > + * No Balance found on '/' > > + * > > + */ > > + if (strstr (lines[0], "No balance found on")) { > > In case the output of the btrfs command changes in future, you need to > check that the length of the lines[] array is >= 1 here, and >= 2 > below. Otherwise this code will segfault.Fixed. Also fixed in patch 2.> > > + ret->btrfsbalance_status = strdup("none"); > > Where you call strdup, you have to check that the return value is not > NULL, and if it is call reply_with_perror ("strdup").Fixed. Thank you for reviewing! Regards, Hu