Klemens Nanni <k...@openbsd.org> writes:

> kern.version=OpenBSD 7.4-current (GENERIC.MP) #1667: Wed Feb  7 20:09:35 MST 
> 2024
>     dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
>
> This boots fine:
>
>       # cat /tmp/vm.conf
>       vm foo {
>               disable
>               disk /tmp/linux.qcow2
>       }
>       # `which vmd`
>       # vmctl start -c foo
>       Welcome to Alpine Linux 3.19
>       Kernel 6.6.11-0-virt on an x86_64 (/dev/ttyS0)
>
>       foo login:
>
> This terminates the VM immediately after startup:
>
>       # cat /tmp/vm.conf
>       vm foo {
>               disable
>               disk /tmp/linux.qcow2
>               interface
>       }
>       # `which vmd` -dvv
>
> vmd: startup
> vmd: vm_register: registering vm 1
> vmd: /tmp/vm.conf:5: vm "foo" registered (disabled)
> vmd: vmd_configure: setting staggered start configuration to parallelism: 12 
> and delay: 30
> vmd: vmd_configure: starting vms in staggered fashion
> vmd: start_vm_batch: starting batch of 12 vms
> vmd: start_vm_batch: not starting vm foo (disabled)
> vmd: start_vm_batch: done starting vms
> priv: config_getconfig: priv retrieving config
> agentx: config_getconfig: agentx retrieving config
> vmm: config_getconfig: vmm retrieving config
> control: config_getconfig: control retrieving config
>
>       # vmctl start -c foo
>
> vmd: vm_opentty: vm foo tty /dev/ttyp7 uid 0 gid 4 mode 620
> vmm: vm_register: registering vm 1
> vmd: vm_priv_ifconfig: interface tap0 description vm1-if0-foo
> vmd: started foo (vm 1) successfully, tty /dev/ttyp7
> vm/foo: loadfile_bios: loaded BIOS image
> vm/foo: pic_set_elcr: setting level triggered mode for irq 3
> vm/foo: pic_set_elcr: setting level triggered mode for irq 5
> vm/foo: virtio_init: vm "foo" vio0 lladdr fe:e1:bb:d1:ec:81
> vm/foo: pic_set_elcr: setting level triggered mode for irq 6
> vm/foo: foo: launching vioblk0
> vm/foo: virtio_dev_launch: sending 'd' type device struct
> vm/foo: virtio_dev_launch: sending vm message for 'foo'
> vm/foo/vioblk: vioblk_main: got viblk dev. num disk fds = 2, sync fd = 17, 
> async fd = 19, capacity = 0 seg_max = 126, vmm fd = 5
> vm/foo/vioblk0: qc2_open: qcow2 disk version 3 size 10737418240 end 
> 7340359680 snap 0
> vm/foo/vioblk0: qc2_open: qcow2 disk version 3 size 10737418240 end 
> 1433206784 snap 0
> vm/foo/vioblk0: vioblk_main: initialized vioblk0 with qcow2 image 
> (capacity=20971520)
> vm/foo/vioblk0: vioblk_main: wiring in async vm event handler (fd=19)
> vm/foo/vioblk0: vm_device_pipe: initializing 'd' device pipe (fd=19)
> vm/foo/vioblk0: vioblk_main: wiring in sync channel handler (fd=17)
> vm/foo/vioblk0: vioblk_main: telling vm foo device is ready
> vm/foo/vioblk0: vioblk_main: sending heartbeat
> vm/foo: virtio_dev_launch: receiving reply
> vm/foo: virtio_dev_launch: device reports ready via sync channel
> vm/foo: vm_device_pipe: initializing 'd' device pipe (fd=18)
> vm/foo: foo: launching vionet0
> vm/foo: virtio_dev_launch: sending 'n' type device struct
> vmm: vmm_sighdlr: handling signal 20
> vmm: vmm_sighdlr: terminated vm foo (id 1)
> vmm: vm_remove: vmm vmm_sighdlr removing vm 1 from running config
> vmm: vm_stop: vmm vmm_sighdlr stopping vm 1
> vmd: vm_stop: vmd vmd_dispatch_vmm stopping vm 1
> vm/foo/vionet: failed to receive vionet: Bad file descriptor
> vm/foo/vioblk0: handle_sync_io: vioblk pipe dead (EV_READ)
> vm/foo/vioblk0: dev_dispatch_vm: pipe dead (EV_READ)
>
>       Connected to /dev/ttyp7 (speed 115200)
>
>       [EOT]

Try this diff. There was an issue in the order of closing disk fds. I
also noticed we're not closing the sockets when closing the data fds, so
that's added into virtio_dev_closefds().

With this i can boot a guest that uses a network interface and a qcow2
disk image with a base image.

diff refs/heads/master refs/heads/vmd-fd-fix
commit - 06bc238730aac28903aeab0d96b2427760b0110a
commit + 8e46c12aa617cf136fdb3557f0177d41adb4d9d9
blob - afe3dd8f7a48cde226a4438567a8a3eb9dac2dce
blob + ce052097a463bed0e75775d7acb2f036ca111572
--- usr.sbin/vmd/virtio.c
+++ usr.sbin/vmd/virtio.c
@@ -1301,8 +1301,8 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev
 {
        char *nargv[12], num[32], vmm_fd[32], vm_name[VM_NAME_MAX], t[2];
        pid_t dev_pid;
-       int data_fds[VM_MAX_BASE_PER_DISK], sync_fds[2], async_fds[2], ret = 0;
-       size_t i, data_fds_sz, sz = 0;
+       int sync_fds[2], async_fds[2], ret = 0;
+       size_t sz = 0;
        struct viodev_msg msg;
        struct virtio_dev *dev_entry;
        struct imsg imsg;
@@ -1310,14 +1310,10 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev

        switch (dev->dev_type) {
        case VMD_DEVTYPE_NET:
-               data_fds[0] = dev->vionet.data_fd;
-               data_fds_sz = 1;
                log_debug("%s: launching vionet%d",
                    vm->vm_params.vmc_params.vcp_name, dev->vionet.idx);
                break;
        case VMD_DEVTYPE_DISK:
-               memcpy(&data_fds, dev->vioblk.disk_fd, sizeof(data_fds));
-               data_fds_sz = dev->vioblk.ndisk_fd;
                log_debug("%s: launching vioblk%d",
                    vm->vm_params.vmc_params.vcp_name, dev->vioblk.idx);
                break;
@@ -1359,10 +1355,6 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev
                dev->sync_fd = sync_fds[1];
                dev->async_fd = async_fds[1];

-               /* Close data fds. Only the child device needs them now. */
-               for (i = 0; i < data_fds_sz; i++)
-                       close_fd(data_fds[i]);
-
                /* 1. Send over our configured device. */
                log_debug("%s: sending '%c' type device struct", __func__,
                        dev->dev_type);
@@ -1373,6 +1365,13 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev
                        goto err;
                }

+               /* Close data fds. Only the child device needs them now. */
+               if (virtio_dev_closefds(dev) == -1) {
+                       log_warnx("%s: failed to close device data fds",
+                           __func__);
+                       goto err;
+               }
+
                /* 2. Send over details on the VM (including memory fds). */
                log_debug("%s: sending vm message for '%s'", __func__,
                        vm->vm_params.vmc_params.vcp_name);
@@ -1775,5 +1774,10 @@ virtio_dev_closefds(struct virtio_dev *dev)
                return (-1);
        }

+       close_fd(dev->async_fd);
+       dev->async_fd = -1;
+       close_fd(dev->sync_fd);
+       dev->sync_fd = -1;
+
        return (0);
 }

Reply via email to