From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44744) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yn0Ec-00057G-LX for qemu-devel@nongnu.org; Tue, 28 Apr 2015 03:47:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yn0Eb-0004Cx-Iv for qemu-devel@nongnu.org; Tue, 28 Apr 2015 03:47:14 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:28822 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yn0Eb-0004Cf-6J for qemu-devel@nongnu.org; Tue, 28 Apr 2015 03:47:13 -0400 From: "Denis V. Lunev" Date: Tue, 28 Apr 2015 10:46:44 +0300 Message-Id: <1430207220-24458-12-git-send-email-den@openvz.org> In-Reply-To: <1430207220-24458-1-git-send-email-den@openvz.org> References: <1430207220-24458-1-git-send-email-den@openvz.org> Subject: [Qemu-devel] [PATCH 11/27] block/parallels: support parallels image creation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Denis V. Lunev" , qemu-devel@nongnu.org Do not even care to create WithoutFreeSpace image, it is obsolete. Always create WithouFreSpacExt one. The code also does not spend a lot of efforts to fill cylinders and heads fields, they are not used actually in a real life neither in QEMU nor in Parallels products. Signed-off-by: Denis V. Lunev Reviewed-by: Roman Kagan Reviewed-by: Stefan Hajnoczi CC: Kevin Wolf --- block/parallels.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/block/parallels.c b/block/parallels.c index 8d73803..15f6cb3 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -33,6 +33,9 @@ #define HEADER_MAGIC2 "WithouFreSpacExt" #define HEADER_VERSION 2 +#define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */ + + // always little-endian typedef struct ParallelsHeader { char magic[16]; // "WithoutFreeSpace" @@ -317,12 +320,103 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs, return ret; } +static int parallels_create(const char *filename, QemuOpts *opts, Error **errp) +{ + int64_t total_size, cl_size; + uint8_t tmp[BDRV_SECTOR_SIZE]; + Error *local_err = NULL; + BlockDriverState *file; + uint32_t cat_entries, cat_sectors; + ParallelsHeader header; + int ret; + + total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); + cl_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, + DEFAULT_CLUSTER_SIZE), BDRV_SECTOR_SIZE); + + ret = bdrv_create_file(filename, opts, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); + return ret; + } + + file = NULL; + ret = bdrv_open(&file, filename, NULL, NULL, + BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); + return ret; + } + ret = bdrv_truncate(file, 0); + if (ret < 0) { + goto exit; + } + + cat_entries = DIV_ROUND_UP(total_size, cl_size); + cat_sectors = DIV_ROUND_UP(cat_entries * sizeof(uint32_t) + + sizeof(ParallelsHeader), cl_size); + cat_sectors = (cat_sectors * cl_size) >> BDRV_SECTOR_BITS; + + memset(&header, 0, sizeof(header)); + memcpy(header.magic, HEADER_MAGIC2, sizeof(header.magic)); + header.version = cpu_to_le32(HEADER_VERSION); + /* don't care much about geometry, it is not used on image level */ + header.heads = cpu_to_le32(16); + header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE / 16 / 32); + header.tracks = cpu_to_le32(cl_size >> BDRV_SECTOR_BITS); + header.catalog_entries = cpu_to_le32(cat_entries); + header.nb_sectors = cpu_to_le64(DIV_ROUND_UP(total_size, BDRV_SECTOR_SIZE)); + header.data_off = cpu_to_le32(cat_sectors); + + /* write all the data */ + memset(tmp, 0, sizeof(tmp)); + memcpy(tmp, &header, sizeof(header)); + + ret = bdrv_pwrite(file, 0, tmp, BDRV_SECTOR_SIZE); + if (ret < 0) { + goto exit; + } + ret = bdrv_write_zeroes(file, 1, cat_sectors - 1, 0); + if (ret < 0) { + goto exit; + } + ret = 0; + +done: + bdrv_unref(file); + return ret; + +exit: + error_setg_errno(errp, -ret, "Failed to create Parallels image"); + goto done; +} + static void parallels_close(BlockDriverState *bs) { BDRVParallelsState *s = bs->opaque; g_free(s->catalog_bitmap); } +static QemuOptsList parallels_create_opts = { + .name = "parallels-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(parallels_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size", + }, + { + .name = BLOCK_OPT_CLUSTER_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Parallels image cluster size", + .def_value_str = stringify(DEFAULT_CLUSTER_SIZE), + }, + { /* end of list */ } + } +}; + static BlockDriver bdrv_parallels = { .format_name = "parallels", .instance_size = sizeof(BDRVParallelsState), @@ -333,6 +427,9 @@ static BlockDriver bdrv_parallels = { .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_readv = parallels_co_readv, .bdrv_co_writev = parallels_co_writev, + + .bdrv_create = parallels_create, + .create_opts = ¶llels_create_opts, }; static void bdrv_parallels_init(void) -- 1.9.1