How QEMU Block Driver Works

Preface

Today is the first day of GSoC 2011. I’m starting working on improving VMDK support of QEMU block driver. The most important thing before I can code is to understand well how QEMU block driver works. So here a very basic description of QEMU block driver code structure is given.

Overview

In the source tree dir ‘block/’ there are quite a few files, each is a block driver and is used to access a particular type of device, format or protocol. E.g. raw-{posix, win32}.c are drivers for local files. All these drivers are self-registered and runtime instanced by block.c. Before going to the driver internals, let’s have a look at how block.c uses the drivers.

Example

Let’s go with a very simple example, assuming that there is an QED image: /media/F/VM/test.qed, and we run qemu-img info /media/F/VM/test.qed to query the info. The program successfully get what we want:

image: /media/F/VM/test.qed file format: qed virtual size: 32G (34359738368 bytes) disk size: 2.3G cluster_size: 65536

Explanation

So what happened during the program progress? At first qemu-img.c only gets a pathname string “/media/F/VM/test.qed“, and it calls ‘block.c: bdrv_open()‘ with it, everything is done there. In block.c, a protocol is found for the actual IO of image file. As it is a common disk file, the basic protocal “file” is used, which is a driver implemented in block/raw-{posix, win32}.c. Using the protocal driver, metadata or magic number is read to probe for the possible driver in a traverse through all drivers. As long as a proper driver is found, it is instanced to handle the image file and become responsible to retrieve any concrete information (that we saw from qemu-img output).

Each driver instance contains a set of operations (function pointers) and two kinds of data holding the instance state, the common data and the driver specific data. The operation and common data structures are defined in block_int.h, they are struct BlockDriver and struct BlockDriverState. The driver specific data structures are defined in each driver implementation .c files in block/. For example struct BDRVVmdkState in block/vmdk.c. The BlockDriverState structure is the main struct for a driver instance, inside which there are pointers to BlockDriver (.drv) and specific state data (.opaque). So every time a driver instance is accessed, a BlockDriverState structure pointer is passed.

Having BlockDriverState in hand, it becomes easy to figure out how block driver works, calling functions in BlockDriver can make vmdk driver to perform various work (probe, open or rw the image, or even creating an initial image file), where driver further access the protocol driver for IO. The protocol driver instance is save in .file field, which is also a BlockDriverState. We can see here the driver is cascaded, this is also the case for backing file support, which in theory make it possible that one kind of image format use another format as its backing file.

Conclusion

QEMU block driver is designed very modular, in order to improve some format support, the needed modification can be very local. The overall process of block device handling is hidden from the driver implementation, as a result device drivers are considerably maintainable.

Comments