]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn: add nvme disk type support 41301/head
authorChristian Brauner <brauner@kernel.org>
Tue, 24 Mar 2026 13:44:34 +0000 (14:44 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 24 Mar 2026 15:53:41 +0000 (16:53 +0100)
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>
man/systemd-vmspawn.xml
shell-completion/bash/systemd-vmspawn
src/vmspawn/vmspawn-settings.c
src/vmspawn/vmspawn-settings.h
src/vmspawn/vmspawn.c

index 80798f7354c611e39cb7dba1985780dd94cdb791..eec52f1374259b1049d7a2a1f16b77de86a05ea3 100644 (file)
 
           <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>
index 955c59bef5bd87d3249c71d9b13bb8c06226c6da..718cb300ce4043e2de5ea060057c5135594a0516 100644 (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
index 2e594e59b253c3f336e0397032586868e4ffd022..7c30ed753f56ef7757a04a020b5393cbd788dd5b 100644 (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);
index 2fe3b84297d6295c56bc958220610f4b7cae2960..252ceecceb9a1cc49abadc6243dceea682ee2f7c 100644 (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;
index 4abc54675b83f79094aa71e70d051fc30d7b6edf..72aa39e18a4e5e3a400b9f9f6f6d142573ec0878 100644 (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();
                 }