Skip to content

Commit

Permalink
block: separate raw images from the file protocol
Browse files Browse the repository at this point in the history
We're running into various problems because the "raw" file access, which
is used internally by the various image formats is entangled with the
"raw" image format, which maps the VM view 1:1 to a file system.

This patch renames the raw file backends to the file protocol which
is treated like other protocols (e.g. nbd and http) and adds a new
"raw" image format which is just a wrapper around calls to the underlying
protocol.

The patch is surprisingly simple, besides changing the probing logical
in block.c to only look for image formats when using bdrv_open and
renaming of the old raw protocols to file there's almost nothing in there.

For creating images, a new bdrv_create_file is introduced which guesses the
protocol to use. This allows using qemu-img create -f raw (or just using the
default) for both files and host devices. Converting the other format drivers
to use this function to create their images is left for later patches.

The only issues still open are in the handling of the host devices.
Firstly in current qemu we can specifiy the host* format names
on various command line acceping images, but the new code can't
do that without adding some translation.  Second the layering breaks
the no_zero_init flag in the BlockDriver used by qemu-img.  I'm not
happy how this is done per-driver instead of per-state so I'll
prepare a separate patch to clean this up.

There's some more cleanup opportunity after this patch, e.g. using
separate lists and registration functions for image formats vs
protocols and maybe even host drivers, but this can be done at a
later stage.

Also there's a check for protocol in bdrv_open for the BDRV_O_SNAPSHOT
case that I don't quite understand, but which I fear won't work as
expected - possibly even before this patch.

Note that this patch requires various recent block patches from Kevin
and me, which should all be in his block queue.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
Christoph Hellwig authored and kevmw committed May 3, 2010
1 parent ace22f6 commit 84a12e6
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Makefile.objs
Expand Up @@ -12,7 +12,7 @@ block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o

block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
block-nested-y += parallels.o nbd.o blkdebug.o
block-nested-$(CONFIG_WIN32) += raw-win32.o
Expand Down
74 changes: 45 additions & 29 deletions block.c
Expand Up @@ -54,6 +54,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
static BlockDriver *find_protocol(const char *filename);

static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
QTAILQ_HEAD_INITIALIZER(bdrv_states);
Expand Down Expand Up @@ -203,6 +204,18 @@ int bdrv_create(BlockDriver *drv, const char* filename,
return drv->bdrv_create(filename, options);
}

int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
{
BlockDriver *drv;

drv = find_protocol(filename);
if (drv == NULL) {
drv = bdrv_find_format("file");
}

return bdrv_create(drv, filename, options);
}

#ifdef _WIN32
void get_tmp_filename(char *filename, int size)
{
Expand Down Expand Up @@ -246,6 +259,28 @@ int is_windows_drive(const char *filename)
}
#endif

/*
* Detect host devices. By convention, /dev/cdrom[N] is always
* recognized as a host CDROM.
*/
static BlockDriver *find_hdev_driver(const char *filename)
{
int score_max = 0, score;
BlockDriver *drv = NULL, *d;

QLIST_FOREACH(d, &bdrv_drivers, list) {
if (d->bdrv_probe_device) {
score = d->bdrv_probe_device(filename);
if (score > score_max) {
score_max = score;
drv = d;
}
}
}

return drv;
}

static BlockDriver *find_protocol(const char *filename)
{
BlockDriver *drv1;
Expand All @@ -256,11 +291,16 @@ static BlockDriver *find_protocol(const char *filename)
#ifdef _WIN32
if (is_windows_drive(filename) ||
is_windows_drive_prefix(filename))
return bdrv_find_format("raw");
return bdrv_find_format("file");
#endif
p = strchr(filename, ':');
if (!p)
return bdrv_find_format("raw");
if (!p) {
drv1 = find_hdev_driver(filename);
if (!drv1) {
drv1 = bdrv_find_format("file");
}
return drv1;
}
len = p - filename;
if (len > sizeof(protocol) - 1)
len = sizeof(protocol) - 1;
Expand All @@ -275,28 +315,6 @@ static BlockDriver *find_protocol(const char *filename)
return NULL;
}

/*
* Detect host devices. By convention, /dev/cdrom[N] is always
* recognized as a host CDROM.
*/
static BlockDriver *find_hdev_driver(const char *filename)
{
int score_max = 0, score;
BlockDriver *drv = NULL, *d;

QLIST_FOREACH(d, &bdrv_drivers, list) {
if (d->bdrv_probe_device) {
score = d->bdrv_probe_device(filename);
if (score > score_max) {
score_max = score;
drv = d;
}
}
}

return drv;
}

static BlockDriver *find_image_format(const char *filename)
{
int ret, score, score_max;
Expand All @@ -319,6 +337,7 @@ static BlockDriver *find_image_format(const char *filename)
}

score_max = 0;
drv = NULL;
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (drv1->bdrv_probe) {
score = drv1->bdrv_probe(buf, ret, filename);
Expand Down Expand Up @@ -423,10 +442,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
pstrcpy(bs->filename, sizeof(bs->filename), filename);

if (!drv) {
drv = find_hdev_driver(filename);
if (!drv) {
drv = find_image_format(filename);
}
drv = find_image_format(filename);
}

if (!drv) {
Expand Down
1 change: 1 addition & 0 deletions block.h
Expand Up @@ -57,6 +57,7 @@ BlockDriver *bdrv_find_format(const char *format_name);
BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options);
int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
BlockDriverState *bdrv_new(const char *device_name);
void bdrv_delete(BlockDriverState *bs);
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
Expand Down
15 changes: 10 additions & 5 deletions block/raw-posix.c
Expand Up @@ -768,8 +768,9 @@ static QEMUOptionParameter raw_create_options[] = {
{ NULL }
};

static BlockDriver bdrv_raw = {
.format_name = "raw",
static BlockDriver bdrv_file = {
.format_name = "file",
.protocol_name = "file",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe = NULL, /* no probe for protocols */
.bdrv_open = raw_open,
Expand Down Expand Up @@ -1026,6 +1027,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)

static BlockDriver bdrv_host_device = {
.format_name = "host_device",
.protocol_name = "host_device",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = hdev_probe_device,
.bdrv_open = hdev_open,
Expand Down Expand Up @@ -1140,6 +1142,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)

static BlockDriver bdrv_host_floppy = {
.format_name = "host_floppy",
.protocol_name = "host_floppy",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = floppy_probe_device,
.bdrv_open = floppy_open,
Expand Down Expand Up @@ -1239,6 +1242,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)

static BlockDriver bdrv_host_cdrom = {
.format_name = "host_cdrom",
.protocol_name = "host_cdrom",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = cdrom_probe_device,
.bdrv_open = cdrom_open,
Expand Down Expand Up @@ -1361,6 +1365,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)

static BlockDriver bdrv_host_cdrom = {
.format_name = "host_cdrom",
.protocol_name = "host_cdrom",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = cdrom_probe_device,
.bdrv_open = cdrom_open,
Expand All @@ -1385,13 +1390,13 @@ static BlockDriver bdrv_host_cdrom = {
};
#endif /* __FreeBSD__ */

static void bdrv_raw_init(void)
static void bdrv_file_init(void)
{
/*
* Register all the drivers. Note that order is important, the driver
* registered last will get probed first.
*/
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_file);
bdrv_register(&bdrv_host_device);
#ifdef __linux__
bdrv_register(&bdrv_host_floppy);
Expand All @@ -1402,4 +1407,4 @@ static void bdrv_raw_init(void)
#endif
}

block_init(bdrv_raw_init);
block_init(bdrv_file_init);
12 changes: 7 additions & 5 deletions block/raw-win32.c
Expand Up @@ -238,8 +238,9 @@ static QEMUOptionParameter raw_create_options[] = {
{ NULL }
};

static BlockDriver bdrv_raw = {
.format_name = "raw",
static BlockDriver bdrv_file = {
.format_name = "file",
.protocol_name = "file",
.instance_size = sizeof(BDRVRawState),
.bdrv_open = raw_open,
.bdrv_close = raw_close,
Expand Down Expand Up @@ -395,6 +396,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)

static BlockDriver bdrv_host_device = {
.format_name = "host_device",
.protocol_name = "host_device",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = hdev_probe_device,
.bdrv_open = hdev_open,
Expand All @@ -406,10 +408,10 @@ static BlockDriver bdrv_host_device = {
.bdrv_getlength = raw_getlength,
};

static void bdrv_raw_init(void)
static void bdrv_file_init(void)
{
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_file);
bdrv_register(&bdrv_host_device);
}

block_init(bdrv_raw_init);
block_init(bdrv_file_init);

0 comments on commit 84a12e6

Please sign in to comment.