mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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
This commit is contained in:
@@ -42,6 +42,7 @@ SUBDIRS += tests/lvm
|
||||
SUBDIRS += tests/luks
|
||||
SUBDIRS += tests/md
|
||||
SUBDIRS += tests/ntfsclone
|
||||
SUBDIRS += tests/btrfs
|
||||
SUBDIRS += tests/regressions
|
||||
endif
|
||||
|
||||
|
||||
@@ -1229,6 +1229,7 @@ AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
sysprep/Makefile
|
||||
test-tool/Makefile
|
||||
tests/btrfs/Makefile
|
||||
tests/c-api/Makefile
|
||||
tests/data/Makefile
|
||||
tests/extra/Makefile
|
||||
|
||||
396
daemon/btrfs.c
396
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;
|
||||
}
|
||||
|
||||
@@ -7136,6 +7136,89 @@ This sets the ext2 file generation of a file.
|
||||
|
||||
See C<guestfs_get_e2generation>.");
|
||||
|
||||
("btrfs_subvolume_snapshot", (RErr, [Pathname "source"; Pathname "dest"], []), 322, [Optional "btrfs"; CamelName "BTRFSSubvolumeSnapshot"],
|
||||
[InitPartition, IfAvailable "btrfs", TestRun (
|
||||
[["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""];
|
||||
["mount"; "/dev/sda1"; "/"];
|
||||
["mkdir"; "/dir"];
|
||||
["btrfs_subvolume_create"; "/test1"];
|
||||
["btrfs_subvolume_create"; "/test2"];
|
||||
["btrfs_subvolume_create"; "/dir/test3"];
|
||||
["btrfs_subvolume_snapshot"; "/dir/test3"; "/dir/test4"]])],
|
||||
"create a writable btrfs snapshot",
|
||||
"\
|
||||
Create a writable snapshot of the btrfs subvolume C<source>.
|
||||
The C<dest> argument is the destination directory and the name
|
||||
of the snapshot, in the form C</path/to/dest/name>.");
|
||||
|
||||
("btrfs_subvolume_delete", (RErr, [Pathname "subvolume"], []), 323, [Optional "btrfs"; CamelName "BTRFSSubvolumeDelete"],
|
||||
[InitPartition, IfAvailable "btrfs", TestRun (
|
||||
[["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""];
|
||||
["mount"; "/dev/sda1"; "/"];
|
||||
["btrfs_subvolume_create"; "/test1"];
|
||||
["btrfs_subvolume_delete"; "/test1"]])],
|
||||
"delete a btrfs snapshot",
|
||||
"\
|
||||
Delete the named btrfs subvolume.");
|
||||
|
||||
("btrfs_subvolume_create", (RErr, [Pathname "dest"], []), 324, [Optional "btrfs"; CamelName "BTRFSSubvolumeCreate"],
|
||||
[], (* tested above *)
|
||||
"create a btrfs snapshot",
|
||||
"\
|
||||
Create a btrfs subvolume. The C<dest> argument is the destination
|
||||
directory and the name of the snapshot, in the form C</path/to/dest/name>.");
|
||||
|
||||
("btrfs_subvolume_list", (RStructList ("subvolumes", "btrfssubvolume"), [Pathname "fs"], []), 325, [Optional "btrfs"; CamelName "BTRFSSubvolumeList"],
|
||||
[], (* tested in tests/btrfs *)
|
||||
"list btrfs snapshots and subvolumes",
|
||||
"\
|
||||
List the btrfs snapshots and subvolumes of the btrfs filesystem
|
||||
which is mounted at C<fs>.");
|
||||
|
||||
("btrfs_subvolume_set_default", (RErr, [Int64 "id"; Pathname "fs"], []), 326, [Optional "btrfs"; CamelName "BTRFSSubvolumeSetDefault"],
|
||||
[], (* tested in tests/btrfs *)
|
||||
"set default btrfs subvolume",
|
||||
"\
|
||||
Set the subvolume of the btrfs filesystem C<fs> which will
|
||||
be mounted by default. See <guestfs_btrfs_subvolume_list> to
|
||||
get a list of subvolumes.");
|
||||
|
||||
("btrfs_filesystem_sync", (RErr, [Pathname "fs"], []), 327, [Optional "btrfs"; CamelName "BTRFSFilesystemSync"],
|
||||
[InitPartition, IfAvailable "btrfs", TestRun (
|
||||
[["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""];
|
||||
["mount"; "/dev/sda1"; "/"];
|
||||
["btrfs_subvolume_create"; "/test1"];
|
||||
["btrfs_filesystem_sync"; "/test1"];
|
||||
["btrfs_filesystem_balance"; "/test1"]])],
|
||||
"sync a btrfs filesystem",
|
||||
"\
|
||||
Force sync on the btrfs filesystem mounted at C<fs>.");
|
||||
|
||||
("btrfs_filesystem_balance", (RErr, [Pathname "fs"], []), 328, [Optional "btrfs"; CamelName "BTRFSFilesystemBalance"],
|
||||
[], (* tested above *)
|
||||
"balance a btrfs filesystem",
|
||||
"\
|
||||
Balance the chunks in the btrfs filesystem mounted at C<fs>
|
||||
across the underlying devices.");
|
||||
|
||||
("btrfs_device_add", (RErr, [DeviceList "devices"; Pathname "fs"], []), 329, [Optional "btrfs"; CamelName "BTRFSDeviceAdd"],
|
||||
[], (* test disk isn't large enough to test this thoroughly, so there
|
||||
* is an external test in 'tests/btrfs' directory.
|
||||
*)
|
||||
"add devices to a btrfs filesystem",
|
||||
"\
|
||||
Add the list of device(s) in C<devices> to the btrfs filesystem
|
||||
mounted at C<fs>. If C<devices> is an empty list, this does nothing.");
|
||||
|
||||
("btrfs_device_delete", (RErr, [DeviceList "devices"; Pathname "fs"], []), 330, [Optional "btrfs"; CamelName "BTRFSDeviceDelete"],
|
||||
[], (* test disk isn't large enough to test this thoroughly, so there
|
||||
* is an external test in 'tests/btrfs' directory.
|
||||
*)
|
||||
"remove devices from a btrfs filesystem",
|
||||
"\
|
||||
Remove the C<devices> from the btrfs filesystem mounted at C<fs>.
|
||||
If C<devices> is an empty list, this does nothing.");
|
||||
|
||||
]
|
||||
|
||||
let all_functions = non_daemon_functions @ daemon_functions
|
||||
|
||||
@@ -219,6 +219,13 @@ let structs = [
|
||||
"mdstat_index", FInt32;
|
||||
"mdstat_flags", FString;
|
||||
];
|
||||
|
||||
(* btrfs subvolume list output *)
|
||||
"btrfssubvolume", [
|
||||
"btrfssubvolume_id", FUInt64;
|
||||
"btrfssubvolume_top_level_id", FUInt64;
|
||||
"btrfssubvolume_path", FString;
|
||||
];
|
||||
] (* end of structs *)
|
||||
|
||||
(* For bindings which want camel case *)
|
||||
@@ -237,6 +244,7 @@ let camel_structs = [
|
||||
"application", "Application";
|
||||
"isoinfo", "ISOInfo";
|
||||
"mdstat", "MDStat";
|
||||
"btrfssubvolume", "BTRFSSubvolume";
|
||||
]
|
||||
let camel_structs = List.sort (fun (_,a) (_,b) -> compare a b) camel_structs
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ guestfs_gobject_headers=\
|
||||
guestfs-gobject-struct-application.h \
|
||||
guestfs-gobject-struct-isoinfo.h \
|
||||
guestfs-gobject-struct-mdstat.h \
|
||||
guestfs-gobject-struct-btrfssubvolume.h \
|
||||
guestfs-gobject-optargs-test0.h \
|
||||
guestfs-gobject-optargs-add_drive_opts.h \
|
||||
guestfs-gobject-optargs-add_domain.h \
|
||||
@@ -78,6 +79,7 @@ guestfs_gobject_sources=\
|
||||
guestfs-gobject-struct-application.c \
|
||||
guestfs-gobject-struct-isoinfo.c \
|
||||
guestfs-gobject-struct-mdstat.c \
|
||||
guestfs-gobject-struct-btrfssubvolume.c \
|
||||
guestfs-gobject-optargs-test0.c \
|
||||
guestfs-gobject-optargs-add_drive_opts.c \
|
||||
guestfs-gobject-optargs-add_domain.c \
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
java_built_sources = \
|
||||
com/redhat/et/libguestfs/Application.java \
|
||||
com/redhat/et/libguestfs/BTRFSSubvolume.java \
|
||||
com/redhat/et/libguestfs/Dirent.java \
|
||||
com/redhat/et/libguestfs/INotifyEvent.java \
|
||||
com/redhat/et/libguestfs/ISOInfo.java \
|
||||
|
||||
1
java/com/redhat/et/libguestfs/.gitignore
vendored
1
java/com/redhat/et/libguestfs/.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
Application.java
|
||||
BTRFSSubvolume.java
|
||||
Dirent.java
|
||||
INotifyEvent.java
|
||||
ISOInfo.java
|
||||
|
||||
@@ -156,6 +156,7 @@ gobject/guestfs-gobject-optargs-tune2fs.c
|
||||
gobject/guestfs-gobject-optargs-umount_local.c
|
||||
gobject/guestfs-gobject-session.c
|
||||
gobject/guestfs-gobject-struct-application.c
|
||||
gobject/guestfs-gobject-struct-btrfssubvolume.c
|
||||
gobject/guestfs-gobject-struct-dirent.c
|
||||
gobject/guestfs-gobject-struct-inotify_event.c
|
||||
gobject/guestfs-gobject-struct-int_bool.c
|
||||
|
||||
@@ -1 +1 @@
|
||||
321
|
||||
330
|
||||
|
||||
31
tests/btrfs/Makefile.am
Normal file
31
tests/btrfs/Makefile.am
Normal file
@@ -0,0 +1,31 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2012 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
TESTS = \
|
||||
test-btrfs-devices.sh \
|
||||
test-btrfs-subvolume-default.pl
|
||||
|
||||
random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
MALLOC_PERTURB_=$(random_val) \
|
||||
$(top_builddir)/run
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(TESTS)
|
||||
57
tests/btrfs/test-btrfs-devices.sh
Executable file
57
tests/btrfs/test-btrfs-devices.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs
|
||||
# Copyright (C) 2012 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Test btrfs adding/removing devices.
|
||||
|
||||
set -e
|
||||
|
||||
# XXX Not a very good test.
|
||||
if ! btrfs --help >/dev/null 2>&1; then
|
||||
echo "$0: test skipped because no 'btrfs' utility"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -f test[1234].img
|
||||
|
||||
../../fish/guestfish <<EOF
|
||||
# Add four empty disks
|
||||
sparse test1.img 1G
|
||||
sparse test2.img 1G
|
||||
sparse test3.img 1G
|
||||
sparse test4.img 1G
|
||||
run
|
||||
|
||||
part-disk /dev/sda mbr
|
||||
part-disk /dev/sdb mbr
|
||||
part-disk /dev/sdc mbr
|
||||
part-disk /dev/sdd mbr
|
||||
|
||||
mkfs-btrfs "/dev/sda1 /dev/sdb1"
|
||||
mount /dev/sda1 /
|
||||
|
||||
mkdir /foo
|
||||
touch /foo/bar
|
||||
|
||||
btrfs-device-add "/dev/sdc1 /dev/sdd1" /
|
||||
|
||||
# I cannot get this to work, seems to be a btrfs bug:
|
||||
#btrfs-device-delete "/dev/sda1 /dev/sdb1" /
|
||||
|
||||
EOF
|
||||
|
||||
rm -f test[1234].img
|
||||
95
tests/btrfs/test-btrfs-subvolume-default.pl
Executable file
95
tests/btrfs/test-btrfs-subvolume-default.pl
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/perl
|
||||
# libguestfs
|
||||
# Copyright (C) 2012 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Test btrfs subvolume list and btrfs subvolume default-id.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Sys::Guestfs;
|
||||
use Sys::Guestfs::Lib qw(feature_available);
|
||||
|
||||
my $testimg = "test1.img";
|
||||
|
||||
unlink $testimg;
|
||||
open FILE, ">$testimg" or die "$testimg: $!";
|
||||
truncate FILE, 1024*1024*1024 or die "$testimg: truncate: $!";
|
||||
close FILE or die "$testimg: $!";
|
||||
|
||||
my $g = Sys::Guestfs->new ();
|
||||
|
||||
$g->add_drive_opts ($testimg, format => "raw");
|
||||
$g->launch ();
|
||||
|
||||
# If btrfs is not available, bail.
|
||||
unless (feature_available ($g, "btrfs")) {
|
||||
warn "$0: skipping test because btrfs is not available\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
$g->part_disk ("/dev/sda", "mbr");
|
||||
|
||||
$g->mkfs_btrfs (["/dev/sda1"]);
|
||||
$g->mount ("/dev/sda1", "/");
|
||||
|
||||
$g->btrfs_subvolume_create ("/test1");
|
||||
$g->mkdir ("/test1/foo");
|
||||
$g->btrfs_subvolume_create ("/test2");
|
||||
|
||||
my @vols = $g->btrfs_subvolume_list ("/");
|
||||
|
||||
# Check the subvolume list, and extract the subvolume ID of path 'test1',
|
||||
# and the top level ID (which should be the same for both subvolumes).
|
||||
die ("expected 2 subvolumes, but got ", 0+@vols, " instead") unless @vols == 2;
|
||||
|
||||
my %ids;
|
||||
my $top_level_id;
|
||||
foreach (@vols) {
|
||||
my $path = $_->{btrfssubvolume_path};
|
||||
my $id = $_->{btrfssubvolume_id};
|
||||
my $top = $_->{btrfssubvolume_top_level_id};
|
||||
|
||||
if (!defined $top_level_id) {
|
||||
$top_level_id = $top;
|
||||
} elsif ($top_level_id != $top) {
|
||||
die "top_level_id fields are not all the same";
|
||||
}
|
||||
|
||||
$ids{$path} = $id;
|
||||
}
|
||||
|
||||
die "no subvolume path 'test1' found" unless exists $ids{test1};
|
||||
|
||||
my $test1_id = $ids{test1};
|
||||
|
||||
$g->btrfs_subvolume_set_default ($test1_id, "/");
|
||||
$g->umount ("/");
|
||||
$g->mount ("/dev/sda1", "/");
|
||||
# This was originally /test1/foo, but now that we changed the
|
||||
# default ID to 'test1', /test1 is mounted as /, so:
|
||||
$g->mkdir ("/foo/bar");
|
||||
|
||||
$g->btrfs_subvolume_set_default ($top_level_id, "/");
|
||||
$g->umount ("/");
|
||||
$g->mount ("/dev/sda1", "/");
|
||||
# Now we're back to the original default volume, so this should work:
|
||||
$g->mkdir ("/test1/foo/bar/baz");
|
||||
|
||||
$g->close ();
|
||||
|
||||
unlink $testimg or die "$testimg: unlink: $!";
|
||||
Reference in New Issue
Block a user