repart: Make partition files NOCOW if the disk image is NOCOW
On btrfs, reflinks into a disk image that has copy-on-write disabled only work if the source has copy-on-write disabled as well so let's make sure that's the case if the disk image has copy-on-write disabled.
This commit is contained in:
+53
-18
@@ -23,6 +23,7 @@
|
||||
#include "btrfs-util.h"
|
||||
#include "build.h"
|
||||
#include "chase.h"
|
||||
#include "chattr-util.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "constants.h"
|
||||
@@ -3792,12 +3793,14 @@ static PartitionTarget* partition_target_free(PartitionTarget *t) {
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(PartitionTarget*, partition_target_free);
|
||||
|
||||
static int prepare_temporary_file(PartitionTarget *t, uint64_t size) {
|
||||
static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t size) {
|
||||
_cleanup_(unlink_and_freep) char *temp = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
const char *vt;
|
||||
unsigned attrs = 0;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
assert(t);
|
||||
|
||||
r = var_tmp_dir(&vt);
|
||||
@@ -3812,6 +3815,16 @@ static int prepare_temporary_file(PartitionTarget *t, uint64_t size) {
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to create temporary file: %m");
|
||||
|
||||
r = read_attr_fd(fdisk_get_devfd(context->fdisk_context), &attrs);
|
||||
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return log_error_errno(r, "Failed to read file attributes of %s: %m", arg_node);
|
||||
|
||||
if (FLAGS_SET(attrs, FS_NOCOW_FL)) {
|
||||
r = chattr_fd(fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
|
||||
if (r < 0 && !ERRNO_IS_NOT_SUPPORTED(r))
|
||||
return log_error_errno(r, "Failed to disable copy-on-write on %s: %m", temp);
|
||||
}
|
||||
|
||||
if (ftruncate(fd, size) < 0)
|
||||
return log_error_errno(errno, "Failed to truncate temporary file to %s: %m",
|
||||
FORMAT_BYTES(size));
|
||||
@@ -3882,7 +3895,7 @@ static int partition_target_prepare(
|
||||
* reflinking support, we can take advantage of this and just reflink the result into the image.
|
||||
*/
|
||||
|
||||
r = prepare_temporary_file(t, size);
|
||||
r = prepare_temporary_file(context, t, size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -5831,6 +5844,7 @@ static int split_name_resolve(Context *context) {
|
||||
}
|
||||
|
||||
static int context_split(Context *context) {
|
||||
unsigned attrs = 0;
|
||||
int fd = -EBADF, r;
|
||||
|
||||
if (!arg_split)
|
||||
@@ -5857,13 +5871,23 @@ static int context_split(Context *context) {
|
||||
if (partition_type_defer(&p->type))
|
||||
continue;
|
||||
|
||||
fdt = open(p->split_path, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL, 0666);
|
||||
if (fd < 0) {
|
||||
assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
|
||||
|
||||
r = read_attr_fd(fd, &attrs);
|
||||
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return log_error_errno(r, "Failed to read file attributes of %s: %m", arg_node);
|
||||
}
|
||||
|
||||
fdt = xopenat_full(
|
||||
AT_FDCWD,
|
||||
p->split_path,
|
||||
O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL,
|
||||
attrs & FS_NOCOW_FL ? XO_NOCOW : 0,
|
||||
0666);
|
||||
if (fdt < 0)
|
||||
return log_error_errno(fdt, "Failed to open split partition file %s: %m", p->split_path);
|
||||
|
||||
if (fd < 0)
|
||||
assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
|
||||
|
||||
if (lseek(fd, p->offset, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to seek to partition offset: %m");
|
||||
|
||||
@@ -6661,10 +6685,15 @@ static int context_crypttab(Context *context) {
|
||||
|
||||
static int context_minimize(Context *context) {
|
||||
const char *vt = NULL;
|
||||
unsigned attrs = 0;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
r = read_attr_fd(context->backing_fd, &attrs);
|
||||
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return log_error_errno(r, "Failed to read file attributes of %s: %m", arg_node);
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *root = NULL;
|
||||
_cleanup_(unlink_and_freep) char *temp = NULL;
|
||||
@@ -6711,13 +6740,18 @@ static int context_minimize(Context *context) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate temporary file path: %m");
|
||||
|
||||
fd = xopenat_full(
|
||||
AT_FDCWD,
|
||||
temp,
|
||||
O_CREAT|O_EXCL|O_CLOEXEC|O_RDWR|O_NOCTTY,
|
||||
attrs & FS_NOCOW_FL ? XO_NOCOW : 0,
|
||||
0600);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
|
||||
|
||||
if (fstype_is_ro(p->format))
|
||||
fs_uuid = p->fs_uuid;
|
||||
else {
|
||||
fd = open(temp, O_CREAT|O_EXCL|O_CLOEXEC|O_RDWR|O_NOCTTY, 0600);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
|
||||
|
||||
/* This may seem huge but it will be created sparse so it doesn't take up any space
|
||||
* on disk until written to. */
|
||||
if (ftruncate(fd, 1024ULL * 1024ULL * 1024ULL * 1024ULL) < 0)
|
||||
@@ -6768,7 +6802,7 @@ static int context_minimize(Context *context) {
|
||||
/* Read-only filesystems are minimal from the first try because they create and size the
|
||||
* loopback file for us. */
|
||||
if (fstype_is_ro(p->format)) {
|
||||
assert(fd < 0);
|
||||
fd = safe_close(fd);
|
||||
|
||||
fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
@@ -6904,18 +6938,19 @@ static int context_minimize(Context *context) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate temporary file path: %m");
|
||||
|
||||
r = touch(temp);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create temporary file: %m");
|
||||
fd = xopenat_full(
|
||||
AT_FDCWD,
|
||||
temp,
|
||||
O_RDONLY|O_CLOEXEC|O_CREAT|O_NONBLOCK,
|
||||
attrs & FS_NOCOW_FL ? XO_NOCOW : 0,
|
||||
0600);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
|
||||
|
||||
r = partition_format_verity_hash(context, p, temp, dp->copy_blocks_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat temporary file: %m");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user