diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 438c72020..1b76d8c34 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1659,3 +1659,129 @@ 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; + size_t nlines; + 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; + + nlines = count_strings (lines); + + 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 (nlines < 1) { + reply_with_perror ("No balance status output"); + return NULL; + } + + if (strstr (lines[0], "No balance found on")) { + ret->btrfsbalance_status = strdup("none"); + if (ret->btrfsbalance_status == NULL) { + reply_with_perror ("strdup"); + return NULL; + } + 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 (nlines < 2) { + reply_with_error ("truncated output from 'btrfs balance status' command"); + 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 8fe7d744f..6b13c5d8a 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12449,6 +12449,16 @@ valid GUID." }; longdesc = "\ Return the GUID of numbered GPT partition C." }; +{ defaults with + name = "btrfs_balance_status"; + style = RStruct ("status", "btrfsbalance"), [Pathname "path"], []; + proc_nr = Some 448; + 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 5b466a2e5..af42529a3 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 e0c0a5f41..3ce10f953 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 103010f6d..499d3deb8 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 1d4accca0..b2b1b2220 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 6e65377b8..3f66c9ffe 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 e9b7520bd..5379c470d 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -447 +448