vmspawn: use fstab.extra credential for runtime mounts instead of kernel cmdline

Switch runtime virtiofs mount configuration from systemd.mount-extra=
kernel command line parameters to the fstab.extra credential. This
avoids consuming kernel command line space (which is limited) and
matches the approach used by mkosi.

Each mount is added as an fstab entry in the format:
  {tag} {destination} virtiofs {ro|rw},x-initrd.mount

If the user already specified a fstab.extra credential via
--set-credential= or --load-credential=, the virtiofs mount entries
are appended to it rather than conflicting.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daan De Meyer
2026-04-02 16:03:29 +02:00
committed by Daan De Meyer
parent 2371c9e798
commit e98a26ddc0
3 changed files with 37 additions and 8 deletions
+3 -3
View File
@@ -447,10 +447,10 @@ char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFl
FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS));
}
char* octescape(const char *s, size_t len) {
char* octescape_full(const char *s, size_t len, const char *bad) {
char *buf, *t;
/* Escapes \ and " chars, in \nnn style escaping. */
/* Escapes all chars in bad, in addition to \ and " chars, in \nnn octal style escaping. */
assert(s || len == 0);
@@ -467,7 +467,7 @@ char* octescape(const char *s, size_t len) {
for (size_t i = 0; i < len; i++) {
uint8_t u = (uint8_t) s[i];
if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"')) {
if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || (bad && strchr(bad, u))) {
*(t++) = '\\';
*(t++) = '0' + (u >> 6);
*(t++) = '0' + ((u >> 3) & 7);
+4 -1
View File
@@ -59,7 +59,10 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
static inline char* xescape(const char *s, const char *bad) {
return xescape_full(s, bad, SIZE_MAX, 0);
}
char* octescape(const char *s, size_t len);
char* octescape_full(const char *s, size_t len, const char *bad);
static inline char* octescape(const char *s, size_t len) {
return octescape_full(s, len, NULL);
}
char* decescape(const char *s, size_t len, const char *bad) _nonnull_if_nonzero_(1, 2);
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags);
+30 -4
View File
@@ -3033,6 +3033,8 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
}
_cleanup_free_ char *fstab_extra = NULL;
for (size_t j = 0; j < arg_runtime_mounts.n_mounts; j++) {
RuntimeMount *m = arg_runtime_mounts.mounts + j;
_cleanup_free_ char *listen_address = NULL;
@@ -3079,15 +3081,39 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
if (r < 0)
return r;
_cleanup_free_ char *clean_target = xescape(m->target, "\":");
if (!clean_target)
/* fstab uses whitespace as field separator, so octal-escape spaces in paths */
_cleanup_free_ char *escaped_target = octescape_full(m->target, SIZE_MAX, " \t");
if (!escaped_target)
return log_oom();
if (strv_extendf(&arg_kernel_cmdline_extra, "systemd.mount-extra=\"%s:%s:virtiofs:%s\"",
id, clean_target, m->read_only ? "ro" : "rw") < 0)
if (strextendf(&fstab_extra, "%s %s virtiofs %s,x-initrd.mount\n",
id, escaped_target, m->read_only ? "ro" : "rw") < 0)
return log_oom();
}
if (fstab_extra) {
/* If the user already specified a fstab.extra credential, combine it with ours */
MachineCredential *existing = machine_credential_find(&arg_credentials, "fstab.extra");
if (existing) {
_cleanup_free_ char *combined = NULL;
if (existing->size > 0 && existing->data[existing->size - 1] != '\n')
r = asprintf(&combined, "%.*s\n%s", (int) existing->size, existing->data, fstab_extra);
else
r = asprintf(&combined, "%.*s%s", (int) existing->size, existing->data, fstab_extra);
if (r < 0)
return log_oom();
erase_and_free(existing->data);
existing->data = TAKE_PTR(combined);
existing->size = r;
} else {
r = machine_credential_add(&arg_credentials, "fstab.extra", fstab_extra, SIZE_MAX);
if (r < 0)
return r;
}
}
_cleanup_(rm_rf_physical_and_freep) char *smbios_dir = NULL;
r = mkdtemp_malloc("/var/tmp/vmspawn-smbios-XXXXXX", &smbios_dir);
if (r < 0)