Merge pull request #14398 from poettering/mount-prep

This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-02-04 16:28:51 +01:00
13 changed files with 306 additions and 113 deletions
+10 -12
View File
@@ -217,7 +217,7 @@ static void mount_done(Unit *u) {
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
}
_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
static MountParameters* get_mount_parameters_fragment(Mount *m) {
assert(m);
if (m->from_fragment)
@@ -226,7 +226,7 @@ _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
return NULL;
}
_pure_ static MountParameters* get_mount_parameters(Mount *m) {
static MountParameters* get_mount_parameters(Mount *m) {
assert(m);
if (m->from_proc_self_mountinfo)
@@ -342,20 +342,18 @@ static int mount_add_device_dependencies(Mount *m) {
if (!is_device_path(p->what))
return 0;
/* /dev/root is a really weird thing, it's not a real device,
* but just a path the kernel exports for the root file system
* specified on the kernel command line. Ignore it here. */
if (path_equal(p->what, "/dev/root"))
/* /dev/root is a really weird thing, it's not a real device, but just a path the kernel exports for
* the root file system specified on the kernel command line. Ignore it here. */
if (PATH_IN_SET(p->what, "/dev/root", "/dev/nfs"))
return 0;
if (path_equal(m->where, "/"))
return 0;
/* Mount units from /proc/self/mountinfo are not bound to devices
* by default since they're subject to races when devices are
* unplugged. But the user can still force this dep with an
* appropriate option (or udev property) so the mount units are
* automatically stopped when the device disappears suddenly. */
/* Mount units from /proc/self/mountinfo are not bound to devices by default since they're subject to
* races when devices are unplugged. But the user can still force this dep with an appropriate option
* (or udev property) so the mount units are automatically stopped when the device disappears
* suddenly. */
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
/* We always use 'what' from /proc/self/mountinfo if mounted */
@@ -365,7 +363,7 @@ static int mount_add_device_dependencies(Mount *m) {
if (r < 0)
return r;
return 0;
return unit_add_blockdev_dependency(UNIT(m), p->what, mask);
}
static int mount_add_quota_dependencies(Mount *m) {
+30 -6
View File
@@ -184,21 +184,45 @@ static int swap_arm_timer(Swap *s, usec_t usec) {
return 0;
}
static SwapParameters* swap_get_parameters(Swap *s) {
assert(s);
if (s->from_proc_swaps)
return &s->parameters_proc_swaps;
if (s->from_fragment)
return &s->parameters_fragment;
return NULL;
}
static int swap_add_device_dependencies(Swap *s) {
UnitDependencyMask mask;
SwapParameters *p;
int r;
assert(s);
if (!s->what)
return 0;
if (!s->from_fragment)
p = swap_get_parameters(s);
if (!p)
return 0;
if (is_device_path(s->what))
return unit_add_node_dependency(UNIT(s), s->what, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE);
mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
/* File based swap devices need to be ordered after systemd-remount-fs.service,
* since they might need a writable file system. */
return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, UNIT_DEPENDENCY_FILE);
if (is_device_path(p->what)) {
r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
if (r < 0)
return r;
return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
}
/* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
* a writable file system. */
return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, mask);
}
static int swap_add_default_dependencies(Swap *s) {
+29 -3
View File
@@ -3866,8 +3866,8 @@ int unit_deserialize_skip(FILE *f) {
}
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
Unit *device;
_cleanup_free_ char *e = NULL;
Unit *device;
int r;
assert(u);
@@ -3879,8 +3879,7 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
if (!is_device_path(what))
return 0;
/* When device units aren't supported (such as in a
* container), don't create dependencies on them. */
/* When device units aren't supported (such as in a container), don't create dependencies on them. */
if (!unit_type_supported(UNIT_DEVICE))
return 0;
@@ -3900,6 +3899,33 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
device, true, mask);
}
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask) {
_cleanup_free_ char *escaped = NULL, *target = NULL;
int r;
assert(u);
if (isempty(what))
return 0;
if (!path_startswith(what, "/dev/"))
return 0;
/* If we don't support devices, then also don't bother with blockdev@.target */
if (!unit_type_supported(UNIT_DEVICE))
return 0;
r = unit_name_path_escape(what, &escaped);
if (r < 0)
return r;
r = unit_name_build("blockdev", escaped, ".target", &target);
if (r < 0)
return r;
return unit_add_dependency_by_name(u, UNIT_AFTER, target, true, mask);
}
int unit_coldplug(Unit *u) {
int r = 0, q;
char **i;
+1
View File
@@ -743,6 +743,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
int unit_deserialize_skip(FILE *f);
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
int unit_coldplug(Unit *u);
void unit_catchup(Unit *u);
+25 -46
View File
@@ -99,7 +99,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
return 0;
}
static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
static int generate_keydev_mount(
const char *name,
const char *keydev,
const char *keydev_timeout,
bool canfail,
char **unit,
char **mount) {
_cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -223,8 +230,8 @@ static int create_disk(
const char *options) {
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL,
*filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *header_path = NULL;
*keydev_mount = NULL, *keyfile_timeout_value = NULL,
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *dmname;
bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
@@ -285,39 +292,29 @@ static int create_disk(
if (r < 0)
return r;
fprintf(f,
"[Unit]\n"
"Description=Cryptography Setup for %%I\n"
"Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
"SourcePath=%s\n"
"DefaultDependencies=no\n"
"IgnoreOnIsolate=true\n"
"After=%s\n",
arg_crypttab,
netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
r = generator_write_cryptsetup_unit_section(f, arg_crypttab);
if (r < 0)
return r;
if (netdev)
fprintf(f, "After=remote-fs-pre.target\n");
/* If initrd takes care of attaching the disk then it should also detach it during shutdown. */
if (!attach_in_initrd)
fprintf(f, "Conflicts=umount.target\n");
if (password) {
password_escaped = specifier_escape(password);
if (!password_escaped)
return log_oom();
}
if (keydev) {
_cleanup_free_ char *unit = NULL, *p = NULL;
_cleanup_free_ char *unit = NULL;
r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
if (r < 0)
return log_error_errno(r, "Failed to generate keydev mount unit: %m");
p = path_join(keydev_mount, password_escaped);
if (!p)
password_buffer = path_join(keydev_mount, password);
if (!password_buffer)
return log_oom();
free_and_replace(password_escaped, p);
password = password_buffer;
fprintf(f, "After=%s\n", unit);
if (keyfile_can_timeout > 0)
@@ -344,17 +341,13 @@ static int create_disk(
return r;
}
if (path_startswith(u, "/dev/")) {
if (path_startswith(u, "/dev/"))
fprintf(f,
"BindsTo=%s\n"
"After=%s\n"
"Before=umount.target\n",
d, d);
if (swap)
fputs("Before=dev-mapper-%i.swap\n",
f);
} else
else
/* For loopback devices, add systemd-tmpfiles-setup-dev.service
dependency to ensure that loopback support is available in
the kernel (/dev/loop-control needs to exist) */
@@ -368,23 +361,9 @@ static int create_disk(
if (r < 0)
log_warning_errno(r, "Failed to write device timeout drop-in: %m");
if (filtered) {
filtered_escaped = specifier_escape(filtered);
if (!filtered_escaped)
return log_oom();
}
fprintf(f,
"\n[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
"TimeoutSec=0\n" /* the binary handles timeouts anyway */
"KeyringMode=shared\n" /* make sure we can share cached keys among instances */
"OOMScoreAdjust=500\n" /* unlocking can allocate a lot of memory if Argon2 is used */
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped),
name_escaped);
r = generator_write_cryptsetup_service_section(f, name, u, password, filtered);
if (r < 0)
return r;
if (tmp)
fprintf(f,
+36 -11
View File
@@ -118,11 +118,18 @@ static int add_swap(
fprintf(f,
"[Unit]\n"
"SourcePath=%s\n"
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n"
"[Swap]\n",
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
"SourcePath=%s\n",
fstab_path());
r = generator_write_blockdev_dependency(f, what);
if (r < 0)
return r;
fprintf(f,
"\n"
"[Swap]\n");
r = write_what(f, what);
if (r < 0)
return r;
@@ -174,8 +181,13 @@ static bool mount_in_initrd(struct mntent *me) {
streq(me->mnt_dir, "/usr");
}
static int write_timeout(FILE *f, const char *where, const char *opts,
const char *filter, const char *variable) {
static int write_timeout(
FILE *f,
const char *where,
const char *opts,
const char *filter,
const char *variable) {
_cleanup_free_ char *timeout = NULL;
char timespan[FORMAT_TIMESPAN_MAX];
usec_t u;
@@ -208,8 +220,12 @@ static int write_mount_timeout(FILE *f, const char *where, const char *opts) {
"x-systemd.mount-timeout\0", "TimeoutSec");
}
static int write_dependency(FILE *f, const char *opts,
const char *filter, const char *format) {
static int write_dependency(
FILE *f,
const char *opts,
const char *filter,
const char *format) {
_cleanup_strv_free_ char **names = NULL, **units = NULL;
_cleanup_free_ char *res = NULL;
char **s;
@@ -230,6 +246,7 @@ static int write_dependency(FILE *f, const char *opts,
r = unit_name_mangle_with_suffix(*s, "as dependency", 0, ".mount", &x);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
r = strv_consume(&units, x);
if (r < 0)
return log_oom();
@@ -249,7 +266,8 @@ static int write_dependency(FILE *f, const char *opts,
}
static int write_after(FILE *f, const char *opts) {
return write_dependency(f, opts, "x-systemd.after", "After=%1$s\n");
return write_dependency(f, opts,
"x-systemd.after", "After=%1$s\n");
}
static int write_requires_after(FILE *f, const char *opts) {
@@ -363,8 +381,8 @@ static int add_mount(
fprintf(f,
"[Unit]\n"
"SourcePath=%s\n"
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
"SourcePath=%s\n",
source);
/* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not
@@ -411,7 +429,14 @@ static int add_mount(
return r;
}
fprintf(f, "\n[Mount]\n");
r = generator_write_blockdev_dependency(f, what);
if (r < 0)
return r;
fprintf(f,
"\n"
"[Mount]\n");
if (original_where)
fprintf(f, "# Canonicalized from %s\n", original_where);
+28 -35
View File
@@ -105,9 +105,8 @@ static int open_parent_block_device(dev_t devnum, int *ret_fd) {
}
static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
_cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
_cleanup_free_ char *e = NULL, *n = NULL, *d = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *p;
int r;
assert(id);
@@ -125,44 +124,28 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
id_escaped = specifier_escape(id);
if (!id_escaped)
return log_oom();
r = generator_open_unit_file(arg_dest, NULL, n, &f);
if (r < 0)
return r;
what_escaped = specifier_escape(what);
if (!what_escaped)
return log_oom();
p = prefix_roota(arg_dest, n);
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
r = generator_write_cryptsetup_unit_section(f, NULL);
if (r < 0)
return r;
fprintf(f,
"# Automatically generated by systemd-gpt-auto-generator\n\n"
"[Unit]\n"
"Description=Cryptography Setup for %%I\n"
"Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
"DefaultDependencies=no\n"
"Conflicts=umount.target\n"
"BindsTo=dev-mapper-%%i.device %s\n"
"Before=umount.target cryptsetup.target\n"
"After=%s\n"
"IgnoreOnIsolate=true\n"
"[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
"TimeoutSec=0\n" /* the binary handles timeouts anyway */
"KeyringMode=shared\n" /* make sure we can share cached keys among instances */
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
d, d,
id_escaped, what_escaped, rw ? "" : "read-only",
id_escaped);
"Conflicts=umount.target\n"
"BindsTo=%s\n"
"After=%s\n",
d, d);
r = generator_write_cryptsetup_service_section(f, id, what, NULL, rw ? NULL : "read-only");
if (r < 0)
return r;
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write file %s: %m", p);
return log_error_errno(r, "Failed to write file %s: %m", n);
r = generator_add_symlink(arg_dest, d, "wants", n);
if (r < 0)
@@ -227,7 +210,6 @@ static int add_mount(
log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)");
if (streq_ptr(fstype, "crypto_LUKS")) {
r = add_cryptsetup(id, what, rw, true, &crypto_what);
if (r < 0)
return r;
@@ -262,6 +244,10 @@ static int add_mount(
if (r < 0)
return r;
r = generator_write_blockdev_dependency(f, what);
if (r < 0)
return r;
fprintf(f,
"\n"
"[Mount]\n"
@@ -370,7 +356,14 @@ static int add_swap(const char *path) {
"# Automatically generated by systemd-gpt-auto-generator\n\n"
"[Unit]\n"
"Description=Swap Partition\n"
"Documentation=man:systemd-gpt-auto-generator(8)\n\n"
"Documentation=man:systemd-gpt-auto-generator(8)\n");
r = generator_write_blockdev_dependency(f, path);
if (r < 0)
return r;
fprintf(f,
"\n"
"[Swap]\n"
"What=%s\n",
path);
+97
View File
@@ -519,6 +519,103 @@ int generator_enable_remount_fs_service(const char *dir) {
SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE);
}
int generator_write_blockdev_dependency(
FILE *f,
const char *what) {
_cleanup_free_ char *escaped = NULL;
int r;
assert(f);
assert(what);
if (!path_startswith(what, "/dev/"))
return 0;
r = unit_name_path_escape(what, &escaped);
if (r < 0)
return log_error_errno(r, "Failed to escape device node path %s: %m", what);
fprintf(f,
"After=blockdev@%s.target\n",
escaped);
return 0;
}
int generator_write_cryptsetup_unit_section(
FILE *f,
const char *source) {
assert(f);
fprintf(f,
"[Unit]\n"
"Description=Cryptography Setup for %%I\n"
"Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
if (source)
fprintf(f, "SourcePath=%s\n", source);
fprintf(f,
"DefaultDependencies=no\n"
"IgnoreOnIsolate=true\n"
"After=cryptsetup-pre.target\n"
"Before=blockdev@dev-mapper-%%i.target\n"
"Wants=blockdev@dev-mapper-%%i.target\n");
return 0;
}
int generator_write_cryptsetup_service_section(
FILE *f,
const char *name,
const char *what,
const char *password,
const char *options) {
_cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *password_escaped = NULL, *options_escaped = NULL;
assert(f);
assert(name);
assert(what);
name_escaped = specifier_escape(name);
if (!name_escaped)
return log_oom();
what_escaped = specifier_escape(what);
if (!what_escaped)
return log_oom();
if (password) {
password_escaped = specifier_escape(password);
if (!password_escaped)
return log_oom();
}
if (options) {
options_escaped = specifier_escape(options);
if (!options_escaped)
return log_oom();
}
fprintf(f,
"\n"
"[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
"TimeoutSec=0\n" /* The binary handles timeouts on its own */
"KeyringMode=shared\n" /* Make sure we can share cached keys among instances */
"OOMScoreAdjust=500\n" /* Unlocking can allocate a lot of memory if Argon2 is used */
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
name_escaped, what_escaped, strempty(password_escaped), strempty(options_escaped),
name_escaped);
return 0;
}
void log_setup_generator(void) {
log_set_prohibit_ipc(true);
log_setup_service();
+15
View File
@@ -27,6 +27,21 @@ int generator_write_timeouts(
const char *opts,
char **filtered);
int generator_write_blockdev_dependency(
FILE *f,
const char *what);
int generator_write_cryptsetup_unit_section(
FILE *f,
const char *source);
int generator_write_cryptsetup_service_section(
FILE *f,
const char *name,
const char *what,
const char *password,
const char *options);
int generator_write_device_deps(
const char *dir,
const char *what,