[systemd-commits] 4 commits - TODO src/import src/nspawn src/shared src/test
Lennart Poettering
lennart at kemper.freedesktop.org
Mon Apr 6 07:07:21 PDT 2015
TODO | 2
src/import/export-tar.c | 2
src/import/pull-common.c | 2
src/import/pull-dkr.c | 2
src/nspawn/nspawn.c | 4
src/shared/btrfs-util.c | 250 ++++++++++++++++++++++++++++++++-------------
src/shared/btrfs-util.h | 10 +
src/shared/machine-image.c | 2
src/test/test-btrfs.c | 14 +-
9 files changed, 206 insertions(+), 82 deletions(-)
New commits:
commit 403100e2813aa2c021975ae96e276824c7ca3c8f
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Apr 6 15:27:18 2015 +0200
update TODO
diff --git a/TODO b/TODO
index 6d5dd76..6ac9879 100644
--- a/TODO
+++ b/TODO
@@ -59,8 +59,6 @@ Features:
* .timer units should optionally support CLOCK_BOOTTIME in addition to CLOCK_MONOTONIC
-* rm_rf() should be able to remove subvolumes
-
* systemd-run should support a mode where we wait for the unit to be started up
* create a btrfs qgroup for /var/lib/machines, and add all container
commit f70a17f8d47ec8a62fa3b9b0bbe40fa107088540
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Apr 6 15:26:59 2015 +0200
btrfs: add support for recursive btrfs snapshotting
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index 7fae062..9bd0251 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -294,7 +294,7 @@ int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType
return r;
/* Let's try to make a snapshot, if we can, so that the export is atomic */
- r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY);
+ r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE);
if (r < 0) {
log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
free(e->temp_path);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 345a5c7..9371d36 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -3761,7 +3761,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = btrfs_subvol_snapshot(arg_directory, np, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
+ r = btrfs_subvol_snapshot(arg_directory, np, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE);
if (r < 0) {
log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory);
goto finish;
@@ -3785,7 +3785,7 @@ int main(int argc, char *argv[]) {
}
if (arg_template) {
- r = btrfs_subvol_snapshot(arg_template, arg_directory, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
+ r = btrfs_subvol_snapshot(arg_template, arg_directory, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE);
if (r == -EEXIST) {
if (!arg_quiet)
log_info("Directory %s already exists, not populating from template %s.", arg_directory, arg_template);
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 7fb92b2..5bf87a3 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -101,74 +101,6 @@ int btrfs_is_snapshot(int fd) {
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
-int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
- struct btrfs_ioctl_vol_args_v2 args = {
- .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
- };
- _cleanup_close_ int new_fd = -1;
- const char *subvolume;
- int r;
-
- assert(new_path);
-
- r = btrfs_is_snapshot(old_fd);
- if (r < 0)
- return r;
- if (r == 0) {
- if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY))
- return -EISDIR;
-
- r = btrfs_subvol_make(new_path);
- if (r < 0)
- return r;
-
- r = copy_directory_fd(old_fd, new_path, true);
- if (r < 0) {
- btrfs_subvol_remove(new_path, false);
- return r;
- }
-
- if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
- r = btrfs_subvol_set_read_only(new_path, true);
- if (r < 0) {
- btrfs_subvol_remove(new_path, false);
- return r;
- }
- }
-
- return 0;
- }
-
- r = extract_subvolume_name(new_path, &subvolume);
- if (r < 0)
- return r;
-
- new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (new_fd < 0)
- return new_fd;
-
- strncpy(args.name, subvolume, sizeof(args.name)-1);
- args.fd = old_fd;
-
- if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &args) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
- _cleanup_close_ int old_fd = -1;
-
- assert(old_path);
- assert(new_path);
-
- old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (old_fd < 0)
- return -errno;
-
- return btrfs_subvol_snapshot_fd(old_fd, new_path, flags);
-}
-
int btrfs_subvol_make(const char *path) {
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -1;
@@ -909,3 +841,183 @@ int btrfs_subvol_remove(const char *path, bool recursive) {
int btrfs_subvol_remove_fd(int fd, const char *subvolume, bool recursive) {
return subvol_remove_children(fd, subvolume, 0, recursive);
}
+
+static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t subvol_id, BtrfsSnapshotFlags flags) {
+
+ struct btrfs_ioctl_search_args args = {
+ .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
+
+ .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID,
+ .key.max_objectid = BTRFS_LAST_FREE_OBJECTID,
+
+ .key.min_type = BTRFS_ROOT_BACKREF_KEY,
+ .key.max_type = BTRFS_ROOT_BACKREF_KEY,
+
+ .key.min_transid = 0,
+ .key.max_transid = (uint64_t) -1,
+ };
+
+ struct btrfs_ioctl_vol_args_v2 vol_args = {
+ .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
+ .fd = old_fd,
+ };
+ int r;
+
+ assert(old_fd >= 0);
+ assert(new_fd >= 0);
+ assert(subvolume);
+
+ strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
+ vol_args.fd = old_fd;
+
+ if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &vol_args) < 0)
+ return -errno;
+
+ if (!(flags & BTRFS_SNAPSHOT_RECURSIVE))
+ return 0;
+
+ if (subvol_id == 0) {
+ r = btrfs_subvol_get_id_fd(old_fd, &subvol_id);
+ if (r < 0)
+ return r;
+ }
+
+ args.key.min_offset = args.key.max_offset = subvol_id;
+
+ while (btrfs_ioctl_search_args_compare(&args) <= 0) {
+ const struct btrfs_ioctl_search_header *sh;
+ unsigned i;
+
+ args.key.nr_items = 256;
+ if (ioctl(old_fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ return -errno;
+
+ if (args.key.nr_items <= 0)
+ break;
+
+ FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
+ _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL;
+ struct btrfs_ioctl_ino_lookup_args ino_args;
+ const struct btrfs_root_ref *ref;
+ _cleanup_close_ int old_child_fd = -1, new_child_fd = -1;
+
+ btrfs_ioctl_search_args_set(&args, sh);
+
+ if (sh->type != BTRFS_ROOT_BACKREF_KEY)
+ continue;
+ if (sh->offset != subvol_id)
+ continue;
+
+ ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
+
+ p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len));
+ if (!p)
+ return -ENOMEM;
+
+ zero(ino_args);
+ ino_args.treeid = subvol_id;
+ ino_args.objectid = htole64(ref->dirid);
+
+ if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
+ return -errno;
+
+ /* The kernel returns an empty name if the
+ * subvolume is in the top-level directory,
+ * and otherwise appends a slash, so that we
+ * can just concatenate easily here, without
+ * adding a slash. */
+ c = strappend(ino_args.name, p);
+ if (!c)
+ return -ENOMEM;
+
+ old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (old_child_fd < 0)
+ return -errno;
+
+ np = strjoin(subvolume, "/", ino_args.name, NULL);
+ if (!np)
+ return -ENOMEM;
+
+ new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (new_child_fd < 0)
+ return -errno;
+
+ /* When btrfs clones the subvolumes, child
+ * subvolumes appear as directories. Remove
+ * them, so that we can create a new snapshot
+ * in their place */
+ if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0)
+ return -errno;
+
+ r = subvol_snapshot_children(old_child_fd, new_child_fd, p, sh->objectid, flags & ~BTRFS_SNAPSHOT_FALLBACK_COPY);
+ if (r < 0)
+ return r;
+ }
+
+ /* Increase search key by one, to read the next item, if we can. */
+ if (!btrfs_ioctl_search_args_inc(&args))
+ break;
+ }
+
+ return 0;
+}
+
+int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
+ _cleanup_close_ int new_fd = -1;
+ const char *subvolume;
+ int r;
+
+ assert(old_fd >= 0);
+ assert(new_path);
+
+ r = btrfs_is_snapshot(old_fd);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY))
+ return -EISDIR;
+
+ r = btrfs_subvol_make(new_path);
+ if (r < 0)
+ return r;
+
+ r = copy_directory_fd(old_fd, new_path, true);
+ if (r < 0) {
+ btrfs_subvol_remove(new_path, false);
+ return r;
+ }
+
+ if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
+ r = btrfs_subvol_set_read_only(new_path, true);
+ if (r < 0) {
+ btrfs_subvol_remove(new_path, false);
+ return r;
+ }
+ }
+
+ return 0;
+ }
+
+ r = extract_subvolume_name(new_path, &subvolume);
+ if (r < 0)
+ return r;
+
+ new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (new_fd < 0)
+ return new_fd;
+
+ return subvol_snapshot_children(old_fd, new_fd, subvolume, 0, flags);
+}
+
+int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
+ _cleanup_close_ int old_fd = -1;
+
+ assert(old_path);
+ assert(new_path);
+
+ old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (old_fd < 0)
+ return -errno;
+
+ return btrfs_subvol_snapshot_fd(old_fd, new_path, flags);
+}
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index e3ad987..02e46e3 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -46,6 +46,7 @@ typedef struct BtrfsQuotaInfo {
typedef enum BtrfsSnapshotFlags {
BTRFS_SNAPSHOT_FALLBACK_COPY = 1,
BTRFS_SNAPSHOT_READ_ONLY = 2,
+ BTRFS_SNAPSHOT_RECURSIVE = 4,
} BtrfsSnapshotFlags;
int btrfs_is_snapshot(int fd);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index ebe5a13..0b41860 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -491,7 +491,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
case IMAGE_DIRECTORY:
new_path = strjoina("/var/lib/machines/", new_name);
- r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
+ r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE);
break;
case IMAGE_RAW:
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index 94437f7..838ffcb 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -133,9 +133,17 @@ int main(int argc, char *argv[]) {
if (mkdir("/xxxrectest/mnt", 0755) < 0)
log_error_errno(errno, "Failed to make directory: %m");
+ r = btrfs_subvol_snapshot("/xxxrectest", "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE);
+ if (r < 0)
+ log_error_errno(r, "Failed to snapshot subvolume: %m");
+
r = btrfs_subvol_remove("/xxxrectest", true);
if (r < 0)
log_error_errno(r, "Failed to recursively remove subvolume: %m");
+ r = btrfs_subvol_remove("/xxxrectest2", true);
+ if (r < 0)
+ log_error_errno(r, "Failed to recursively remove subvolume: %m");
+
return 0;
}
commit cbf21ecc02746b3e651c5067658a9f1e99838a53
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Apr 6 14:55:45 2015 +0200
btrfs: missing endian conversion fix
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 34ebaec..7fb92b2 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -849,7 +849,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
zero(ino_args);
ino_args.treeid = subvol_id;
- ino_args.objectid = ref->dirid;
+ ino_args.objectid = htole64(ref->dirid);
if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
return -errno;
commit e9bc1871b974fa9e33d9c1a45e249e6d1c8bc562
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Apr 6 11:47:25 2015 +0200
btrfs: make btrfs_subvol_snapshot() parameters a flags field
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index c2fd656..7fae062 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -294,7 +294,7 @@ int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType
return r;
/* Let's try to make a snapshot, if we can, so that the export is atomic */
- r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, true, false);
+ r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY);
if (r < 0) {
log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
free(e->temp_path);
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index ee0c064..efd67a2 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -127,7 +127,7 @@ int pull_make_local_copy(const char *final, const char *image_root, const char *
if (force_local)
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
- r = btrfs_subvol_snapshot(final, p, false, false);
+ r = btrfs_subvol_snapshot(final, p, 0);
if (r == -ENOTTY) {
r = copy_tree(final, p, false);
if (r < 0)
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
index 402ddac..c922bac 100644
--- a/src/import/pull-dkr.c
+++ b/src/import/pull-dkr.c
@@ -486,7 +486,7 @@ static int dkr_pull_job_on_open_disk(PullJob *j) {
const char *base_path;
base_path = strjoina(i->image_root, "/.dkr-", base);
- r = btrfs_subvol_snapshot(base_path, i->temp_path, false, true);
+ r = btrfs_subvol_snapshot(base_path, i->temp_path, BTRFS_SNAPSHOT_FALLBACK_COPY);
} else
r = btrfs_subvol_make(i->temp_path);
if (r < 0)
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 90c4415..345a5c7 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -3761,7 +3761,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = btrfs_subvol_snapshot(arg_directory, np, arg_read_only, true);
+ r = btrfs_subvol_snapshot(arg_directory, np, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
if (r < 0) {
log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory);
goto finish;
@@ -3785,7 +3785,7 @@ int main(int argc, char *argv[]) {
}
if (arg_template) {
- r = btrfs_subvol_snapshot(arg_template, arg_directory, arg_read_only, true);
+ r = btrfs_subvol_snapshot(arg_template, arg_directory, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
if (r == -EEXIST) {
if (!arg_quiet)
log_info("Directory %s already exists, not populating from template %s.", arg_directory, arg_template);
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index fc795cb..34ebaec 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -101,9 +101,9 @@ int btrfs_is_snapshot(int fd) {
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
-int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, bool read_only, bool fallback_copy) {
+int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
struct btrfs_ioctl_vol_args_v2 args = {
- .flags = read_only ? BTRFS_SUBVOL_RDONLY : 0,
+ .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
};
_cleanup_close_ int new_fd = -1;
const char *subvolume;
@@ -115,7 +115,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, bool read_only, b
if (r < 0)
return r;
if (r == 0) {
- if (!fallback_copy)
+ if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY))
return -EISDIR;
r = btrfs_subvol_make(new_path);
@@ -128,7 +128,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, bool read_only, b
return r;
}
- if (read_only) {
+ if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
r = btrfs_subvol_set_read_only(new_path, true);
if (r < 0) {
btrfs_subvol_remove(new_path, false);
@@ -156,7 +156,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, bool read_only, b
return 0;
}
-int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_only, bool fallback_copy) {
+int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
_cleanup_close_ int old_fd = -1;
assert(old_path);
@@ -166,7 +166,7 @@ int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_
if (old_fd < 0)
return -errno;
- return btrfs_subvol_snapshot_fd(old_fd, new_path, read_only, fallback_copy);
+ return btrfs_subvol_snapshot_fd(old_fd, new_path, flags);
}
int btrfs_subvol_make(const char *path) {
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index 06ecc11..e3ad987 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -43,13 +43,18 @@ typedef struct BtrfsQuotaInfo {
uint64_t exclusive_max;
} BtrfsQuotaInfo;
+typedef enum BtrfsSnapshotFlags {
+ BTRFS_SNAPSHOT_FALLBACK_COPY = 1,
+ BTRFS_SNAPSHOT_READ_ONLY = 2,
+} BtrfsSnapshotFlags;
+
int btrfs_is_snapshot(int fd);
int btrfs_subvol_make(const char *path);
int btrfs_subvol_make_label(const char *path);
-int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, bool read_only, bool fallback_copy);
-int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_only, bool fallback_copy);
+int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags);
+int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags);
int btrfs_subvol_set_read_only_fd(int fd, bool b);
int btrfs_subvol_set_read_only(const char *path, bool b);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index fb72123..ebe5a13 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -491,7 +491,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
case IMAGE_DIRECTORY:
new_path = strjoina("/var/lib/machines/", new_name);
- r = btrfs_subvol_snapshot(i->path, new_path, read_only, true);
+ r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY);
break;
case IMAGE_RAW:
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index 373ce43..94437f7 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -72,11 +72,11 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to write file: %m");
- r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", false, false);
+ r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", 0);
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
- r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", true, false);
+ r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY);
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
@@ -92,7 +92,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to remove subvolume: %m");
- r = btrfs_subvol_snapshot("/etc", "/etc2", true, true);
+ r = btrfs_subvol_snapshot("/etc", "/etc2", BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY);
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
More information about the systemd-commits
mailing list