From 9b5ba882bd9ae4e0ed270289eada03c2040fefe2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 Sep 2025 22:25:06 +0200 Subject: [PATCH 1/2] vmspawn: initialize block device "serials" from backing file name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we pass multiple block devices into a VM it's really useful to pass recognizable serial numbers on them, so that we know which one is which. qemu allows setting them, hence initialize them automatically from the filename of the backing file, as a convenience feature. Inside of a VM this means /dev/disk/by-id/… symlinks will be generated with useful identifiers. --- src/vmspawn/vmspawn.c | 51 +++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 544710d310..8d3d168afe 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -2094,24 +2094,30 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { } if (arg_image) { - _cleanup_free_ char *escaped_image = NULL; - assert(!arg_directory); - r = strv_extend(&cmdline, "-drive"); - if (r < 0) + if (strv_extend(&cmdline, "-drive") < 0) return log_oom(); - escaped_image = escape_qemu_value(arg_image); + _cleanup_free_ char *escaped_image = escape_qemu_value(arg_image); if (!escaped_image) return log_oom(); - r = strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=raw,discard=%s", escaped_image, on_off(arg_discard_disk)); - if (r < 0) + if (strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=raw,discard=%s", escaped_image, on_off(arg_discard_disk)) < 0) return log_oom(); - r = strv_extend_many(&cmdline, "-device", "virtio-blk-pci,drive=vmspawn,bootindex=1"); - if (r < 0) + _cleanup_free_ char *image_fn = NULL; + if (path_extract_filename(arg_image, &image_fn) < 0) + return log_error_errno(r, "Failed to extract filename from path '%s': %m", image_fn); + + _cleanup_free_ char *escaped_image_fn = escape_qemu_value(image_fn); + if (!escaped_image_fn) + return log_oom(); + + if (strv_extend(&cmdline, "-device") < 0) + return log_oom(); + + if (strv_extendf(&cmdline, "virtio-blk-pci,drive=vmspawn,bootindex=1,serial=%s", escaped_image_fn) < 0) return log_oom(); r = grow_image(arg_image, arg_grow_image); @@ -2186,21 +2192,18 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { size_t i = 0; STRV_FOREACH(drive, arg_extra_drives) { - _cleanup_free_ char *escaped_drive = NULL; - const char *driver = NULL; - struct stat st; - - r = strv_extend(&cmdline, "-blockdev"); - if (r < 0) + if (strv_extend(&cmdline, "-blockdev") < 0) return log_oom(); - escaped_drive = escape_qemu_value(*drive); + _cleanup_free_ char *escaped_drive = escape_qemu_value(*drive); if (!escaped_drive) return log_oom(); + struct stat st; if (stat(*drive, &st) < 0) return log_error_errno(errno, "Failed to stat '%s': %m", *drive); + const char *driver = NULL; if (S_ISREG(st.st_mode)) driver = "file"; else if (S_ISBLK(st.st_mode)) @@ -2208,16 +2211,22 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected regular file or block device, not '%s'.", *drive); - r = strv_extendf(&cmdline, "driver=raw,cache.direct=off,cache.no-flush=on,file.driver=%s,file.filename=%s,node-name=vmspawn_extra_%zu", driver, escaped_drive, i); - if (r < 0) + if (strv_extendf(&cmdline, "driver=raw,cache.direct=off,cache.no-flush=on,file.driver=%s,file.filename=%s,node-name=vmspawn_extra_%zu", driver, escaped_drive, i) < 0) return log_oom(); - r = strv_extend(&cmdline, "-device"); + _cleanup_free_ char *drive_fn = NULL; + r = path_extract_filename(*drive, &drive_fn); if (r < 0) + return log_error_errno(r, "Failed to extract filename from path '%s': %m", *drive); + + _cleanup_free_ char *escaped_drive_fn = escape_qemu_value(drive_fn); + if (!escaped_drive_fn) return log_oom(); - r = strv_extendf(&cmdline, "scsi-hd,drive=vmspawn_extra_%zu", i++); - if (r < 0) + if (strv_extend(&cmdline, "-device") < 0) + return log_oom(); + + if (strv_extendf(&cmdline, "scsi-hd,drive=vmspawn_extra_%zu,serial=%s", i++, escaped_drive_fn) < 0) return log_oom(); } From 2f473de3cb4b906964574c95384c7487c6ff3864 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Sep 2025 09:36:29 +0200 Subject: [PATCH 2/2] vmspawn: support specfiying relative paths to tpm state dir, by prefixing with ./ --- src/vmspawn/vmspawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 8d3d168afe..56b1c09053 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -628,7 +628,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_TPM_STATE: - if (path_is_absolute(optarg) && path_is_valid(optarg)) { + if (path_is_valid(optarg) && (path_is_absolute(optarg) || path_startswith(optarg, "./"))) { r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm_state_path); if (r < 0) return r;