Closed ru-fu closed 1 year ago
Follow-up bug: After increasing the disk size and rebooting the host machine & host VM, trying to launch another VM with the same image fails:
root@vm:~# lxc image list
+-------+--------------+--------+-------------------------------------+--------------+-----------------+-----------+-----------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+-------+--------------+--------+-------------------------------------+--------------+-----------------+-----------+-----------------------------+
| | 215974d90318 | no | Ubuntu lunar amd64 (20230503_07:42) | x86_64 | VIRTUAL-MACHINE | 1117.81MB | May 4, 2023 at 7:18am (UTC) |
+-------+--------------+--------+-------------------------------------+--------------+-----------------+-----------+-----------------------------+
root@vm:~# lxc launch images:ubuntu/23.04/desktop --vm
Creating the instance
Error: Failed instance creation: Failed creating instance from image: Failed to run: zfs clone -o volmode=none default/images/215974d90318b9cc725ca06d5f4a88914baab5c82799cad28ea5311c5bdd06e9.block@readonly default/virtual-machines/wondrous-ladybird.block: exit status 1 (cannot open 'default/images/215974d90318b9cc725ca06d5f4a88914baab5c82799cad28ea5311c5bdd06e9.block@readonly': dataset does not exist)
I reproduced this issue, but I don't think there is much we can do about it. You've effectively emulated a defective hard disk.
My understanding is that you were launching a VM with a 4GiB root disk, and then installing LXD inside it and using a ZFS storage pool on a loop file inside the VM (which LXD sets at a minimum size of 5GiB) and then trying to create a large nested VM (using images:ubuntu/23.04/desktop
) on that pool.
This would have caused the outer VM's root disk filesystem to fill up, which would have then presented as a disk I/O problem to the ZFS pool running on the loop file (because the loop file is of a fixed size, but that full size cannot be realised), causing the warning:
[ 192.622010] WARNING: Pool 'default' has encountered an uncorrectable I/O failure and has been suspended.
/dev/sda2 3.8G 3.7G 0 100% /
Then the qemu-img process hangs, and even when its killed it then goes into a defunct state, presumably because of blocked I/O:
root 3366 0.0 1.1 1097708 11552 pts/0 Sl+ 13:27 0:00 /snap/lxd/24871/bin/lxc launch images:ubuntu/23.04/desktop --vm
root 3567 1.2 0.0 0 0 ? ZNsl 13:27 0:14 [qemu-img] <defunct>
I've looked at the go routine list in LXD when that happens, and found this:
goroutine 682 [syscall, 7 minutes]:
syscall.Syscall6(0x7fd94c3b9678?, 0x7fd975314108?, 0x10?, 0xc000374c00?, 0xc000bde620?, 0x0?, 0x686690?)
/snap/go/current/src/syscall/syscall_linux.go:91 +0x36
os.(*Process).blockUntilWaitable(0xc000af3830)
/snap/go/current/src/os/wait_waitid.go:32 +0x87
os.(*Process).wait(0xc000af3830)
/snap/go/current/src/os/exec_unix.go:22 +0x28
os.(*Process).Wait(...)
/snap/go/current/src/os/exec.go:132
github.com/lxc/lxd/shared/subprocess.(*Process).start.func3()
/build/lxd/parts/lxd/src/shared/subprocess/proc.go:176 +0x6c
created by github.com/lxc/lxd/shared/subprocess.(*Process).start
/build/lxd/parts/lxd/src/shared/subprocess/proc.go:173 +0x6f8
This is Go waiting on the qemu-img process to finish, and because its in a defunct state it never will. Go is actually waiting on the kernel to return from waitid syscall (https://linux.die.net/man/3/waitid).
The problem is that by this point you have to stop the VM forcefully, crashing LXD, in order to grow the underlying filesystem, at which point the revert logic inside LXD that would have deleted the image storage volume record will not run as LXD is killed.
This then leaves an image storage volume record in the DB, but the actual ZFS volume doesn't exist, and hence on next init/launch you get the error:
Error: Failed instance creation: Failed creating instance from image: Failed to run: zfs clone -o volmode=none default/images/215974d90318b9cc725ca06d5f4a88914baab5c82799cad28ea5311c5bdd06e9.block@readonly default/virtual-machines/wondrous-ladybird.block: exit status 1 (cannot open 'default/images/215974d90318b9cc725ca06d5f4a88914baab5c82799cad28ea5311c5bdd06e9.block@readonly': dataset does not exist)
In theory one way to avoid getting into this state is to avoid making the loop file bigger than the available free space on the root disk. So rather than setting a minimum size of 5GiB we could set it smaller or detect insufficient free space and refuse to create the pool.
However this does not guarantee that we won't be able to get into this state another time by having plenty of free space when the pool is created, and then filling the disk later such that the same problem occurs.
@stgraber could we do something with loopFileSizeDefault
so that it prevents pool creation using a loop file size that is larger than the free space at the time the pool is created. It wouldn't be a panacea but might avoid accidental situations like this.
Currently its using filesystem size as a basis for calculation of pool loop file, whereas it could use filesystem free space as the basis. And then fail if there isn't at least 5GiB free.
Yeah, we can make it use free space instead.
When launching an instance on a host VM with a small disk (4GiB), there isn't enough space to fully unpack the image. The process hangs at "Unpack: 100%". However, both instance and image are created and can be listed. When killing the
qemu-img convert
process, no cleanup happens, and the image and instance are still in the list.Creating a VM on a host VM with too little disk space:
Log from lxc monitor (long time without output after):
The image is already listed, but it's still busy converting:
Killing the process does not trigger cleanup:
(Kill at 12:11)