Lifecycle of a vdev

Updated: October 28, 2024

Below is an overview of the lifecycle of a vdev, from initialization to termination.

For examples of source code that look after each stage of a vdev's lifecycle, see the next chapter: The Basics: vdev trace.

Overview

The lifecycle of a vdev can be divided into two stages:

The figure below presents the lifecycle of a vdev. Notice the Startup/Running demarcation, identified by the VDEV_CTRL_GUEST_CONFIGURED callback.



Figure 1. Virtual device lifecycle

Determining when startup is complete

When you write a vdev, you must include code to identify the demarcation between your vdev's startup stage and its running stage, because some functions may be called only during the startup stage, when the qvm process instance is assembling the VM, including the vdevs. Others may be called only after the startup stage has completed, when the system is running.

When the qvm process is completing the vdev and VM configuration, it will issue callbacks that your vdev can use to identify when the startup stage ends and the running stage has begun:

VDEV_CTRL_OPTIONS_END
The qvm process has finished parsing your vdev's options. It may not have completed configuring the VM, however: it may still have other vdevs and VM components to configure.
While some vdev API functions that should only be used after startup is complete may be safely called after the VDEV_CTRL_OPTIONS_END callback, many can't be called safely at this point (e.g., vdev_path()). It is best to wait for the VDEV_CTRL_GUEST_CONFIGURED callback before calling any of these functions.
VDEV_CTRL_ASSIGN
All user-specified options have been processed. The vdev must now check if the loc and intr options have been specified; if they haven't been specified, and the vdev will use them, the vdev must specify them for itself.
VDEV_CTRL_GUEST_CONFIGURED
The qvm process has finished configuring the VM for the guest system. It is safe to create threads, and to call functions that should only be used after startup is complete (e.g., vdev_path()).
From this point forward, your code must assume that it is running in a multi-threaded environment.
VDEV_CTRL_GUEST_STARTING
The qvm process is about to start the guest. This callback marks the point at which the qvm process is about to change the state of the vCPU thread that will start the guest.
As mentioned above, VDEV_CTRL_GUEST_CONFIGURED is used to determine if the qvm process has finished configuring the VM for the guest system; don't use VDEV_CTRL_GUEST_STARTING for this purpose.

Protecting your vdev in a multi-threaded environment

When a qvm process instance is in its startup stage (i.e., assembling and configuring a VM), it is single-threaded: it runs with only a main thread executing code. This means that your vdev can skip some tasks that are required after the VM is ready and the guest has started executing. For example, your vdev doesn't need to call gasp_lock() and gasp_unlock() around other calls to gasp_*() functions (see Guest memory regions and the Virtual Device Developer's API Reference gasp.h chapter).

When the guest starts executing, it requires at least one vCPU, which adds a vCPU thread, so the qvm process instance must run at least two threads: the main thread and the vCPU thread. This means that your vdev is running in a multi-threaded environment and must use lock functions such as gasp_lock() to ensure that no other entity in your VM (e.g., another vdev) interferes with your vdev's resources.

  翻译: