This topic describes how to resolve an Oops exception that occurs when you hot-unplug a virtio device from an ECS instance running a recent kernel version.
Symptoms
Hot-unplugging a virtio device, such as a disk or NIC, from an ECS instance running a specific recent kernel version can cause an Oops exception, resulting in one of the following outcomes:
-
If the instance is configured with
kernel.panic_on_oops = 1, a kernel panic occurs. -
If the instance is configured with
kernel.panic_on_oops = 0, the kernel becomes unresponsive.
kernel.panic_on_oops is a kernel parameter that controls how the kernel behaves when it encounters an Oops (a kernel error).
-
Kernel panic: The system stops the current task, saves debugging information, and then reboots or shuts down. This allows a quick response to the issue and minimizes potential damage.
-
Kernel unresponsiveness: The kernel attempts to continue running. This is not recommended in production environments because it can lead to data corruption or other critical issues.
Cause
The Linux upstream community introduced this issue in this commit, which added support for the admin virtqueue for virtio devices.
This commit introduced the following changes:
-
An
is_avqfunction pointer was added to thevirtio_pci_devicedefinition to check for the existence of an admin virtqueue. -
The
virtio_pci_modern_probefunction, which is responsible for initializing modern virtio devices, assigns a value to theis_avqfunction pointer.@@ -588,6 +658,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) vp_dev->config_vector = vp_config_vector; vp_dev->setup_vq = setup_vq; vp_dev->del_vq = del_vq; + vp_dev->is_avq = vp_is_avq; vp_dev->isr = mdev->isr; vp_dev->vdev.id = mdev->id; -
When a virtio device is hot-unplugged, the code checks whether the current queue is an admin virtqueue.
@@ -236,6 +236,9 @@ void vp_del_vqs(struct virtio_device *vdev) int i; list_for_entry_safe(vq, n, &vdev->vqs, list) { + if (vp_dev->is_avq(vdev, vq->index)) + continue; + if (vp_dev->per_vq_vectors) { int v = vp_dev->vqs[vq->index]->msix_vector; } }
However, for legacy virtio devices, the is_avq function pointer is not initialized and remains a null pointer. As a result, when you hot-unplug a legacy virtio device, the call toif (vp_dev->is_avq(vdev, vq->index)) attempts to dereference a null pointer. This triggers an exception, which can cause a system crash.
Affected scope
-
Linux upstream community
The upstream community has resolved this issue in this commit. The fix adds a null check for the
is_avqfunction pointer before calling it. -
Operating system
-
Ubuntu 24
-
Other operating systems with kernel versions around 6.8 that have incorporated admin virtqueue support but lack the is_avq null check patch.
NoteYou can run the
uname -rcommand to check the kernel version.
-
-
virtio device
This issue affects legacy virtio devices when they are hot-unplugged from ECS instances.
Solutions
-
Solution 1: Switch to an instance family that uses modern virtio devices, such as 8th-generation or later instance families. These instance families are not affected by this issue. For more information, see Change instance types. To learn more about instance families, see Instance families.
-
Solution 2:
-
Upgrade to the latest kernel package and verify that it includes the virtio-pci: Check if is_avq is NULL patch.
-
(Conditionally required) If the latest kernel does not include the patch, you must apply it manually.
-
Appendix: Terms
This section explains key terms used in this topic, such as virtio device, admin virtqueue, and virtio_pci_device.
|
Term |
Description |
|
virtio device |
Virtio is a standardized framework for I/O virtualization that allows virtual machines to efficiently interact with a host's virtual hardware. A virtio device, such as a disk or NIC, is an emulated device in a virtualized environment. These devices are classified as either legacy or modern, distinguished primarily by the configuration interface they use. |
|
admin virtqueue |
An admin virtqueue is a special queue used for device management operations, such as querying device status or applying configuration changes. Not all virtio devices support an admin virtqueue. |
|
virtio_pci_device |
This is the data structure within the kernel that represents a virtio PCI device. It contains pointers to various functions, including the |
|
is_avq |
A function pointer that, when assigned, points to a function that checks whether a given virtio queue is an admin virtqueue. |
|
virtio_pci_modern_probe |
This function is responsible for detecting and initializing a virtio PCI device. After the system discovers a device, this function is called to complete the setup, which includes reading the configuration space, detecting device features, and allocating necessary resources. |
|
RIP |
The RIP (Instruction Pointer) register in an x86 CPU stores the address of the next instruction to execute. When an exception occurs, such as an attempt to dereference a null pointer, the RIP points to the address of the faulting instruction. |