diff options
-rw-r--r-- | block.c | 44 | ||||
-rw-r--r-- | block.h | 6 | ||||
-rw-r--r-- | block/cow.c | 26 | ||||
-rw-r--r-- | block/qcow.c | 28 | ||||
-rw-r--r-- | block/qcow2.c | 36 | ||||
-rw-r--r-- | block/raw-posix.c | 37 | ||||
-rw-r--r-- | block/raw-win32.c | 20 | ||||
-rw-r--r-- | block/vmdk.c | 28 | ||||
-rw-r--r-- | block/vpc.c | 21 | ||||
-rw-r--r-- | block/vvfat.c | 4 | ||||
-rw-r--r-- | block_int.h | 17 | ||||
-rw-r--r-- | qemu-img.c | 2 |
12 files changed, 214 insertions, 55 deletions
@@ -189,22 +189,44 @@ int bdrv_create2(BlockDriver *drv, const char *backing_file, const char *backing_format, int flags) { - if (drv->bdrv_create2) - return drv->bdrv_create2(filename, size_in_sectors, backing_file, - backing_format, flags); - if (drv->bdrv_create) - return drv->bdrv_create(filename, size_in_sectors, backing_file, - flags); - return -ENOTSUP; + QEMUOptionParameter *options; + + options = parse_option_parameters("", drv->create_options, NULL); + + // Process flags + if (flags & ~(BLOCK_FLAG_ENCRYPT | BLOCK_FLAG_COMPAT6 | BLOCK_FLAG_COMPRESS)) { + return -ENOTSUP; + } + + if (flags & BLOCK_FLAG_ENCRYPT) { + set_option_parameter_int(options, BLOCK_OPT_ENCRYPT, 1); + } + if (flags & BLOCK_FLAG_COMPAT6) { + set_option_parameter_int(options, BLOCK_OPT_COMPAT6, 1); + } + + // Add size to options + set_option_parameter_int(options, BLOCK_OPT_SIZE, size_in_sectors * 512); + + // Backing files + if ((backing_file != NULL && set_option_parameter(options, + BLOCK_OPT_BACKING_FILE, backing_file)) + || (backing_format != NULL && set_option_parameter(options, + BLOCK_OPT_BACKING_FMT, backing_format))) + { + return -ENOTSUP; + } + + return bdrv_create(drv, filename, options); } -int bdrv_create(BlockDriver *drv, - const char *filename, int64_t size_in_sectors, - const char *backing_file, int flags) +int bdrv_create(BlockDriver *drv, const char* filename, + QEMUOptionParameter *options) { if (!drv->bdrv_create) return -ENOTSUP; - return drv->bdrv_create(filename, size_in_sectors, backing_file, flags); + + return drv->bdrv_create(filename, options); } #ifdef _WIN32 @@ -3,6 +3,7 @@ #include "qemu-aio.h" #include "qemu-common.h" +#include "qemu-option.h" /* block.c */ typedef struct BlockDriver BlockDriver; @@ -45,9 +46,8 @@ void bdrv_info_stats(Monitor *mon); void bdrv_init(void); BlockDriver *bdrv_find_format(const char *format_name); -int bdrv_create(BlockDriver *drv, - const char *filename, int64_t size_in_sectors, - const char *backing_file, int flags); +int bdrv_create(BlockDriver *drv, const char* filename, + QEMUOptionParameter *options); int bdrv_create2(BlockDriver *drv, const char *filename, int64_t size_in_sectors, const char *backing_file, const char *backing_format, diff --git a/block/cow.c b/block/cow.c index 94b3549..41d292a 100644 --- a/block/cow.c +++ b/block/cow.c @@ -202,15 +202,23 @@ static void cow_close(BlockDriverState *bs) close(s->fd); } -static int cow_create(const char *filename, int64_t image_sectors, - const char *image_filename, int flags) +static int cow_create(const char *filename, QEMUOptionParameter *options) { int fd, cow_fd; struct cow_header_v2 cow_header; struct stat st; - - if (flags) - return -ENOTSUP; + int64_t image_sectors = 0; + const char *image_filename = NULL; + + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + image_sectors = options->value.n / 512; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + image_filename = options->value.s; + } + options++; + } cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -253,6 +261,12 @@ static void cow_flush(BlockDriverState *bs) fsync(s->fd); } +static QEMUOptionParameter cow_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { BLOCK_OPT_BACKING_FILE, OPT_STRING }, + { NULL } +}; + static BlockDriver bdrv_cow = { .format_name = "cow", .instance_size = sizeof(BDRVCowState), @@ -264,6 +278,8 @@ static BlockDriver bdrv_cow = { .bdrv_create = cow_create, .bdrv_flush = cow_flush, .bdrv_is_allocated = cow_is_allocated, + + .create_options = cow_create_options, }; static void bdrv_cow_init(void) diff --git a/block/qcow.c b/block/qcow.c index 1cf7c3b..6ecf2e8 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -767,12 +767,26 @@ static void qcow_close(BlockDriverState *bs) bdrv_delete(s->hd); } -static int qcow_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int qcow_create(const char *filename, QEMUOptionParameter *options) { int fd, header_size, backing_filename_len, l1_size, i, shift; QCowHeader header; uint64_t tmp; + int64_t total_size = 0; + const char *backing_file = NULL; + int flags = 0; + + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + total_size = options->value.n / 512; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + backing_file = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { + flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; + } + options++; + } fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) @@ -918,6 +932,14 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } + +static QEMUOptionParameter qcow_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { BLOCK_OPT_BACKING_FILE, OPT_STRING }, + { BLOCK_OPT_ENCRYPT, OPT_FLAG }, + { NULL } +}; + static BlockDriver bdrv_qcow = { .format_name = "qcow", .instance_size = sizeof(BDRVQcowState), @@ -935,6 +957,8 @@ static BlockDriver bdrv_qcow = { .aiocb_size = sizeof(QCowAIOCB), .bdrv_write_compressed = qcow_write_compressed, .bdrv_get_info = qcow_get_info, + + .create_options = qcow_create_options, }; static void bdrv_qcow_init(void) diff --git a/block/qcow2.c b/block/qcow2.c index 33f3299..803cf7f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1696,10 +1696,28 @@ static int qcow_create2(const char *filename, int64_t total_size, return 0; } -static int qcow_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) -{ - return qcow_create2(filename, total_size, backing_file, NULL, flags); +static int qcow_create(const char *filename, QEMUOptionParameter *options) +{ + const char *backing_file = NULL; + const char *backing_fmt = NULL; + uint64_t sectors = 0; + int flags = 0; + + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + sectors = options->value.n / 512; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + backing_file = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { + backing_fmt = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { + flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; + } + options++; + } + + return qcow_create2(filename, sectors, backing_file, backing_fmt, flags); } static int qcow_make_empty(BlockDriverState *bs) @@ -2897,6 +2915,14 @@ static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf, return ret; } +static QEMUOptionParameter qcow_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { BLOCK_OPT_BACKING_FILE, OPT_STRING }, + { BLOCK_OPT_BACKING_FMT, OPT_STRING }, + { BLOCK_OPT_ENCRYPT, OPT_FLAG }, + { NULL } +}; + static BlockDriver bdrv_qcow2 = { .format_name = "qcow2", .instance_size = sizeof(BDRVQcowState), @@ -2924,7 +2950,7 @@ static BlockDriver bdrv_qcow2 = { .bdrv_put_buffer = qcow_put_buffer, .bdrv_get_buffer = qcow_get_buffer, - .bdrv_create2 = qcow_create2, + .create_options = qcow_create_options, .bdrv_check = qcow_check, }; diff --git a/block/raw-posix.c b/block/raw-posix.c index f3a9476..86e3067 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -823,13 +823,18 @@ again: } #endif -static int raw_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int raw_create(const char *filename, QEMUOptionParameter *options) { int fd; + int64_t total_size = 0; - if (flags || backing_file) - return -ENOTSUP; + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + total_size = options->value.n / 512; + } + options++; + } fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -846,6 +851,12 @@ static void raw_flush(BlockDriverState *bs) fsync(s->fd); } + +static QEMUOptionParameter raw_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { NULL } +}; + static BlockDriver bdrv_raw = { .format_name = "raw", .instance_size = sizeof(BDRVRawState), @@ -866,6 +877,8 @@ static BlockDriver bdrv_raw = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + + .create_options = raw_create_options, }; /***********************************************/ @@ -1364,15 +1377,20 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, #endif /* !linux && !FreeBSD */ #if defined(__linux__) || defined(__FreeBSD__) -static int hdev_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int hdev_create(const char *filename, QEMUOptionParameter *options) { int fd; int ret = 0; struct stat stat_buf; + int64_t total_size = 0; - if (flags || backing_file) - return -ENOTSUP; + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, "size")) { + total_size = options->value.n / 512; + } + options++; + } fd = open(filename, O_WRONLY | O_BINARY); if (fd < 0) @@ -1391,8 +1409,7 @@ static int hdev_create(const char *filename, int64_t total_size, #else /* !(linux || freebsd) */ -static int hdev_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int hdev_create(const char *filename, QEMUOptionParameter *options) { return -ENOTSUP; } diff --git a/block/raw-win32.c b/block/raw-win32.c index 15f3ec4..6e5c09b 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -210,13 +210,18 @@ static int64_t raw_getlength(BlockDriverState *bs) return l.QuadPart; } -static int raw_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int raw_create(const char *filename, QEMUOptionParameter *options) { int fd; + int64_t total_size = 0; - if (flags || backing_file) - return -ENOTSUP; + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + total_size = options->value.n / 512; + } + options++; + } fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -228,6 +233,11 @@ static int raw_create(const char *filename, int64_t total_size, return 0; } +static QEMUOptionParameter raw_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { NULL } +}; + static BlockDriver bdrv_raw = { .format_name = "raw", .instance_size = sizeof(BDRVRawState), @@ -239,6 +249,8 @@ static BlockDriver bdrv_raw = { .bdrv_write = raw_write, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + + .create_options = raw_create_options, }; /***********************************************/ diff --git a/block/vmdk.c b/block/vmdk.c index 13866e9..b3ea686 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -687,8 +687,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, return 0; } -static int vmdk_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int vmdk_create(const char *filename, QEMUOptionParameter *options) { int fd, i; VMDK4Header header; @@ -713,6 +712,21 @@ static int vmdk_create(const char *filename, int64_t total_size, "ddb.adapterType = \"ide\"\n"; char desc[1024]; const char *real_filename, *temp_str; + int64_t total_size = 0; + const char *backing_file = NULL; + int flags = 0; + + // Read out options + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + total_size = options->value.n / 512; + } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + backing_file = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { + flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0; + } + options++; + } /* XXX: add support for backing file */ if (backing_file) { @@ -812,6 +826,14 @@ static void vmdk_flush(BlockDriverState *bs) bdrv_flush(s->hd); } + +static QEMUOptionParameter vmdk_create_options[] = { + { BLOCK_OPT_SIZE, OPT_SIZE }, + { BLOCK_OPT_BACKING_FILE, OPT_STRING }, + { BLOCK_OPT_COMPAT6, OPT_FLAG }, + { NULL } +}; + static BlockDriver bdrv_vmdk = { .format_name = "vmdk", .instance_size = sizeof(BDRVVmdkState), @@ -823,6 +845,8 @@ static BlockDriver bdrv_vmdk = { .bdrv_create = vmdk_create, .bdrv_flush = vmdk_flush, .bdrv_is_allocated = vmdk_is_allocated, + + .create_options = vmdk_create_options, }; static void bdrv_vmdk_init(void) diff --git a/block/vpc.c b/block/vpc.c index 211ae5c..662a6f6 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -477,8 +477,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, return 0; } -static int vpc_create(const char *filename, int64_t total_sectors, - const char *backing_file, int flags) +static int vpc_create(const char *filename, QEMUOptionParameter *options) { uint8_t buf[1024]; struct vhd_footer* footer = (struct vhd_footer*) buf; @@ -489,10 +488,17 @@ static int vpc_create(const char *filename, int64_t total_sectors, uint8_t heads; uint8_t secs_per_cyl; size_t block_size, num_bat_entries; + int64_t total_sectors = 0; - if (backing_file != NULL) - return -ENOTSUP; + // Read out options + while (options && options->name) { + if (!strcmp(options->name, "size")) { + total_sectors = options->value.n / 512; + } + options++; + } + // Create the file fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) return -EIO; @@ -587,6 +593,11 @@ static void vpc_close(BlockDriverState *bs) bdrv_delete(s->hd); } +static QEMUOptionParameter vpc_create_options[] = { + { "size", OPT_SIZE }, + { NULL } +}; + static BlockDriver bdrv_vpc = { .format_name = "vpc", .instance_size = sizeof(BDRVVPCState), @@ -596,6 +607,8 @@ static BlockDriver bdrv_vpc = { .bdrv_write = vpc_write, .bdrv_close = vpc_close, .bdrv_create = vpc_create, + + .create_options = vpc_create_options, }; static void bdrv_vpc_init(void) diff --git a/block/vvfat.c b/block/vvfat.c index 2a8feb3..13960e9 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2777,8 +2777,8 @@ static int enable_write_target(BDRVVVFATState *s) s->qcow_filename = qemu_malloc(1024); get_tmp_filename(s->qcow_filename, 1024); - if (bdrv_create(bdrv_find_format("qcow"), - s->qcow_filename, s->sector_count, "fat:", 0) < 0) + if (bdrv_create2(bdrv_find_format("qcow"), + s->qcow_filename, s->sector_count, "fat:", NULL, 0) < 0) return -1; s->qcow = bdrv_new(""); if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0) diff --git a/block_int.h b/block_int.h index 9d11940..782de6c 100644 --- a/block_int.h +++ b/block_int.h @@ -25,11 +25,18 @@ #define BLOCK_INT_H #include "block.h" +#include "qemu-option.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPRESS 2 #define BLOCK_FLAG_COMPAT6 4 +#define BLOCK_OPT_SIZE "size" +#define BLOCK_OPT_ENCRYPT "encryption" +#define BLOCK_OPT_COMPAT6 "compat6" +#define BLOCK_OPT_BACKING_FILE "backing_file" +#define BLOCK_OPT_BACKING_FMT "backing_fmt" + typedef struct AIOPool { void (*cancel)(BlockDriverAIOCB *acb); int aiocb_size; @@ -46,8 +53,7 @@ struct BlockDriver { int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); void (*bdrv_close)(BlockDriverState *bs); - int (*bdrv_create)(const char *filename, int64_t total_sectors, - const char *backing_file, int flags); + int (*bdrv_create)(const char *filename, QEMUOptionParameter *options); void (*bdrv_flush)(BlockDriverState *bs); int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); @@ -97,10 +103,9 @@ struct BlockDriver { AIOPool aio_pool; - /* new create with backing file format */ - int (*bdrv_create2)(const char *filename, int64_t total_sectors, - const char *backing_file, const char *backing_format, - int flags); + /* List of options for creating images, terminated by name == NULL */ + QEMUOptionParameter *create_options; + /* Returns number of errors in image, -errno for internal errors */ int (*bdrv_check)(BlockDriverState* bs); @@ -551,7 +551,7 @@ static int img_convert(int argc, char **argv) if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS) error("Compression and encryption not supported at the same time"); - ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags); + ret = bdrv_create2(drv, out_filename, total_sectors, out_baseimg, NULL, flags); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", out_fmt); |