diff --git a/Makefile.objs b/Makefile.objs index 1c7c64b1d8..4f65bfbae5 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -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 diff --git a/block.c b/block.c index 7974215ea4..ad681db564 100644 --- a/block.c +++ b/block.c @@ -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); @@ -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) { @@ -246,35 +259,6 @@ int is_windows_drive(const char *filename) } #endif -static BlockDriver *find_protocol(const char *filename) -{ - BlockDriver *drv1; - char protocol[128]; - int len; - const char *p; - -#ifdef _WIN32 - if (is_windows_drive(filename) || - is_windows_drive_prefix(filename)) - return bdrv_find_format("raw"); -#endif - p = strchr(filename, ':'); - if (!p) - return bdrv_find_format("raw"); - len = p - filename; - if (len > sizeof(protocol) - 1) - len = sizeof(protocol) - 1; - memcpy(protocol, filename, len); - protocol[len] = '\0'; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (drv1->protocol_name && - !strcmp(drv1->protocol_name, protocol)) { - return drv1; - } - } - return NULL; -} - /* * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. @@ -297,6 +281,40 @@ static BlockDriver *find_hdev_driver(const char *filename) return drv; } +static BlockDriver *find_protocol(const char *filename) +{ + BlockDriver *drv1; + char protocol[128]; + int len; + const char *p; + +#ifdef _WIN32 + if (is_windows_drive(filename) || + is_windows_drive_prefix(filename)) + return bdrv_find_format("file"); +#endif + p = strchr(filename, ':'); + 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; + memcpy(protocol, filename, len); + protocol[len] = '\0'; + QLIST_FOREACH(drv1, &bdrv_drivers, list) { + if (drv1->protocol_name && + !strcmp(drv1->protocol_name, protocol)) { + return drv1; + } + } + return NULL; +} + static BlockDriver *find_image_format(const char *filename) { int ret, score, score_max; @@ -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); @@ -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) { diff --git a/block.h b/block.h index 05ad572d8d..f58edf17c3 100644 --- a/block.h +++ b/block.h @@ -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); diff --git a/block/raw-posix.c b/block/raw-posix.c index 4cda9c1f85..8f57ab06ae 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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); @@ -1402,4 +1407,4 @@ static void bdrv_raw_init(void) #endif } -block_init(bdrv_raw_init); +block_init(bdrv_file_init); diff --git a/block/raw-win32.c b/block/raw-win32.c index 526764f62f..eadebeb613 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -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, @@ -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, @@ -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); diff --git a/block/raw.c b/block/raw.c new file mode 100644 index 0000000000..953e2858af --- /dev/null +++ b/block/raw.c @@ -0,0 +1,171 @@ + +#include "qemu-common.h" +#include "block_int.h" +#include "module.h" + +typedef struct RAWState { + BlockDriverState *hd; +} RAWState; + +static int raw_open(BlockDriverState *bs, const char *filename, int flags) +{ + RAWState *s = bs->opaque; + int ret; + + ret = bdrv_file_open(&s->hd, filename, flags); + if (!ret) { + bs->sg = s->hd->sg; + } + + return ret; +} + +static int raw_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + RAWState *s = bs->opaque; + return bdrv_read(s->hd, sector_num, buf, nb_sectors); +} + +static int raw_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + RAWState *s = bs->opaque; + return bdrv_write(s->hd, sector_num, buf, nb_sectors); +} + +static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RAWState *s = bs->opaque; + + return bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque); +} + +static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RAWState *s = bs->opaque; + + return bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque); +} + +static void raw_close(BlockDriverState *bs) +{ + RAWState *s = bs->opaque; + bdrv_delete(s->hd); +} + +static void raw_flush(BlockDriverState *bs) +{ + RAWState *s = bs->opaque; + bdrv_flush(s->hd); +} + +static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RAWState *s = bs->opaque; + return bdrv_aio_flush(s->hd, cb, opaque); +} + +static int64_t raw_getlength(BlockDriverState *bs) +{ + RAWState *s = bs->opaque; + return bdrv_getlength(s->hd); +} + +static int raw_truncate(BlockDriverState *bs, int64_t offset) +{ + RAWState *s = bs->opaque; + return bdrv_truncate(s->hd, offset); +} + +static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + return 1; /* everything can be opened as raw image */ +} + +static int raw_is_inserted(BlockDriverState *bs) +{ + RAWState *s = bs->opaque; + return bdrv_is_inserted(s->hd); +} + +static int raw_eject(BlockDriverState *bs, int eject_flag) +{ + RAWState *s = bs->opaque; + return bdrv_eject(s->hd, eject_flag); +} + +static int raw_set_locked(BlockDriverState *bs, int locked) +{ + RAWState *s = bs->opaque; + bdrv_set_locked(s->hd, locked); + return 0; +} + +static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) +{ + RAWState *s = bs->opaque; + return bdrv_ioctl(s->hd, req, buf); +} + +static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, + unsigned long int req, void *buf, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RAWState *s = bs->opaque; + return bdrv_aio_ioctl(s->hd, req, buf, cb, opaque); +} + +static int raw_create(const char *filename, QEMUOptionParameter *options) +{ + return bdrv_create_file(filename, options); +} + +static QEMUOptionParameter raw_create_options[] = { + { + .name = BLOCK_OPT_SIZE, + .type = OPT_SIZE, + .help = "Virtual disk size" + }, + { NULL } +}; + +static BlockDriver bdrv_raw = { + .format_name = "raw", + + .instance_size = sizeof(RAWState), + + .bdrv_open = raw_open, + .bdrv_close = raw_close, + .bdrv_read = raw_read, + .bdrv_write = raw_write, + .bdrv_flush = raw_flush, + .bdrv_probe = raw_probe, + .bdrv_getlength = raw_getlength, + .bdrv_truncate = raw_truncate, + + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, + .bdrv_aio_flush = raw_aio_flush, + + .bdrv_is_inserted = raw_is_inserted, + .bdrv_eject = raw_eject, + .bdrv_set_locked = raw_set_locked, + .bdrv_ioctl = raw_ioctl, + .bdrv_aio_ioctl = raw_aio_ioctl, + + .bdrv_create = raw_create, + .create_options = raw_create_options, +}; + +static void bdrv_raw_init(void) +{ + bdrv_register(&bdrv_raw); +} + +block_init(bdrv_raw_init);