mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 09:32:04 +00:00
repart: Reuse the backing fd for fdisk
Because fdisk_assign_device tries to open block devices with O_EXCL, when it does it blocks cryptsetup from using partition block devices for the same disk. Since we already have a file descriptor for the device, we can just share it and use fdisk_assign_device_by_fd instead. This requires at least libfdisk 2.35 (part of util-linux) which was released in 2020.
This commit is contained in:
2
README
2
README
@@ -219,7 +219,7 @@ REQUIREMENTS:
|
||||
libacl (optional)
|
||||
libbpf >= 0.1.0 (optional),
|
||||
>= 1.4.0 is required for using GCC as a bpf compiler
|
||||
libfdisk >= 2.32 (from util-linux) (optional)
|
||||
libfdisk >= 2.35 (from util-linux) (optional)
|
||||
libselinux >= 2.1.9 (optional)
|
||||
libapparmor >= 2.13 (optional)
|
||||
libxenctrl >= 4.9 (optional)
|
||||
|
||||
@@ -1076,7 +1076,7 @@ conf.set10('HAVE_LIBMOUNT', have)
|
||||
libmount_cflags = libmount.partial_dependency(includes: true, compile_args: true)
|
||||
|
||||
libfdisk = dependency('fdisk',
|
||||
version : '>= 2.32',
|
||||
version : '>= 2.35',
|
||||
required : get_option('fdisk'))
|
||||
libfdisk_cflags = libfdisk.partial_dependency(includes: true, compile_args: true)
|
||||
conf.set10('HAVE_LIBFDISK', libfdisk.found())
|
||||
|
||||
@@ -544,6 +544,7 @@ struct Context {
|
||||
uint64_t start, end, total;
|
||||
|
||||
struct fdisk_context *fdisk_context;
|
||||
int fdisk_context_fd;
|
||||
uint64_t sector_size, grain_size, default_fs_sector_size;
|
||||
|
||||
sd_id128_t seed;
|
||||
@@ -948,6 +949,7 @@ static Context* context_new(
|
||||
.empty = empty,
|
||||
.dry_run = dry_run,
|
||||
.backing_fd = -EBADF,
|
||||
.fdisk_context_fd = -EBADF,
|
||||
};
|
||||
|
||||
return context;
|
||||
@@ -977,6 +979,7 @@ static Context* context_free(Context *context) {
|
||||
|
||||
if (context->fdisk_context)
|
||||
sym_fdisk_unref_context(context->fdisk_context);
|
||||
safe_close(context->fdisk_context_fd);
|
||||
|
||||
safe_close(context->backing_fd);
|
||||
if (context->node_is_our_file)
|
||||
@@ -3162,16 +3165,17 @@ static int find_verity_sibling(Context *context, Partition *p, VerityMode mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_open_and_lock_backing_fd(const char *node, int operation, int *backing_fd) {
|
||||
static int context_open_and_lock_backing_fd(const char *node, int operation, int mode, int *backing_fd) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
assert(node);
|
||||
assert(backing_fd);
|
||||
assert(IN_SET(mode, O_RDONLY, O_RDWR));
|
||||
|
||||
if (*backing_fd >= 0)
|
||||
return 0;
|
||||
|
||||
fd = open(node, O_RDONLY|O_CLOEXEC);
|
||||
fd = open(node, mode|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open device '%s': %m", node);
|
||||
|
||||
@@ -3264,7 +3268,7 @@ static int context_copy_from_one(Context *context, const char *src) {
|
||||
|
||||
assert(src);
|
||||
|
||||
r = context_open_and_lock_backing_fd(src, LOCK_SH, &fd);
|
||||
r = context_open_and_lock_backing_fd(src, LOCK_SH, O_RDONLY, &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -3674,7 +3678,12 @@ static int context_load_fallback_metrics(Context *context) {
|
||||
return 1; /* Starting from scratch */
|
||||
}
|
||||
|
||||
static int context_open_mode(Context *context) {
|
||||
return ASSERT_PTR(context)->dry_run ? O_RDONLY : O_RDWR;
|
||||
}
|
||||
|
||||
static int context_load_partition_table(Context *context) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
|
||||
_cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
|
||||
uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors;
|
||||
@@ -3688,6 +3697,7 @@ static int context_load_partition_table(Context *context) {
|
||||
assert(context);
|
||||
assert(context->node);
|
||||
assert(!context->fdisk_context);
|
||||
assert(context->fdisk_context_fd < 0);
|
||||
assert(!context->free_areas);
|
||||
assert(context->start == UINT64_MAX);
|
||||
assert(context->end == UINT64_MAX);
|
||||
@@ -3709,6 +3719,7 @@ static int context_load_partition_table(Context *context) {
|
||||
r = context_open_and_lock_backing_fd(
|
||||
context->node,
|
||||
context->dry_run ? LOCK_SH : LOCK_EX,
|
||||
context_open_mode(context),
|
||||
&context->backing_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -3739,11 +3750,15 @@ static int context_load_partition_table(Context *context) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set sector size: %m");
|
||||
|
||||
/* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
|
||||
* /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
|
||||
r = sym_fdisk_assign_device(
|
||||
if (context->backing_fd < 0) {
|
||||
fd = open(context->node, context_open_mode(context)|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open backing node '%s': %m", context->node);
|
||||
}
|
||||
r = sym_fdisk_assign_device_by_fd(
|
||||
c,
|
||||
context->backing_fd >= 0 ? FORMAT_PROC_FD_PATH(context->backing_fd) : context->node,
|
||||
context->backing_fd >= 0 ? context->backing_fd : fd,
|
||||
context->node,
|
||||
context->dry_run);
|
||||
if (r == -EINVAL && arg_size_auto) {
|
||||
struct stat st;
|
||||
@@ -3752,7 +3767,7 @@ static int context_load_partition_table(Context *context) {
|
||||
* it if automatic sizing is requested. */
|
||||
|
||||
if (context->backing_fd < 0)
|
||||
r = stat(context->node, &st);
|
||||
r = fstat(fd, &st);
|
||||
else
|
||||
r = fstat(context->backing_fd, &st);
|
||||
if (r < 0)
|
||||
@@ -3775,6 +3790,7 @@ static int context_load_partition_table(Context *context) {
|
||||
/* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
|
||||
r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(sym_fdisk_get_devfd(c)),
|
||||
context->dry_run ? LOCK_SH : LOCK_EX,
|
||||
context_open_mode(context),
|
||||
&context->backing_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -4047,6 +4063,7 @@ add_initial_free_area:
|
||||
context->default_fs_sector_size = fs_secsz;
|
||||
context->grain_size = grainsz;
|
||||
context->fdisk_context = TAKE_PTR(c);
|
||||
context->fdisk_context_fd = TAKE_FD(fd);
|
||||
|
||||
return from_scratch;
|
||||
}
|
||||
@@ -4103,6 +4120,7 @@ static void context_unload_partition_table(Context *context) {
|
||||
sym_fdisk_unref_context(context->fdisk_context);
|
||||
context->fdisk_context = NULL;
|
||||
}
|
||||
context->fdisk_context_fd = safe_close(context->fdisk_context_fd);
|
||||
|
||||
context_free_free_areas(context);
|
||||
}
|
||||
@@ -10433,13 +10451,21 @@ static int acquire_root_devno(
|
||||
assert(ret);
|
||||
assert(ret_fd);
|
||||
|
||||
fd = chase_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
|
||||
fd = chase_and_open(p, root, CHASE_PREFIX_ROOT, (mode & ~O_ACCMODE_STRICT) | O_RDONLY, &found_path);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if ((S_ISREG(st.st_mode) || S_ISBLK(st.st_mode)) && (mode & O_ACCMODE_STRICT) != O_RDONLY) {
|
||||
_cleanup_close_ int new_fd = fd_reopen(fd, mode);
|
||||
if (new_fd < 0)
|
||||
return new_fd;
|
||||
|
||||
close_and_replace(fd, new_fd);
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
*ret = TAKE_PTR(found_path);
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
@@ -10499,7 +10525,7 @@ static int acquire_root_devno(
|
||||
|
||||
static int find_root(Context *context) {
|
||||
_cleanup_free_ char *device = NULL;
|
||||
int r;
|
||||
int r, open_flags = O_CLOEXEC|context_open_mode(context);
|
||||
|
||||
assert(context);
|
||||
|
||||
@@ -10515,7 +10541,7 @@ static int find_root(Context *context) {
|
||||
if (!s)
|
||||
return log_oom();
|
||||
|
||||
fd = xopenat_full(AT_FDCWD, arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, XO_NOCOW, 0666);
|
||||
fd = xopenat_full(AT_FDCWD, arg_node, open_flags|O_CREAT|O_EXCL|O_NOFOLLOW, XO_NOCOW, 0666);
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to create '%s': %m", arg_node);
|
||||
|
||||
@@ -10527,7 +10553,7 @@ static int find_root(Context *context) {
|
||||
|
||||
/* Note that we don't specify a root argument here: if the user explicitly configured a node
|
||||
* we'll take it relative to the host, not the image */
|
||||
r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
|
||||
r = acquire_root_devno(arg_node, NULL, open_flags, &context->node, &context->backing_fd);
|
||||
if (r == -EUCLEAN)
|
||||
return btrfs_log_dev_root(LOG_ERR, r, arg_node);
|
||||
if (r < 0)
|
||||
@@ -10549,7 +10575,7 @@ static int find_root(Context *context) {
|
||||
|
||||
FOREACH_STRING(p, "/", "/usr") {
|
||||
|
||||
r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, &context->node,
|
||||
r = acquire_root_devno(p, arg_root, open_flags|O_DIRECTORY, &context->node,
|
||||
&context->backing_fd);
|
||||
if (r < 0) {
|
||||
if (r == -EUCLEAN)
|
||||
@@ -10562,7 +10588,7 @@ static int find_root(Context *context) {
|
||||
} else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
|
||||
else {
|
||||
r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
|
||||
r = acquire_root_devno(device, NULL, open_flags, &context->node, &context->backing_fd);
|
||||
if (r == -EUCLEAN)
|
||||
return btrfs_log_dev_root(LOG_ERR, r, device);
|
||||
if (r < 0)
|
||||
|
||||
@@ -23,6 +23,7 @@ DLSYM_PROTOTYPE(fdisk_apply_table) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_ask_get_type) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_ask_string_set_result) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_assign_device) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_assign_device_by_fd) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_create_disklabel) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_delete_partition) = NULL;
|
||||
DLSYM_PROTOTYPE(fdisk_get_devfd) = NULL;
|
||||
@@ -97,6 +98,7 @@ int dlopen_fdisk(int log_level) {
|
||||
DLSYM_ARG(fdisk_ask_get_type),
|
||||
DLSYM_ARG(fdisk_ask_string_set_result),
|
||||
DLSYM_ARG(fdisk_assign_device),
|
||||
DLSYM_ARG(fdisk_assign_device_by_fd),
|
||||
DLSYM_ARG(fdisk_create_disklabel),
|
||||
DLSYM_ARG(fdisk_delete_partition),
|
||||
DLSYM_ARG(fdisk_get_devfd),
|
||||
|
||||
@@ -14,6 +14,7 @@ extern DLSYM_PROTOTYPE(fdisk_apply_table);
|
||||
extern DLSYM_PROTOTYPE(fdisk_ask_get_type);
|
||||
extern DLSYM_PROTOTYPE(fdisk_ask_string_set_result);
|
||||
extern DLSYM_PROTOTYPE(fdisk_assign_device);
|
||||
extern DLSYM_PROTOTYPE(fdisk_assign_device_by_fd);
|
||||
extern DLSYM_PROTOTYPE(fdisk_create_disklabel);
|
||||
extern DLSYM_PROTOTYPE(fdisk_delete_partition);
|
||||
extern DLSYM_PROTOTYPE(fdisk_get_devfd);
|
||||
|
||||
Reference in New Issue
Block a user