if (*root_image) {
log_debug("Making ephemeral copy of %s to %s", *root_image, new_root);
- fd = copy_file(*root_image,
- new_root,
- O_EXCL,
- 0600,
- COPY_LOCK_BSD|
- COPY_REFLINK|
- COPY_CRTIME);
+ fd = copy_file(*root_image, new_root, O_EXCL, 0600,
+ COPY_LOCK_BSD|COPY_REFLINK|COPY_CRTIME|COPY_NOCOW_AFTER);
if (fd < 0)
return log_debug_errno(fd, "Failed to copy image %s to %s: %m",
*root_image, new_root);
-
- /* A root image might be subject to lots of random writes so let's try to disable COW on it
- * which tends to not perform well in combination with lots of random writes.
- *
- * Note: btrfs actually isn't impressed by us setting the flag after making the reflink'ed
- * copy, but we at least want to make the intention clear.
- */
- r = chattr_fd(fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
- if (r < 0)
- log_debug_errno(r, "Failed to disable copy-on-write for %s, ignoring: %m", new_root);
} else {
assert(*root_directory);
#include "capability-util.h"
#include "cgroup-util.h"
#include "chase.h"
+#include "chattr-util.h"
#include "common-signal.h"
#include "copy.h"
#include "cpu-set-util.h"
{
BLOCK_SIGNALS(SIGINT);
- r = copy_file_full(arg_image, np, O_EXCL, arg_read_only ? 0400 : 0600,
- FS_NOCOW_FL, FS_NOCOW_FL,
- COPY_REFLINK|COPY_CRTIME|COPY_SIGINT,
- NULL, NULL);
+ r = copy_file(arg_image, np, O_EXCL, arg_read_only ? 0400 : 0600,
+ COPY_REFLINK|COPY_CRTIME|COPY_SIGINT|COPY_NOCOW_AFTER);
}
if (r == -EINTR) {
log_error_errno(r, "Interrupted while copying image file to %s, removed again.", np);
goto fail;
}
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL);
+ unsigned nocow = FLAGS_SET(copy_flags, COPY_NOCOW_AFTER) ? FS_NOCOW_FL : 0;
+ if ((chattr_mask | nocow) != 0)
+ (void) chattr_fd(fdt, chattr_flags | nocow, (chattr_mask & ~CHATTR_EARLY_FL) | nocow, NULL);
if (copy_flags & (COPY_FSYNC|COPY_FSYNC_FULL)) {
if (fsync(fdt) < 0) {
t = mfree(t);
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL);
+ unsigned nocow = FLAGS_SET(copy_flags, COPY_NOCOW_AFTER) ? FS_NOCOW_FL : 0;
+ if ((chattr_mask | nocow) != 0)
+ (void) chattr_fd(fdt, chattr_flags | nocow, (chattr_mask & ~CHATTR_EARLY_FL) | nocow, NULL);
r = close_nointr(TAKE_FD(fdt)); /* even if this fails, the fd is now invalidated */
if (r < 0)
COPY_LOCK_BSD = 1 << 17, /* Return a BSD exclusively locked file descriptor referring to the copied image/directory. */
COPY_VERIFY_LINKED = 1 << 18, /* Check the source file is still linked after copying. */
COPY_RESTORE_DIRECTORY_TIMESTAMPS = 1 << 19, /* Make sure existing directory timestamps don't change during copying. */
+ /* A root image might be subject to lots of random writes so we provide a flag to try to disable COW
+ * on a copied file which tends to not perform well in combination with lots of random writes.
+ *
+ * Note: btrfs actually isn't impressed by us setting the flag after making the copy, but this at
+ * least makes the intention clear. We don't want to unconditionally set the flag before doing the
+ * copy because reflinking from COW to NOCOW files is not supported.
+ */
+ COPY_NOCOW_AFTER = 1 << 20,
} CopyFlags;
typedef enum DenyType {
case IMAGE_RAW:
new_path = strjoina("/var/lib/machines/", new_name, ".raw");
- r = copy_file_atomic_full(i->path, new_path, read_only ? 0444 : 0644, FS_NOCOW_FL, FS_NOCOW_FL,
- COPY_REFLINK|COPY_CRTIME, NULL, NULL);
+ r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644,
+ COPY_REFLINK|COPY_CRTIME|COPY_NOCOW_AFTER);
break;
case IMAGE_BLOCK: