From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y5thQ-0005GV-G4 for qemu-devel@nongnu.org; Tue, 30 Dec 2014 05:06:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y5thN-0003Vc-4j for qemu-devel@nongnu.org; Tue, 30 Dec 2014 05:06:48 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:28180 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y5thM-0003Ue-4u for qemu-devel@nongnu.org; Tue, 30 Dec 2014 05:06:45 -0500 From: "Denis V. Lunev" Date: Tue, 30 Dec 2014 13:07:03 +0300 Message-Id: <1419934032-24216-1-git-send-email-den@openvz.org> In-Reply-To: <1419931701-19362-1-git-send-email-den@openvz.org> References: <1419931701-19362-1-git-send-email-den@openvz.org> Subject: [Qemu-devel] [PATCH 10/19] 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, Stefan Hajnoczi 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 Acked-by: Roman Kagan CC: Kevin Wolf CC: Stefan Hajnoczi --- block/parallels.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/block/parallels.c b/block/parallels.c index dca3d0b..bea1217 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" @@ -300,12 +303,103 @@ fail: 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), @@ -315,6 +409,9 @@ static BlockDriver bdrv_parallels = { .bdrv_co_get_block_status = parallels_co_get_block_status, .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