diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-04-25 16:35:12 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-04-25 17:32:30 +0100 |
commit | 87ea7a04094d5ed40f3f047ff2b7a613d4d530d4 (patch) | |
tree | 458b3713c313d124c37b8de11e45d0b081f3fde6 /daemon | |
parent | 3cc9703f901e85a589692b9d0bf5ef7cbf72ed73 (diff) | |
download | libguestfs-87ea7a04094d5ed40f3f047ff2b7a613d4d530d4.tar.gz libguestfs-87ea7a04094d5ed40f3f047ff2b7a613d4d530d4.tar.xz libguestfs-87ea7a04094d5ed40f3f047ff2b7a613d4d530d4.zip |
New btrfs APIs.
Bind the easy parts of the 'btrfs' program.
The new APIs are:
btrfs-device-add: add devices to a btrfs filesystem
btrfs-device-delete: remove devices from a btrfs filesystem
btrfs-filesystem-sync: sync a btrfs filesystem
btrfs-filesystem-balance: balance a btrfs filesystem
btrfs-subvolume-create: create a btrfs snapshot
btrfs-subvolume-delete: delete a btrfs snapshot
btrfs-subvolume-list: list btrfs snapshots and subvolumes
btrfs-subvolume-set-default: set default btrfs subvolume
btrfs-subvolume-snapshot: create a writable btrfs snapshot
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/btrfs.c | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 60c863a4..8569173e 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -202,3 +202,399 @@ do_mkfs_btrfs (char *const *devices, free (err); return 0; } + +int +do_btrfs_subvolume_snapshot (const char *source, const char *dest) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *source_buf, *dest_buf; + char *err; + int r; + + source_buf = sysroot_path (source); + if (source_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + dest_buf = sysroot_path (dest); + if (dest_buf == NULL) { + reply_with_perror ("malloc"); + free (source_buf); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "snapshot"); + ADD_ARG (argv, i, source_buf); + ADD_ARG (argv, i, dest_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (source_buf); + free (dest_buf); + if (r == -1) { + reply_with_error ("%s: %s: %s", source, dest, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_subvolume_delete (const char *subvolume) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *subvolume_buf; + char *err; + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "delete"); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (subvolume_buf); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_subvolume_create (const char *dest) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *dest_buf; + char *err; + int r; + + dest_buf = sysroot_path (dest); + if (dest_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "create"); + ADD_ARG (argv, i, dest_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (dest_buf); + if (r == -1) { + reply_with_error ("%s: %s", dest, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +guestfs_int_btrfssubvolume_list * +do_btrfs_subvolume_list (const char *fs) +{ + const size_t MAX_ARGS = 64; + guestfs_int_btrfssubvolume_list *ret; + char *fs_buf; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *out, *err, **lines, *pos; + size_t nr_subvolumes; + int r; + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "list"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return NULL; + } + free (err); + + lines = split_lines (out); + free (out); + if (!lines) + return NULL; + + /* Output is: + * + * ID 256 top level 5 path test1 + * ID 257 top level 5 path dir/test2 + * ID 258 top level 5 path test3 + * + * "ID <n>" is the subvolume ID. "top level <n>" is the top level + * subvolume ID. "path <str>" is the subvolume path, relative to + * the top of the filesystem. + */ + nr_subvolumes = count_strings (lines); + + ret = malloc (sizeof *ret); + if (!ret) { + reply_with_perror ("malloc"); + free_stringslen (lines, nr_subvolumes); + return NULL; + } + ret->guestfs_int_btrfssubvolume_list_len = nr_subvolumes; + ret->guestfs_int_btrfssubvolume_list_val = + calloc (nr_subvolumes, sizeof (struct guestfs_int_btrfssubvolume)); + if (ret->guestfs_int_btrfssubvolume_list_val == NULL) { + reply_with_perror ("malloc"); + free (ret); + free_stringslen (lines, nr_subvolumes); + return NULL; + } + + for (i = 0; i < nr_subvolumes; ++i) { + /* To avoid allocations, reuse the 'line' buffer to store the + * path. Thus we don't need to free 'line', since it will be + * freed by the calling (XDR) code. + */ + char *line = lines[i]; + + if (sscanf (line, "ID %" SCNu64 " top level %" SCNu64 " path ", + &ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_id, + &ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_top_level_id) != 2) { + unexpected_output: + reply_with_error ("unexpected output from 'btrfs subvolume list' command: %s", line); + free_stringslen (lines, nr_subvolumes); + free (ret->guestfs_int_btrfssubvolume_list_val); + free (ret); + return NULL; + } + + pos = strstr (line, " path "); + if (pos == NULL) + goto unexpected_output; + pos += 6; + + memmove (line, pos, strlen (pos) + 1); + ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_path = line; + } + + return ret; +} + +int +do_btrfs_subvolume_set_default (int64_t id, const char *fs) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf; + char buf[64]; + char *err; + int r; + + snprintf (buf, sizeof buf, "%" PRIi64, id); + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "set-default"); + ADD_ARG (argv, i, buf); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_filesystem_sync (const char *fs) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf; + char *err; + int r; + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "filesystem"); + ADD_ARG (argv, i, "sync"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_filesystem_balance (const char *fs) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + char *fs_buf; + char *err; + int r; + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "filesystem"); + ADD_ARG (argv, i, "balance"); + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_device_add (char *const *devices, const char *fs) +{ + size_t nr_devices = count_strings (devices); + + if (nr_devices == 0) + return 0; + + size_t MAX_ARGS = nr_devices + 8; + const char *argv[MAX_ARGS]; + size_t i = 0, j; + char *fs_buf; + char *err; + int r; + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "device"); + ADD_ARG (argv, i, "add"); + + for (j = 0; j < nr_devices; ++j) + ADD_ARG (argv, i, devices[j]); + + ADD_ARG (argv, i, fs_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return -1; + } + free (err); + + return 0; +} + +int +do_btrfs_device_delete (char *const *devices, const char *fs) +{ + size_t nr_devices = count_strings (devices); + + if (nr_devices == 0) + return 0; + + size_t MAX_ARGS = nr_devices + 8; + const char *argv[MAX_ARGS]; + size_t i = 0, j; + char *fs_buf; + char *err; + int r; + + fs_buf = sysroot_path (fs); + if (fs_buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + ADD_ARG (argv, i, "btrfs"); + ADD_ARG (argv, i, "device"); + ADD_ARG (argv, i, "delete"); + for (j = 0; j < nr_devices; ++j) + ADD_ARG (argv, i, devices[j]); + ADD_ARG (argv, i, fs); + ADD_ARG (argv, i, NULL); + + r = commandv (NULL, &err, argv); + free (fs_buf); + if (r == -1) { + reply_with_error ("%s: %s", fs, err); + free (err); + return -1; + } + free (err); + + return 0; +} |