From 8120ee28b8d5d316d9ded9240bcccc9edb41ee06 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 19:26:54 +0200 Subject: image: enable btrfs quotas on the clone destination, not the source --- src/shared/machine-image.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/shared') diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index bebfc40efe..042ccc071c 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -607,9 +607,9 @@ int image_clone(Image *i, const char *new_name, bool read_only) { r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA); - /* Enable "subtree" quotas for the copy, if we didn't - * copy any quota from the source. */ - (void) btrfs_subvol_auto_qgroup(i->path, 0, true); + /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */ + if (r >= 0) + (void) btrfs_subvol_auto_qgroup(new_path, 0, true); break; -- cgit v1.2.3-54-g00ecf From a67d68b84801dccbbc03010c679138bb9e4f91ac Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 20:05:44 +0200 Subject: tree-wide: fix invocations of chattr_path() chattr_path() takes two bitmasks, and no booleans. Fix the various invocations to do this properly. --- src/journal/journal-file.c | 2 +- src/shared/machine-image.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/shared') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index c9ce5c73be..ec50333c2c 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -3293,7 +3293,7 @@ int journal_file_open_reliably( /* btrfs doesn't cope well with our write pattern and * fragments heavily. Let's defrag all files we rotate */ - (void) chattr_path(p, false, FS_NOCOW_FL); + (void) chattr_path(p, 0, FS_NOCOW_FL); (void) btrfs_defrag(p); log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 042ccc071c..eb8f6ee438 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -423,7 +423,7 @@ int image_remove(Image *i) { case IMAGE_DIRECTORY: /* Allow deletion of read-only directories */ - (void) chattr_path(i->path, false, FS_IMMUTABLE_FL); + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL); r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); if (r < 0) return r; @@ -505,7 +505,7 @@ int image_rename(Image *i, const char *new_name) { (void) read_attr_path(i->path, &file_attr); if (file_attr & FS_IMMUTABLE_FL) - (void) chattr_path(i->path, false, FS_IMMUTABLE_FL); + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL); /* fall through */ @@ -538,7 +538,7 @@ int image_rename(Image *i, const char *new_name) { /* Restore the immutable bit, if it was set before */ if (file_attr & FS_IMMUTABLE_FL) - (void) chattr_path(new_path, true, FS_IMMUTABLE_FL); + (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL); free(i->path); i->path = new_path; @@ -670,7 +670,7 @@ int image_read_only(Image *i, bool b) { a read-only subvolume, but at least something, and we can read the value back.*/ - r = chattr_path(i->path, b, FS_IMMUTABLE_FL); + r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 9a50e3caab82f8406ecfac6048ac8e2ce98b0ab8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 20:06:20 +0200 Subject: machined: support non-btrfs file systems with "machinectl clone" Fall back to a normal copy operation when the backing file system isn't btrfs, and hence doesn't support cheap snapshotting. Of course, this will be slow, but given that the execution is asynchronous now, this should be OK. Fixes: #1308 --- src/basic/copy.c | 15 +++++++++++++++ src/basic/copy.h | 1 + src/shared/machine-image.c | 14 +++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src/shared') diff --git a/src/basic/copy.c b/src/basic/copy.c index 79b9a0e1a0..c3586728d0 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -423,6 +423,21 @@ int copy_directory_fd(int dirfd, const char *to, bool merge) { return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge); } +int copy_directory(const char *from, const char *to, bool merge) { + struct stat st; + + assert(from); + assert(to); + + if (lstat(from, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -ENOTDIR; + + return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, merge); +} + int copy_file_fd(const char *from, int fdt, bool try_reflink) { _cleanup_close_ int fdf = -1; int r; diff --git a/src/basic/copy.h b/src/basic/copy.h index 3e5eb52506..b5d08ebafe 100644 --- a/src/basic/copy.h +++ b/src/basic/copy.h @@ -30,6 +30,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace int copy_tree(const char *from, const char *to, bool merge); int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge); int copy_directory_fd(int dirfd, const char *to, bool merge); +int copy_directory(const char *from, const char *to, bool merge); int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink); int copy_times(int fdf, int fdt); int copy_xattr(int fdf, int fdt); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index eb8f6ee438..66f58ecd92 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -603,12 +603,20 @@ int image_clone(Image *i, const char *new_name, bool read_only) { case IMAGE_SUBVOLUME: case IMAGE_DIRECTORY: + /* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain + * 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 | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA); - - /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */ - if (r >= 0) + if (r == -EOPNOTSUPP) { + /* No btrfs snapshots supported, create a normal directory then. */ + + r = copy_directory(i->path, new_path, false); + if (r >= 0) + (void) chattr_path(new_path, read_only ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL); + } else if (r >= 0) + /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */ (void) btrfs_subvol_auto_qgroup(new_path, 0, true); break; -- cgit v1.2.3-54-g00ecf