aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c44
-rw-r--r--block.h6
-rw-r--r--block/cow.c26
-rw-r--r--block/qcow.c28
-rw-r--r--block/qcow2.c36
-rw-r--r--block/raw-posix.c37
-rw-r--r--block/raw-win32.c20
-rw-r--r--block/vmdk.c28
-rw-r--r--block/vpc.c21
-rw-r--r--block/vvfat.c4
-rw-r--r--block_int.h17
-rw-r--r--qemu-img.c2
12 files changed, 214 insertions, 55 deletions
diff --git a/block.c b/block.c
index cbc83b166e..c80d4b90ce 100644
--- a/block.c
+++ b/block.c
@@ -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
diff --git a/block.h b/block.h
index 22df8ca737..0acac63b87 100644
--- a/block.h
+++ b/block.h
@@ -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 94b3549389..41d292aac2 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 1cf7c3be77..6ecf2e8e03 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 33f329992f..803cf7f883 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 f3a9476b44..86e3067762 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 15f3ec4849..6e5c09bcb5 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 13866e9b06..b3ea68679c 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 211ae5c72f..662a6f6cf8 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 2a8feb38d8..13960e95a6 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 9d119404cf..782de6c62d 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);
diff --git a/qemu-img.c b/qemu-img.c
index a3d15e716b..190153ff11 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -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);