Jeff Cody
Red Hat, Inc.
A QEMU
block driver provides storage on the host, that the guest sees as a drive.
In the QEMU code, they are located in the block/
directory.
Provide a structured way to store data, often with built-in features (such as snapshots, data sparseness, drive metadata, etc..).
Examples
Provides the underlying data I/O for image formats, although may also be a stand-alone driver as well.
Examples include:
Network-based protocols drivers in QEMU:
Host protocols drivers in QEMU:
The BlockDriver
struct contains the block-layer internal API to the format driver. It consists mainly of function pointers, used to interface with the driver.
.bdrv_open
.bdrv_co_readv
etc..
We'll get into these more later.
00000000 76 68 64 78 66 69 6c 65 51 00 45 00 4d 00 55 00 |vhdxfileQ.E.M.U.|
00000010 20 00 76 00 31 00 2e 00 36 00 2e 00 35 00 30 00 | .v.1...6...5.0.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 b8 |QFI.............|
QCOW2
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
if (buf_size >= sizeof(QCowHeader) &&
be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
be32_to_cpu(cow_header->version) >= 2)
return 100;
else
return 0;
}
(Simplified view, as relevant to an Image Format Driver)
At the minimum, we need:
Let's see this as code.
#include "block/block_int.h"
/* Our open function */
static int silly_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
return 0;
}
/* Our attributes / functions */
static BlockDriver bdrv_silly = {
.format_name = "silly",
.bdrv_open = silly_open
};
/* register our BlockDrivers */
static void bdrv_silly_init(void)
{
bdrv_register(&bdrv_silly);
}
/* macro magic, creates an init function */
block_init(bdrv_silly_init);
Most Block Drivers require state data, populated on open.
The BlockDriverState struct is passed to most functions. The "opaque" field is for your driver's internal data.
At a minimum, your .bdrv_open must:
Reopen allows QEMU to open an image chain with different flags
Reopen has three hooks:
.bdrv_reopen_prepare()
, required if reopen supported
Depending on what your driver needs to support reopen, you may also need to provide the commit and abort functions, but these are optional
Block driver read / write operations all make use of coroutines
Coroutines allow asynchronous code to masquerade as synchronous code
(Despite sounding complex, this makes life easier for you!)
Control stays with your coroutine until you either yield, or return
qemu_co_mutex_lock
)qemu_coroutine_yeild()
)
Simplied read flow, for an Image Format driver using I/O vectors
Simplied write flow, for an Image Format driver using I/O vectors
This can cause problems
During Live Migration, the image format metadata may differ from your cache.
You can either invalidate the metadata when requested, or prevent migration
static BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcowState),
.bdrv_probe = qcow2_probe,
.bdrv_open = qcow2_open,
.bdrv_close = qcow2_close,
.bdrv_reopen_prepare = qcow2_reopen_prepare,
.bdrv_create = qcow2_create,
/* snipped */
.bdrv_co_readv = qcow2_co_readv,
.bdrv_co_writev = qcow2_co_writev,
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
/* more snipped */
.create_options = qcow2_create_options,
};
If you are reading or writing data structures from / to disk, please:
Unvalidated data can be security risks:
Make sure that your driver will work on all platforms
If you don't do this, your driver may work fine on your system.
.bdrv_co_get_block_status
Look at BlockDriver struct in include/block/block_int.h