vmspawn: add nvme disk type support

Extend --image-disk-type= and the --extra-drive= disk type prefix to
support nvme in addition to virtio-blk and virtio-scsi:

  systemd-vmspawn --image-disk-type=nvme --image=image.raw
  systemd-vmspawn --image=image.raw --extra-drive=nvme:data.raw

The NVMe serial number is limited to 20 characters by the NVMe spec.
If the image filename exceeds this, it is hashed with SHA-256 and
truncated to 20 hex characters via the disk_serial() helper introduced
in the previous commit.

Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner
2026-03-24 16:53:41 +01:00
parent e4a58c38e9
commit b76e1732f7
5 changed files with 28 additions and 7 deletions
+3 -2
View File
@@ -130,8 +130,9 @@
<listitem><para>Specifies the disk type to use for the root disk passed to <option>--image=</option>.
Extra drives added via <option>--extra-drive=</option> inherit this disk type unless overridden
with an explicit disk type prefix. Takes one of <literal>virtio-blk</literal> or
<literal>virtio-scsi</literal>. Defaults to <literal>virtio-blk</literal>.</para>
with an explicit disk type prefix. Takes one of <literal>virtio-blk</literal>,
<literal>virtio-scsi</literal>, or <literal>nvme</literal>. Defaults to
<literal>virtio-blk</literal>.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
+1 -1
View File
@@ -61,7 +61,7 @@ _systemd_vmspawn() {
elif __contains_word "$prev" ${OPTS[IMAGE_FORMAT]}; then
comps='raw qcow2'
elif __contains_word "$prev" ${OPTS[IMAGE_DISK_TYPE]}; then
comps='virtio-blk virtio-scsi'
comps='virtio-blk virtio-scsi nvme'
elif __contains_word "$prev" ${OPTS[ARG]}; then
comps=''
else
+1
View File
@@ -13,6 +13,7 @@ DEFINE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
static const char *const disk_type_table[_DISK_TYPE_MAX] = {
[DISK_TYPE_VIRTIO_BLK] = "virtio-blk",
[DISK_TYPE_VIRTIO_SCSI] = "virtio-scsi",
[DISK_TYPE_NVME] = "nvme",
};
DEFINE_STRING_TABLE_LOOKUP(disk_type, DiskType);
+1
View File
@@ -13,6 +13,7 @@ typedef enum ImageFormat {
typedef enum DiskType {
DISK_TYPE_VIRTIO_BLK,
DISK_TYPE_VIRTIO_SCSI,
DISK_TYPE_NVME,
_DISK_TYPE_MAX,
_DISK_TYPE_INVALID = -EINVAL,
} DiskType;
+22 -4
View File
@@ -209,7 +209,7 @@ static int help(void) {
" -i --image=FILE|DEVICE Root file system disk image or device for the VM\n"
" --image-format=FORMAT Specify disk image format (raw, qcow2; default: raw)\n"
" --image-disk-type=TYPE\n"
" Specify disk type (virtio-blk, virtio-scsi)\n"
" Specify disk type (virtio-blk, virtio-scsi, nvme; default: virtio-blk)\n"
"\n%3$sHost Configuration:%4$s\n"
" --cpus=CPUS Configure number of CPUs in guest\n"
" --ram=BYTES Configure guest's RAM size\n"
@@ -251,8 +251,9 @@ static int help(void) {
" --bind-ro=SOURCE[:TARGET]\n"
" Mount a file or directory, but read-only\n"
" --extra-drive=[FORMAT:][DISKTYPE:]PATH\n"
" Adds an additional disk to the virtual machine\n"
" (FORMAT: raw, qcow2; DISKTYPE: virtio-blk, virtio-scsi)\n"
" Adds an additional disk to the VM\n"
" FORMAT: raw, qcow2\n"
" DISKTYPE: virtio-blk, virtio-scsi, nvme\n"
" --bind-user=NAME Bind user from host to virtual machine\n"
" --bind-user-shell=BOOL|PATH\n"
" Configure the shell to use for --bind-user= users\n"
@@ -1994,7 +1995,7 @@ static int make_sidecar_path(const char *suffix, char **ret) {
return 0;
}
/* Device serial numbers have length limits (e.g. 30 for SCSI).
/* Device serial numbers have length limits (e.g. 20 for NVMe, 30 for SCSI).
* If the filename fits, use it directly; otherwise hash it with SHA-256 and
* take the first max_len hex characters. max_len must be even and <= 64.
* The filename should already be QEMU-escaped (commas doubled) so that the
@@ -2593,6 +2594,14 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
break;
}
case DISK_TYPE_NVME: {
_cleanup_free_ char *serial = NULL;
if (disk_serial(escaped_image_fn, 20, &serial) < 0)
return log_oom();
if (strv_extend_joined(&cmdline, "nvme,drive=vmspawn,bootindex=1,serial=", serial) < 0)
return log_oom();
break;
}
default:
assert_not_reached();
}
@@ -2737,6 +2746,15 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
break;
}
case DISK_TYPE_NVME: {
_cleanup_free_ char *serial = NULL;
r = disk_serial(escaped_drive_fn, 20, &serial);
if (r < 0)
return log_oom();
if (strv_extendf(&cmdline, "nvme,drive=vmspawn_extra_%zu,serial=%s", i++, serial) < 0)
return log_oom();
break;
}
default:
assert_not_reached();
}