Hu Tao
2014-Dec-12 07:03 UTC
[Libguestfs] [PATCH v3 00/11] btrfs support part2: qgroup/quota commands
Hi, This is v3 series to add support to btrfs qgroup related commands, inclduing quota commands, and two leftover of subvolume commands. Regards, Hu changes: v3: - don't intialize fs_buf (patch 1) - check the return value of sysroot_path (patch 1) - check fs_buf rather than fs (patch 1) - fprintf (stderr,...) -> reply_with_error() v2: - add tests for new APIs - combine btrfs_quota_enable and btrfs_quota_disable - following APIs changed to operate on Mountable_or_Path: btrfs_subvolume_get_default, btrfs_quota_enable, btrfs_quota_rescan. Hu Tao (11): daemon: btrfs: add helper functions mount and umount New API: btrfs_subvolume_get_default New API: btrfs_subvolume_show New API: btrfs_quota_enable New API: btrfs_quota_rescan New API: btrfs_qgroup_limit New API: btrfs_qgroup_create New API: btrfs_qgroup_destroy New API: btrfs_qgroup_show New API: btrfs_qgroup_assign New API: btrfs_qgroup_remove daemon/btrfs.c | 666 ++++++++++++++++++++++++++++--- generator/actions.ml | 203 ++++++++++ generator/structs.ml | 10 + 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, 837 insertions(+), 49 deletions(-) -- 1.9.3
Hu Tao
2014-Dec-12 07:03 UTC
[Libguestfs] [PATCH v3 01/11] daemon: btrfs: add helper functions mount and umount
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 106 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 754fdcd..514ba37 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -326,6 +326,58 @@ do_btrfs_subvolume_create (const char *dest, const char *qgroupid) return 0; } +static char +*mount (const mountable_t *fs) +{ + char *fs_buf; + + if (fs->type == MOUNTABLE_PATH) { + fs_buf = sysroot_path (fs->device); + if (fs_buf == NULL) + reply_with_perror ("malloc"); + } else { + fs_buf = strdup ("/tmp/btrfs.XXXXXX"); + if (fs_buf == NULL) { + reply_with_perror ("strdup"); + return NULL; + } + + if (mkdtemp (fs_buf) == NULL) { + reply_with_perror ("mkdtemp"); + free (fs_buf); + return NULL; + } + + if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) { + if (rmdir (fs_buf) == -1 && errno != ENOENT) + reply_with_error ("rmdir: %m\n"); + free (fs_buf); + return NULL; + } + } + + return fs_buf; +} + +static int +umount (char *fs_buf, const mountable_t *fs) +{ + if (fs->type != MOUNTABLE_PATH) { + CLEANUP_FREE char *err = NULL; + if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { + reply_with_error ("%s", err ? err : "malloc"); + return -1; + } + + if (rmdir (fs_buf) == -1 && errno != ENOENT) { + reply_with_error ("rmdir: %m\n"); + return -1; + } + } + free (fs_buf); + return 0; +} + guestfs_int_btrfssubvolume_list * do_btrfs_subvolume_list (const mountable_t *fs) { @@ -336,42 +388,10 @@ do_btrfs_subvolume_list (const mountable_t *fs) /* Execute 'btrfs subvolume list <fs>', and split the output into lines */ { - CLEANUP_FREE char *fs_buf = NULL; - - if (fs->type == MOUNTABLE_PATH) { - fs_buf = sysroot_path (fs->device); - if (fs_buf == NULL) { - reply_with_perror ("malloc"); - - cmderror: - if (fs->type != MOUNTABLE_PATH && fs_buf) { - CLEANUP_FREE char *err = NULL; - if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) - fprintf (stderr, "%s\n", err); - - if (rmdir (fs_buf) == -1 && errno != ENOENT) - fprintf (stderr, "rmdir: %m\n"); - } - return NULL; - } - } - - else { - fs_buf = strdup ("/tmp/btrfs.XXXXXX"); - if (fs_buf == NULL) { - reply_with_perror ("strdup"); - goto cmderror; - } + char *fs_buf = mount (fs); - if (mkdtemp (fs_buf) == NULL) { - reply_with_perror ("mkdtemp"); - goto cmderror; - } - - if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) { - goto cmderror; - } - } + if (!fs_buf) + return NULL; ADD_ARG (argv, i, str_btrfs); ADD_ARG (argv, i, "subvolume"); @@ -382,18 +402,8 @@ do_btrfs_subvolume_list (const mountable_t *fs) CLEANUP_FREE char *out = NULL, *errout = NULL; int r = commandv (&out, &errout, argv); - if (fs->type != MOUNTABLE_PATH) { - CLEANUP_FREE char *err = NULL; - if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { - reply_with_error ("%s", err ? err : "malloc"); - goto cmderror; - } - - if (rmdir (fs_buf) == -1 && errno != ENOENT) { - reply_with_error ("rmdir: %m\n"); - goto cmderror; - } - } + if (umount (fs_buf, fs) != 0) + return NULL; if (r == -1) { CLEANUP_FREE char *fs_desc = mountable_to_string (fs); @@ -401,7 +411,7 @@ do_btrfs_subvolume_list (const mountable_t *fs) fprintf (stderr, "malloc: %m"); } reply_with_error ("%s: %s", fs_desc ? fs_desc : "malloc", errout); - goto cmderror; + return NULL; } lines = split_lines (out); -- 1.9.3
Hu Tao
2014-Dec-12 07:03 UTC
[Libguestfs] [PATCH v3 02/11] New API: btrfs_subvolume_get_default
btrfs_subvolume_get_default is for getting the default subvolume of a btrfs filesystem. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 39 +++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 18 ++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 514ba37..bcd7a50 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -555,6 +555,45 @@ do_btrfs_subvolume_set_default (int64_t id, const char *fs) return 0; } +int64_t +do_btrfs_subvolume_get_default (const mountable_t *fs) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + int r; + int64_t ret = -1; + + fs_buf = mount (fs); + if (fs_buf == NULL) + goto error; + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "get-default"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", fs_buf, err); + goto error; + } + if (sscanf (out, "ID %" SCNi64, &ret) != 1) { + reply_with_error ("%s: could not parse subvolume id: %s.", argv[0], out); + ret = -1; + goto error; + } + +error: + if (fs_buf && umount (fs_buf, fs) != 0) + return -1; + return ret; +} + int do_btrfs_filesystem_sync (const char *fs) { diff --git a/generator/actions.ml b/generator/actions.ml index 4bd0788..df1be22 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12029,6 +12029,24 @@ Set readahead (in 512-byte sectors) for the device. This uses the L<blockdev(8)> command." }; + { defaults with + name = "btrfs_subvolume_get_default"; + style = RInt64 "id", [Mountable_or_Path "fs"], []; + proc_nr = Some 425; + optional = Some "btrfs"; camel_name = "BTRFSSubvolumeGetDefault"; + tests = [ + InitPartition, Always, TestResult ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["btrfs_subvolume_get_default"; "/dev/sda1"]], "ret > 0"), []; + InitPartition, Always, TestResult ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_subvolume_get_default"; "/"]], "ret > 0"), [] + ]; + shortdesc = "get the default subvolume or snapshot of a filesystem"; + longdesc = "\ +Get the default subvolume or snapshot of a filesystem mounted at C<mountpoint>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 9524ef4..5e4a522 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -424 +425 -- 1.9.3
btrfs_subvolume_show shows the detailed information of a subvolume or snapshot. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 25 +++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 220 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index bcd7a50..18722c8 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -24,11 +24,13 @@ #include <pcre.h> #include <string.h> #include <unistd.h> +#include <assert.h> #include "daemon.h" #include "actions.h" #include "optgroups.h" #include "xstrtol.h" +#include "c-ctype.h" GUESTFSD_EXT_CMD(str_btrfs, btrfs); GUESTFSD_EXT_CMD(str_btrfstune, btrfstune); @@ -821,3 +823,195 @@ do_btrfs_fsck (const char *device, int64_t superblock, int repair) return 0; } + +/* analyze_line: analyze one line contains key:value pair. + * returns the next position following \n. + */ +static char * +analyze_line (char *line, char **key, char **value) +{ + char *p = line; + char *next = NULL; + char delimiter = ':'; + char *del_pos = NULL; + + if (!line || *line == '\0') { + *key = NULL; + *value = NULL; + return NULL; + } + + next = strchr (p, '\n'); + if (next) { + *next = '\0'; + ++next; + } + + /* leading spaces and tabs */ + while (*p && c_isspace (*p)) + ++p; + + assert (key); + if (*p == delimiter) + *key = NULL; + else + *key = p; + + del_pos = strchr (p, delimiter); + if (del_pos) { + *del_pos = '\0'; + + /* leading spaces and tabs */ + do { + ++del_pos; + } while (*del_pos && c_isspace (*del_pos)); + assert (value); + *value = del_pos; + } else + *value = NULL; + + return next; +} + +char ** +do_btrfs_subvolume_show (const char *subvolume) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *subvolume_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + char *p, *key = NULL, *value = NULL; + DECLARE_STRINGSBUF (ret); + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "show"); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + return NULL; + } + + /* If the path is the btrfs root, `btrfs subvolume show' reports: + * <path> is btrfs root + */ + if (out && strstr (out, "is btrfs root") != NULL) { + reply_with_error ("%s is btrfs root", subvolume); + return NULL; + } + + /* If the path is a normal directory, `btrfs subvolume show' reports: + * ERROR: <path> is not a subvolume + */ + if (err && strstr (err, "is not a subvolume")) { + reply_with_error ("%s is not a subvolume", subvolume); + return NULL; + } + + /* Output is: + * + * / + * Name: root + * uuid: c875169e-cf4e-a04d-9959-b667dec36234 + * Parent uuid: - + * Creation time: 2014-11-13 10:13:08 + * Object ID: 256 + * Generation (Gen): 6579 + * Gen at creation: 5 + * Parent: 5 + * Top Level: 5 + * Flags: - + * Snapshot(s): + * snapshots/test1 + * snapshots/test2 + * snapshots/test3 + * + */ + p = analyze_line(out, &key, &value); + if (!p) { + reply_with_error ("truncated output: %s", out); + return NULL; + } + + /* The first line is the path of the subvolume. */ + if (key && !value) { + if (add_string (&ret, "path") == -1) + return NULL; + if (add_string (&ret, key) == -1) + return NULL; + } else { + if (add_string (&ret, key) == -1) + return NULL; + if (add_string (&ret, value) == -1) + return NULL; + } + + /* Read the lines and split into "key: value". */ + p = analyze_line(p, &key, &value); + while (key) { + /* snapshot is special, see the output above */ + if (STREQLEN (key, "Snapshot(s)", sizeof ("Snapshot(s)") - 1)) { + char *ss = NULL; + int ss_len = 0; + + if (add_string (&ret, key) == -1) + return NULL; + + p = analyze_line(p, &key, &value); + + while (key && !value) { + ss = realloc (ss, ss_len + strlen (key) + 1); + if (!ss) + return NULL; + + if (ss_len != 0) + ss[ss_len++] = ','; + + memcpy (ss + ss_len, key, strlen (key)); + ss_len += strlen (key); + ss[ss_len] = '\0'; + + p = analyze_line(p, &key, &value); + } + + if (ss) { + if (add_string_nodup (&ret, ss) == -1) { + free (ss); + return NULL; + } + } else { + if (add_string (&ret, "") == -1) + return NULL; + } + } else { + if (add_string (&ret, key ? key : "") == -1) + return NULL; + if (value && !STREQ(value, "-")) { + if (add_string (&ret, value) == -1) + return NULL; + } else { + if (add_string (&ret, "") == -1) + return NULL; + } + + p = analyze_line(p, &key, &value); + } + } + + if (end_stringsbuf (&ret) == -1) + return NULL; + + return ret.argv; +} diff --git a/generator/actions.ml b/generator/actions.ml index df1be22..cfd7472 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12047,6 +12047,31 @@ This uses the L<blockdev(8)> command." }; longdesc = "\ Get the default subvolume or snapshot of a filesystem mounted at C<mountpoint>." }; + { defaults with + name = "btrfs_subvolume_show"; + style = RHashtable "btrfssubvolumeinfo", [Pathname "subvolume"], []; + proc_nr = Some 426; + optional = Some "btrfs"; camel_name = "BTRFSSubvolumeShow"; + tests = [ + InitPartition, Always, TestLastFail ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_subvolume_show"; "/"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_subvolume_create"; "/sub1"; "NOARG"]; + ["btrfs_subvolume_show"; "/sub1"]]), []; + InitPartition, Always, TestLastFail ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["mkdir"; "/dir1"]; + ["btrfs_subvolume_show"; "/dir1"]]), []; + ]; + shortdesc = "return detailed information of the subvolume"; + longdesc = "\ +Return detailed information of the subvolume." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 5e4a522..9f51d08 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -425 +426 -- 1.9.3
btrfs_quota_enable enables or disables quota for btrfs filesystems. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 36 ++++++++++++++++++++++++++++++++++++ generator/actions.ml | 25 +++++++++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 18722c8..ee07e7e 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1015,3 +1015,39 @@ do_btrfs_subvolume_show (const char *subvolume) return ret.argv; } + +int +do_btrfs_quota_enable (const mountable_t *fs, int enable) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + int r = -1; + + fs_buf = mount (fs); + if (fs_buf == NULL) + goto error; + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "quota"); + if (enable) + ADD_ARG (argv, i, "enable"); + else + ADD_ARG (argv, i, "disable"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", fs_buf, err); + goto error; + } + +error: + if (fs_buf && umount (fs_buf, fs) != 0) + return -1; + return r; +} diff --git a/generator/actions.ml b/generator/actions.ml index cfd7472..d669b59 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12072,6 +12072,31 @@ Get the default subvolume or snapshot of a filesystem mounted at C<mountpoint>." longdesc = "\ Return detailed information of the subvolume." }; + { defaults with + name = "btrfs_quota_enable"; + style = RErr, [Mountable_or_Path "fs"; Bool "enable"], []; + proc_nr = Some 427; + optional = Some "btrfs"; camel_name = "BTRFSQuotaEnable"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["btrfs_quota_enable"; "/dev/sda1"; "true"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["btrfs_quota_enable"; "/dev/sda1"; "false"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "false"]]), []; + ]; + shortdesc = "enable or disable subvolume quota support"; + longdesc = "\ +Enable or disable subvolume quota support for filesystem which contains C<path>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 9f51d08..d2a1e59 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -426 +427 -- 1.9.3
btrfs_quota_rescan trashs all qgroup numbers and scans the metadata again with the current config. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 33 +++++++++++++++++++++++++++++++++ generator/actions.ml | 21 +++++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index ee07e7e..71229f1 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1051,3 +1051,36 @@ error: return -1; return r; } + +int +do_btrfs_quota_rescan (const mountable_t *fs) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + int r = -1; + + fs_buf = mount (fs); + if (fs_buf == NULL) + goto error; + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "quota"); + ADD_ARG (argv, i, "rescan"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", fs_buf, err); + goto error; + } + +error: + if (fs_buf && umount (fs_buf, fs) != 0) + return -1; + return r; +} diff --git a/generator/actions.ml b/generator/actions.ml index d669b59..3e5aab0 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12097,6 +12097,27 @@ Return detailed information of the subvolume." }; longdesc = "\ Enable or disable subvolume quota support for filesystem which contains C<path>." }; + { defaults with + name = "btrfs_quota_rescan"; + style = RErr, [Mountable_or_Path "fs"], []; + proc_nr = Some 428; + optional = Some "btrfs"; camel_name = "BTRFSQuotaRescan"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["btrfs_quota_enable"; "/dev/sda1"; "true"]; + ["btrfs_quota_rescan"; "/dev/sda1"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_quota_rescan"; "/"]]), []; + ]; + + shortdesc = "trash all qgroup numbers and scan the metadata again with the current config"; + longdesc = "\ +Trash all qgroup numbers and scan the metadata again with the current config." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index d2a1e59..43d371a 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -427 +428 -- 1.9.3
btrfs_qgroup_limit limits the size of a qgroup. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 35 +++++++++++++++++++++++++++++++++++ generator/actions.ml | 22 ++++++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 71229f1..01fd0cf 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1084,3 +1084,38 @@ error: return -1; return r; } + +int +do_btrfs_qgroup_limit (const char *subvolume, int64_t size) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *subvolume_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + char size_str[32]; + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "qgroup"); + ADD_ARG (argv, i, "limit"); + snprintf (size_str, sizeof size_str, "%" PRIi64, size); + ADD_ARG (argv, i, size_str); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 3e5aab0..6352851 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12118,6 +12118,28 @@ Enable or disable subvolume quota support for filesystem which contains C<path>. longdesc = "\ Trash all qgroup numbers and scan the metadata again with the current config." }; + { defaults with + name = "btrfs_qgroup_limit"; + style = RErr, [Pathname "subvolume"; Int64 "size"], []; + proc_nr = Some 429; + optional = Some "btrfs"; camel_name = "BTRFSQgroupLimit"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_qgroup_limit"; "/"; "10737418240"]]), []; + InitPartition, Always, TestLastFail ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "false"]; + ["btrfs_qgroup_limit"; "/"; "10737418240"]]), []; + ]; + shortdesc = "limit the size of a subvolume"; + longdesc = "\ +Limit the size of a subvolume which's path is C<subvolume>. C<size> +can have suffix of G, M, or K. " }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 43d371a..3560666 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -428 +429 -- 1.9.3
btrfs_qgroup_create creates a new qgroup. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 33 +++++++++++++++++++++++++++++++++ generator/actions.ml | 17 +++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 01fd0cf..89a7ddc 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1119,3 +1119,36 @@ do_btrfs_qgroup_limit (const char *subvolume, int64_t size) return 0; } + +int +do_btrfs_qgroup_create (const char *qgroupid, const char *subvolume) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *subvolume_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "qgroup"); + ADD_ARG (argv, i, "create"); + ADD_ARG (argv, i, qgroupid); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 6352851..a44d939 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12140,6 +12140,23 @@ Trash all qgroup numbers and scan the metadata again with the current config." } Limit the size of a subvolume which's path is C<subvolume>. C<size> can have suffix of G, M, or K. " }; + { defaults with + name = "btrfs_qgroup_create"; + style = RErr, [String "qgroupid"; Pathname "subvolume"], []; + proc_nr = Some 430; + optional = Some "btrfs"; camel_name = "BTRFSQgroupCreate"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_subvolume_create"; "/sub1"; "NOARG"]; + ["btrfs_qgroup_create"; "0/1000"; "/sub1"]]), []; + ]; + shortdesc = "create a subvolume quota group"; + longdesc = "\ +Create a quota group (qgroup) for subvolume at C<subvolume>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 3560666..c15fb93 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -429 +430 -- 1.9.3
btrfs_qgroup_destroy destroys a qgroup. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 33 +++++++++++++++++++++++++++++++++ generator/actions.ml | 18 ++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 89a7ddc..c38a4b5 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1152,3 +1152,36 @@ do_btrfs_qgroup_create (const char *qgroupid, const char *subvolume) return 0; } + +int +do_btrfs_qgroup_destroy (const char *qgroupid, const char *subvolume) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *subvolume_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "qgroup"); + ADD_ARG (argv, i, "destroy"); + ADD_ARG (argv, i, qgroupid); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index a44d939..c3294b3 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12157,6 +12157,24 @@ can have suffix of G, M, or K. " }; longdesc = "\ Create a quota group (qgroup) for subvolume at C<subvolume>." }; + { defaults with + name = "btrfs_qgroup_destroy"; + style = RErr, [String "qgroupid"; Pathname "subvolume"], []; + proc_nr = Some 431; + optional = Some "btrfs"; camel_name = "BTRFSQgroupDestroy"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_subvolume_create"; "/sub1"; "NOARG"]; + ["btrfs_qgroup_create"; "0/1000"; "/sub1"]; + ["btrfs_qgroup_destroy"; "0/1000"; "/sub1"]]), []; + ]; + shortdesc = "destroy a subvolume quota group"; + longdesc = "\ +Destroy a quota group." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index c15fb93..ed4f162 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -430 +431 -- 1.9.3
btrfs_qgroup_show shows all qgroups on a btrfs filesystem. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 89 ++++++++++++++++++++++++++++++++ generator/actions.ml | 19 +++++++ generator/structs.ml | 10 ++++ 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, 124 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index c38a4b5..cde84fe 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1185,3 +1185,92 @@ do_btrfs_qgroup_destroy (const char *qgroupid, const char *subvolume) return 0; } + +guestfs_int_btrfsqgroup_list * +do_btrfs_qgroup_show (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; + CLEANUP_FREE char *out = NULL; + int r; + char **lines; + + 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, "qgroup"); + ADD_ARG (argv, i, "show"); + 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; + + /* line 0 and 1 are: + * + * qgroupid rfer excl + * -------- ---- ---- + */ + size_t nr_qgroups = count_strings (lines) - 2; + guestfs_int_btrfsqgroup_list *ret = NULL; + ret = malloc (sizeof *ret); + if (!ret) { + reply_with_perror ("malloc"); + goto error; + } + + ret->guestfs_int_btrfsqgroup_list_len = nr_qgroups; + ret->guestfs_int_btrfsqgroup_list_val + calloc (nr_qgroups, sizeof (struct guestfs_int_btrfsqgroup)); + if (ret->guestfs_int_btrfsqgroup_list_val == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + for (i = 0; i < nr_qgroups; ++i) { + char *line = lines[i + 2]; + struct guestfs_int_btrfsqgroup *this + &ret->guestfs_int_btrfsqgroup_list_val[i]; + uint64_t dummy1, dummy2; + char *p; + + if (sscanf (line, "%" SCNu64 "/%" SCNu64 " %" SCNu64 " %" SCNu64, + &dummy1, &dummy2, &this->btrfsqgroup_rfer, + &this->btrfsqgroup_excl) != 4) { + reply_with_perror ("sscanf"); + goto error; + } + p = strchr(line, ' '); + if (!p) { + reply_with_error ("truncated line: %s", line); + goto error; + } + *p = '\0'; + this->btrfsqgroup_id = line; + } + + free (lines); + return ret; + +error: + free_stringslen (lines, nr_qgroups + 2); + if (ret) + free (ret->guestfs_int_btrfsqgroup_list_val); + free (ret); + + return NULL; +} diff --git a/generator/actions.ml b/generator/actions.ml index c3294b3..8a03000 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12175,6 +12175,25 @@ Create a quota group (qgroup) for subvolume at C<subvolume>." }; longdesc = "\ Destroy a quota group." }; + { defaults with + name = "btrfs_qgroup_show"; + style = RStructList ("qgroups", "btrfsqgroup"), [Pathname "path"], []; + proc_nr = Some 432; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_subvolume_create"; "/sub1"; "NOARG"]; + ["btrfs_qgroup_create"; "0/1000"; "/sub1"]; + ["btrfs_qgroup_show"; "/"]]), []; + ]; + optional = Some "btrfs"; camel_name = "BTRFSQgroupShow"; + shortdesc = "show subvolume quota groups"; + longdesc = "\ +Show all subvolume quota groups in a btrfs filesystem, inclding their +usages." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/generator/structs.ml b/generator/structs.ml index 578ebb7..df3ff47 100644 --- a/generator/structs.ml +++ b/generator/structs.ml @@ -330,6 +330,16 @@ let structs = [ ]; s_camel_name = "BTRFSSubvolume" }; + (* btrfs qgroup show output *) + { defaults with + s_name = "btrfsqgroup"; + s_cols = [ + "btrfsqgroup_id", FString; + "btrfsqgroup_rfer", FUInt64; + "btrfsqgroup_excl", FUInt64; + ]; + s_camel_name = "BTRFSQgroup" }; + (* XFS info descriptor. *) { defaults with s_name = "xfsinfo"; diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index 218eef7..91c4ea6 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-btrfsqgroup.h \ include/guestfs-gobject/struct-btrfssubvolume.h \ include/guestfs-gobject/struct-dirent.h \ include/guestfs-gobject/struct-hivex_node.h \ @@ -106,6 +107,7 @@ guestfs_gobject_sources= \ src/tristate.c \ src/struct-application.c \ src/struct-application2.c \ + src/struct-btrfsqgroup.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 614caaa..34938fb 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/BTRFSQgroup.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 4882c96..1d4accc 100644 --- a/java/com/redhat/et/libguestfs/.gitignore +++ b/java/com/redhat/et/libguestfs/.gitignore @@ -1,5 +1,6 @@ Application.java Application2.java +BTRFSQgroup.java BTRFSSubvolume.java Dirent.java HivexNode.java diff --git a/po/POTFILES b/po/POTFILES index a8e211f..57a8153 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -229,6 +229,7 @@ gobject/src/optargs-xfs_repair.c gobject/src/session.c gobject/src/struct-application.c gobject/src/struct-application2.c +gobject/src/struct-btrfsqgroup.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 ed4f162..84796bf 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -431 +432 -- 1.9.3
btrfs_qgroup_assign adds a qgroup to a parent qgroup. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 34 ++++++++++++++++++++++++++++++++++ generator/actions.ml | 19 +++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index cde84fe..7bb1ca0 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1274,3 +1274,37 @@ error: return NULL; } + +int +do_btrfs_qgroup_assign (const char *src, const char *dst, 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; + CLEANUP_FREE char *out = NULL; + int r; + + path_buf = sysroot_path (path); + if (path_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "qgroup"); + ADD_ARG (argv, i, "assign"); + ADD_ARG (argv, i, src); + ADD_ARG (argv, i, dst); + 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 -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 8a03000..67cd7ab 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12194,6 +12194,25 @@ Destroy a quota group." }; Show all subvolume quota groups in a btrfs filesystem, inclding their usages." }; + { defaults with + name = "btrfs_qgroup_assign"; + style = RErr, [String "src"; String "dst"; Pathname "path"], []; + proc_nr = Some 433; + optional = Some "btrfs"; camel_name = "BTRFSQgroupAssign"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_qgroup_create"; "0/1000"; "/"]; + ["btrfs_qgroup_create"; "1/1000"; "/"]; + ["btrfs_qgroup_assign"; "0/1000"; "1/1000"; "/"]]), []; + ]; + shortdesc = "add a qgroup to a parent qgroup"; + longdesc = "\ +Add qgroup C<src> to parent qgroup C<dst>. This command can group +several qgroups into a parent qgroup to share common limit." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 84796bf..21fbd2e 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -432 +433 -- 1.9.3
btrfs_qgroup_remove removes a qgroup from its parent qgroup. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- daemon/btrfs.c | 34 ++++++++++++++++++++++++++++++++++ generator/actions.ml | 19 +++++++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 7bb1ca0..2304a72 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -1308,3 +1308,37 @@ do_btrfs_qgroup_assign (const char *src, const char *dst, const char *path) return 0; } + +int +do_btrfs_qgroup_remove (const char *src, const char *dst, 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; + CLEANUP_FREE char *out = NULL; + int r; + + path_buf = sysroot_path (path); + if (path_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "qgroup"); + ADD_ARG (argv, i, "remove"); + ADD_ARG (argv, i, src); + ADD_ARG (argv, i, dst); + 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 -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 67cd7ab..5be9441 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12213,6 +12213,25 @@ usages." }; Add qgroup C<src> to parent qgroup C<dst>. This command can group several qgroups into a parent qgroup to share common limit." }; + { defaults with + name = "btrfs_qgroup_remove"; + style = RErr, [String "src"; String "dst"; Pathname "path"], []; + proc_nr = Some 434; + optional = Some "btrfs"; camel_name = "BTRFSQgroupRemove"; + tests = [ + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_quota_enable"; "/"; "true"]; + ["btrfs_qgroup_create"; "0/1000"; "/"]; + ["btrfs_qgroup_create"; "1/1000"; "/"]; + ["btrfs_qgroup_assign"; "0/1000"; "1/1000"; "/"]; + ["btrfs_qgroup_remove"; "0/1000"; "1/1000"; "/"]]), []; + ]; + shortdesc = "remove a qgroup from its parent qgroup"; + longdesc = "\ +Remove qgroup C<src> from the parent qgroup C<dst>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 21fbd2e..e828e5d 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -433 +434 -- 1.9.3
Richard W.M. Jones
2014-Dec-12 16:41 UTC
Re: [Libguestfs] [PATCH v3 00/11] btrfs support part2: qgroup/quota commands
On Fri, Dec 12, 2014 at 03:03:22PM +0800, Hu Tao wrote:> Hi, > > This is v3 series to add support to btrfs qgroup related commands, inclduing > quota commands, and two leftover of subvolume commands.I really need to look at this in detail next week, especially the mount/umount helper functions in patch 01. However I did run the test suite, and it did pass, so that's a good sign. 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/
Hu Tao
2014-Dec-15 02:17 UTC
Re: [Libguestfs] [PATCH v3 00/11] btrfs support part2: qgroup/quota commands
On Fri, Dec 12, 2014 at 04:41:44PM +0000, Richard W.M. Jones wrote:> On Fri, Dec 12, 2014 at 03:03:22PM +0800, Hu Tao wrote: > > Hi, > > > > This is v3 series to add support to btrfs qgroup related commands, inclduing > > quota commands, and two leftover of subvolume commands. > > I really need to look at this in detail next week, especially the > mount/umount helper functions in patch 01.No problem!> > However I did run the test suite, and it did pass, so that's a good sign.Good. Thanks for testing! Regards, Hu> > 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
2014-Dec-15 16:46 UTC
Re: [Libguestfs] [PATCH v3 01/11] daemon: btrfs: add helper functions mount and umount
On Fri, Dec 12, 2014 at 03:03:23PM +0800, Hu Tao wrote:> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > daemon/btrfs.c | 106 +++++++++++++++++++++++++++++++-------------------------- > 1 file changed, 58 insertions(+), 48 deletions(-) > > diff --git a/daemon/btrfs.c b/daemon/btrfs.c > index 754fdcd..514ba37 100644 > --- a/daemon/btrfs.c > +++ b/daemon/btrfs.c > + if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) { > + if (rmdir (fs_buf) == -1 && errno != ENOENT) > + reply_with_error ("rmdir: %m\n");This error path calls reply_with_error twice (the first time in mount_vfs_nochroot). That's a problem because it would cause protocol desychronization. [...]> + if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { > + reply_with_error ("%s", err ? err : "malloc"); > + return -1; > + }'err' is always non-NULL here. There's no need to send an updated patch, as I'm just going to change this to an fprintf statement before I push it (very soon). Thanks, Rich.> + if (rmdir (fs_buf) == -1 && errno != ENOENT) { > + reply_with_error ("rmdir: %m\n"); > + return -1; > + } > + } > + free (fs_buf); > + return 0; > +} > + > guestfs_int_btrfssubvolume_list * > do_btrfs_subvolume_list (const mountable_t *fs) > { > @@ -336,42 +388,10 @@ do_btrfs_subvolume_list (const mountable_t *fs) > > /* Execute 'btrfs subvolume list <fs>', and split the output into lines */ > { > - CLEANUP_FREE char *fs_buf = NULL; > - > - if (fs->type == MOUNTABLE_PATH) { > - fs_buf = sysroot_path (fs->device); > - if (fs_buf == NULL) { > - reply_with_perror ("malloc"); > - > - cmderror: > - if (fs->type != MOUNTABLE_PATH && fs_buf) { > - CLEANUP_FREE char *err = NULL; > - if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) > - fprintf (stderr, "%s\n", err); > - > - if (rmdir (fs_buf) == -1 && errno != ENOENT) > - fprintf (stderr, "rmdir: %m\n"); > - } > - return NULL; > - } > - } > - > - else { > - fs_buf = strdup ("/tmp/btrfs.XXXXXX"); > - if (fs_buf == NULL) { > - reply_with_perror ("strdup"); > - goto cmderror; > - } > + char *fs_buf = mount (fs); > > - if (mkdtemp (fs_buf) == NULL) { > - reply_with_perror ("mkdtemp"); > - goto cmderror; > - } > - > - if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) { > - goto cmderror; > - } > - } > + if (!fs_buf) > + return NULL; > > ADD_ARG (argv, i, str_btrfs); > ADD_ARG (argv, i, "subvolume"); > @@ -382,18 +402,8 @@ do_btrfs_subvolume_list (const mountable_t *fs) > CLEANUP_FREE char *out = NULL, *errout = NULL; > int r = commandv (&out, &errout, argv); > > - if (fs->type != MOUNTABLE_PATH) { > - CLEANUP_FREE char *err = NULL; > - if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { > - reply_with_error ("%s", err ? err : "malloc"); > - goto cmderror; > - } > - > - if (rmdir (fs_buf) == -1 && errno != ENOENT) { > - reply_with_error ("rmdir: %m\n"); > - goto cmderror; > - } > - } > + if (umount (fs_buf, fs) != 0) > + return NULL; > > if (r == -1) { > CLEANUP_FREE char *fs_desc = mountable_to_string (fs); > @@ -401,7 +411,7 @@ do_btrfs_subvolume_list (const mountable_t *fs) > fprintf (stderr, "malloc: %m"); > } > reply_with_error ("%s: %s", fs_desc ? fs_desc : "malloc", errout); > - goto cmderror; > + return NULL; > } > > lines = split_lines (out); > -- > 1.9.3 > > _______________________________________________ > 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 Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Pino Toscano
2014-Dec-16 13:20 UTC
Re: [Libguestfs] [PATCH v3 01/11] daemon: btrfs: add helper functions mount and umount
In data venerdì 12 dicembre 2014 15:03:23, Hu Tao ha scritto:> +static int > +umount (char *fs_buf, const mountable_t *fs) > +{ > + if (fs->type != MOUNTABLE_PATH) { > + CLEANUP_FREE char *err = NULL; > + if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) { > + reply_with_error ("%s", err ? err : "malloc"); > + return -1; > + } > + > + if (rmdir (fs_buf) == -1 && errno != ENOENT) { > + reply_with_error ("rmdir: %m\n"); > + return -1; > + } > + } > + free (fs_buf); > + return 0; > +}The only issue with umount is that it does not free fs_buf properly in all the return paths (e.g. when command or rmdir fail). IMHO it'd be better to leave the ownership of that buffer to whatever calls umount (using CLEANUP_FREE to ease that). -- Pino Toscano
Possibly Parallel Threads
- [PATCH v2 01/11] daemon: btrfs: add helper functions mount and umount
- Re: [PATCH v2 01/11] daemon: btrfs: add helper functions mount and umount
- [PATCH v2 15/23] daemon: Reimplement ‘btrfs_subvolume_list’ and ‘btrfs_subvolume_get_default’ in OCaml.
- [PATCH 18/27] daemon: Reimplement ‘btrfs_subvolume_list’ and ‘btrfs_subvolume_get_default’ in OCaml.
- [PATCH v3 00/11] btrfs support part2: qgroup/quota commands