]> git.proxmox.com Git - mirror_qemu.git/blame - block/vpc.c
block: Mark bdrv_filter_bs() and callers GRAPH_RDLOCK
[mirror_qemu.git] / block / vpc.c
CommitLineData
6a0f9e82 1/*
cc2040f8 2 * Block driver for Connectix / Microsoft Virtual PC images
5fafdf24 3 *
6a0f9e82 4 * Copyright (c) 2005 Alex Beregszaszi
15d35bc5 5 * Copyright (c) 2009 Kevin Wolf <kwolf@suse.de>
5fafdf24 6 *
6a0f9e82
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
922a01a0 25
80c71a24 26#include "qemu/osdep.h"
da34e65c 27#include "qapi/error.h"
737e150e 28#include "block/block_int.h"
609f45ea 29#include "block/qdict.h"
b8f45cdf 30#include "sysemu/block-backend.h"
1de7afc9 31#include "qemu/module.h"
922a01a0 32#include "qemu/option.h"
795c40b8 33#include "migration/blocker.h"
58369e22 34#include "qemu/bswap.h"
38440a21 35#include "qemu/uuid.h"
5df022cf 36#include "qemu/memalign.h"
182c8835
KW
37#include "qapi/qmp/qdict.h"
38#include "qapi/qobject-input-visitor.h"
39#include "qapi/qapi-visit-block-core.h"
6a0f9e82
FB
40
41/**************************************************************/
42
6a0f9e82
FB
43//#define CACHE
44
2cfacb62
AL
45enum vhd_type {
46 VHD_FIXED = 2,
47 VHD_DYNAMIC = 3,
48 VHD_DIFFERENCING = 4,
49};
50
9c057d0b 51/* Seconds since Jan 1, 2000 0:00:00 (UTC) */
57c7d9e5
AL
52#define VHD_TIMESTAMP_BASE 946684800
53
fb9245c2
JC
54#define VHD_CHS_MAX_C 65535LL
55#define VHD_CHS_MAX_H 16
56#define VHD_CHS_MAX_S 255
57
c23fb11b 58#define VHD_MAX_SECTORS 0xff000000 /* 2040 GiB max image size */
fb9245c2
JC
59#define VHD_MAX_GEOMETRY (VHD_CHS_MAX_C * VHD_CHS_MAX_H * VHD_CHS_MAX_S)
60
61#define VPC_OPT_FORCE_SIZE "force_size"
97f1c45c 62
9c057d0b 63/* always big-endian */
e54835c0 64typedef struct vhd_footer {
9c057d0b 65 char creator[8]; /* "conectix" */
2cfacb62
AL
66 uint32_t features;
67 uint32_t version;
68
9c057d0b 69 /* Offset of next header structure, 0xFFFFFFFF if none */
2cfacb62
AL
70 uint64_t data_offset;
71
9c057d0b 72 /* Seconds since Jan 1, 2000 0:00:00 (UTC) */
2cfacb62
AL
73 uint32_t timestamp;
74
9c057d0b 75 char creator_app[4]; /* e.g., "vpc " */
2cfacb62
AL
76 uint16_t major;
77 uint16_t minor;
9c057d0b 78 char creator_os[4]; /* "Wi2k" */
2cfacb62
AL
79
80 uint64_t orig_size;
03671ded 81 uint64_t current_size;
2cfacb62
AL
82
83 uint16_t cyls;
84 uint8_t heads;
85 uint8_t secs_per_cyl;
86
87 uint32_t type;
88
9c057d0b
JC
89 /* Checksum of the Hard Disk Footer ("one's complement of the sum of all
90 the bytes in the footer without the checksum field") */
2cfacb62
AL
91 uint32_t checksum;
92
9c057d0b 93 /* UUID used to identify a parent hard disk (backing file) */
38440a21 94 QemuUUID uuid;
2cfacb62
AL
95
96 uint8_t in_saved_state;
275734e4 97 uint8_t reserved[427];
e54835c0 98} QEMU_PACKED VHDFooter;
b9fa33a6 99
275734e4
MA
100QEMU_BUILD_BUG_ON(sizeof(VHDFooter) != 512);
101
e54835c0 102typedef struct vhd_dyndisk_header {
9c057d0b 103 char magic[8]; /* "cxsparse" */
2cfacb62 104
9c057d0b 105 /* Offset of next header structure, 0xFFFFFFFF if none */
2cfacb62
AL
106 uint64_t data_offset;
107
9c057d0b 108 /* Offset of the Block Allocation Table (BAT) */
2cfacb62
AL
109 uint64_t table_offset;
110
111 uint32_t version;
9c057d0b 112 uint32_t max_table_entries; /* 32bit/entry */
2cfacb62 113
9c057d0b 114 /* 2 MB by default, must be a power of two */
2cfacb62
AL
115 uint32_t block_size;
116
117 uint32_t checksum;
118 uint8_t parent_uuid[16];
119 uint32_t parent_timestamp;
120 uint32_t reserved;
121
9c057d0b 122 /* Backing file name (in UTF-16) */
2cfacb62
AL
123 uint8_t parent_name[512];
124
125 struct {
126 uint32_t platform;
127 uint32_t data_space;
128 uint32_t data_length;
129 uint32_t reserved;
130 uint64_t data_offset;
131 } parent_locator[8];
e326f078 132 uint8_t reserved2[256];
e54835c0 133} QEMU_PACKED VHDDynDiskHeader;
6a0f9e82 134
e326f078
MA
135QEMU_BUILD_BUG_ON(sizeof(VHDDynDiskHeader) != 1024);
136
6a0f9e82 137typedef struct BDRVVPCState {
848c66e8 138 CoMutex lock;
275734e4 139 VHDFooter footer;
15d35bc5 140 uint64_t free_data_block_offset;
2cfacb62 141 int max_table_entries;
6a0f9e82 142 uint32_t *pagetable;
15d35bc5
AL
143 uint64_t bat_offset;
144 uint64_t last_bitmap_offset;
6a0f9e82 145
2cfacb62 146 uint32_t block_size;
15d35bc5 147 uint32_t bitmap_size;
c540d53a
JC
148 bool force_use_chs;
149 bool force_use_sz;
15d35bc5 150
6a0f9e82
FB
151#ifdef CACHE
152 uint8_t *pageentry_u8;
153 uint32_t *pageentry_u32;
154 uint16_t *pageentry_u16;
3b46e624 155
6a0f9e82
FB
156 uint64_t last_bitmap;
157#endif
612ff3d8
KW
158
159 Error *migration_blocker;
6a0f9e82
FB
160} BDRVVPCState;
161
c540d53a
JC
162#define VPC_OPT_SIZE_CALC "force_size_calc"
163static QemuOptsList vpc_runtime_opts = {
164 .name = "vpc-runtime-opts",
165 .head = QTAILQ_HEAD_INITIALIZER(vpc_runtime_opts.head),
166 .desc = {
167 {
168 .name = VPC_OPT_SIZE_CALC,
169 .type = QEMU_OPT_STRING,
170 .help = "Force disk size calculation to use either CHS geometry, "
171 "or use the disk current_size specified in the VHD footer. "
172 "{chs, current_size}"
173 },
174 { /* end of list */ }
175 }
176};
177
182c8835
KW
178static QemuOptsList vpc_create_opts;
179
7550379d 180static uint32_t vpc_checksum(void *p, size_t size)
57c7d9e5 181{
7550379d 182 uint8_t *buf = p;
57c7d9e5
AL
183 uint32_t res = 0;
184 int i;
185
186 for (i = 0; i < size; i++)
187 res += buf[i];
188
189 return ~res;
190}
191
192
6a0f9e82
FB
193static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
194{
ffe8ab83 195 if (buf_size >= 8 && !strncmp((char *)buf, "conectix", 8))
7d37435b 196 return 100;
6a0f9e82
FB
197 return 0;
198}
199
c540d53a
JC
200static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts,
201 Error **errp)
202{
203 BDRVVPCState *s = bs->opaque;
204 const char *size_calc;
205
206 size_calc = qemu_opt_get(opts, VPC_OPT_SIZE_CALC);
207
208 if (!size_calc) {
209 /* no override, use autodetect only */
210 } else if (!strcmp(size_calc, "current_size")) {
211 s->force_use_sz = true;
212 } else if (!strcmp(size_calc, "chs")) {
213 s->force_use_chs = true;
214 } else {
215 error_setg(errp, "Invalid size calculation mode: '%s'", size_calc);
216 }
217}
218
015a1036
HR
219static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
220 Error **errp)
6a0f9e82
FB
221{
222 BDRVVPCState *s = bs->opaque;
66f82cee 223 int i;
e54835c0 224 VHDFooter *footer;
c540d53a
JC
225 QemuOpts *opts = NULL;
226 Error *local_err = NULL;
227 bool use_chs;
e326f078 228 VHDDynDiskHeader dyndisk_header;
57c7d9e5 229 uint32_t checksum;
97f1c45c 230 uint64_t computed_size;
b15deac7 231 uint64_t pagetable_size;
24da78db 232 int disk_type = VHD_DYNAMIC;
59294e46 233 int ret;
81caa3cc 234 int64_t bs_size;
6a0f9e82 235
83930780
VSO
236 ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
237 if (ret < 0) {
238 return ret;
4e4bf5c4
KW
239 }
240
c540d53a 241 opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
af175e85 242 if (!qemu_opts_absorb_qdict(opts, options, errp)) {
c540d53a
JC
243 ret = -EINVAL;
244 goto fail;
245 }
246
247 vpc_parse_options(bs, opts, &local_err);
248 if (local_err) {
249 error_propagate(errp, local_err);
250 ret = -EINVAL;
251 goto fail;
252 }
253
32cc71de 254 ret = bdrv_pread(bs->file, 0, sizeof(s->footer), &s->footer, 0);
59294e46 255 if (ret < 0) {
32f6439c 256 error_setg(errp, "Unable to read VHD header");
6a0f9e82 257 goto fail;
59294e46 258 }
6a0f9e82 259
275734e4 260 footer = &s->footer;
24da78db 261 if (strncmp(footer->creator, "conectix", 8)) {
9a4f4c31 262 int64_t offset = bdrv_getlength(bs->file->bs);
59294e46
KW
263 if (offset < 0) {
264 ret = offset;
32f6439c 265 error_setg(errp, "Invalid file size");
59294e46 266 goto fail;
be7c5ddd 267 } else if (offset < sizeof(*footer)) {
59294e46 268 ret = -EINVAL;
32f6439c 269 error_setg(errp, "File too small for a VHD header");
24da78db
CA
270 goto fail;
271 }
59294e46 272
24da78db 273 /* If a fixed disk, the footer is found only at the end of the file */
32cc71de
AF
274 ret = bdrv_pread(bs->file, offset - sizeof(*footer), sizeof(*footer),
275 footer, 0);
59294e46 276 if (ret < 0) {
24da78db
CA
277 goto fail;
278 }
7da9623c
TH
279 if (strncmp(footer->creator, "conectix", 8) ||
280 be32_to_cpu(footer->type) != VHD_FIXED) {
76abe407
PB
281 error_setg(errp, "invalid VPC image");
282 ret = -EINVAL;
24da78db
CA
283 goto fail;
284 }
285 disk_type = VHD_FIXED;
286 }
6a0f9e82 287
57c7d9e5
AL
288 checksum = be32_to_cpu(footer->checksum);
289 footer->checksum = 0;
be7c5ddd 290 if (vpc_checksum(footer, sizeof(*footer)) != checksum) {
04788ba2
MA
291 error_setg(errp, "Incorrect header checksum");
292 ret = -EINVAL;
293 goto fail;
294 }
57c7d9e5 295
c088b691 296 /* Write 'checksum' back to footer, or else will leave it with zero. */
a4127c42 297 footer->checksum = cpu_to_be32(checksum);
c088b691 298
9c057d0b
JC
299 /* The visible size of a image in Virtual PC depends on the geometry
300 rather than on the size stored in the footer (the size in the footer
301 is too large usually) */
33ccf667
SH
302 bs->total_sectors = (int64_t)
303 be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
1fa79228 304
c540d53a
JC
305 /* Microsoft Virtual PC and Microsoft Hyper-V produce and read
306 * VHD image sizes differently. VPC will rely on CHS geometry,
307 * while Hyper-V and disk2vhd use the size specified in the footer.
308 *
309 * We use a couple of approaches to try and determine the correct method:
310 * look at the Creator App field, and look for images that have CHS
311 * geometry that is the maximum value.
312 *
313 * If the CHS geometry is the maximum CHS geometry, then we assume that
314 * the size is the footer->current_size to avoid truncation. Otherwise,
315 * we follow the table based on footer->creator_app:
316 *
317 * Known creator apps:
318 * 'vpc ' : CHS Virtual PC (uses disk geometry)
319 * 'qemu' : CHS QEMU (uses disk geometry)
fb9245c2 320 * 'qem2' : current_size QEMU (uses current_size)
c540d53a
JC
321 * 'win ' : current_size Hyper-V
322 * 'd2v ' : current_size Disk2vhd
9bdfb9e8 323 * 'tap\0' : current_size XenServer
bab246db 324 * 'CTXS' : current_size XenConverter
c540d53a
JC
325 *
326 * The user can override the table values via drive options, however
327 * even with an override we will still use current_size for images
328 * that have CHS geometry of the maximum size.
329 */
330 use_chs = (!!strncmp(footer->creator_app, "win ", 4) &&
fb9245c2 331 !!strncmp(footer->creator_app, "qem2", 4) &&
9bdfb9e8 332 !!strncmp(footer->creator_app, "d2v ", 4) &&
bab246db 333 !!strncmp(footer->creator_app, "CTXS", 4) &&
9bdfb9e8 334 !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs;
c540d53a
JC
335
336 if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) {
03671ded 337 bs->total_sectors = be64_to_cpu(footer->current_size) /
c540d53a 338 BDRV_SECTOR_SIZE;
0173e7bb
PL
339 }
340
c23fb11b
JC
341 /* Allow a maximum disk size of 2040 GiB */
342 if (bs->total_sectors > VHD_MAX_SECTORS) {
59294e46 343 ret = -EFBIG;
efc8243d
SH
344 goto fail;
345 }
346
24da78db 347 if (disk_type == VHD_DYNAMIC) {
02df95c4 348 ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset),
32cc71de 349 sizeof(dyndisk_header), &dyndisk_header, 0);
59294e46 350 if (ret < 0) {
32f6439c 351 error_setg(errp, "Error reading dynamic VHD header");
24da78db
CA
352 goto fail;
353 }
b9fa33a6 354
e326f078 355 if (strncmp(dyndisk_header.magic, "cxsparse", 8)) {
32f6439c 356 error_setg(errp, "Invalid header magic");
59294e46 357 ret = -EINVAL;
24da78db
CA
358 goto fail;
359 }
6a0f9e82 360
e326f078 361 s->block_size = be32_to_cpu(dyndisk_header.block_size);
5e71dfad
KW
362 if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
363 error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
364 ret = -EINVAL;
365 goto fail;
366 }
24da78db 367 s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
15d35bc5 368
e326f078 369 s->max_table_entries = be32_to_cpu(dyndisk_header.max_table_entries);
97f1c45c
JC
370
371 if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
32f6439c 372 error_setg(errp, "Too many blocks");
97f1c45c
JC
373 ret = -EINVAL;
374 goto fail;
375 }
97f1c45c
JC
376
377 computed_size = (uint64_t) s->max_table_entries * s->block_size;
378 if (computed_size < bs->total_sectors * 512) {
32f6439c 379 error_setg(errp, "Page table too small");
97f1c45c
JC
380 ret = -EINVAL;
381 goto fail;
382 }
383
b15deac7
JC
384 if (s->max_table_entries > SIZE_MAX / 4 ||
385 s->max_table_entries > (int) INT_MAX / 4) {
386 error_setg(errp, "Max Table Entries too large (%" PRId32 ")",
387 s->max_table_entries);
388 ret = -EINVAL;
389 goto fail;
390 }
391
392 pagetable_size = (uint64_t) s->max_table_entries * 4;
393
9a4f4c31 394 s->pagetable = qemu_try_blockalign(bs->file->bs, pagetable_size);
5fb09cd5 395 if (s->pagetable == NULL) {
32f6439c 396 error_setg(errp, "Unable to allocate memory for page table");
5fb09cd5
KW
397 ret = -ENOMEM;
398 goto fail;
399 }
b71d1c2e 400
e326f078 401 s->bat_offset = be64_to_cpu(dyndisk_header.table_offset);
59294e46 402
32cc71de
AF
403 ret = bdrv_pread(bs->file, s->bat_offset, pagetable_size,
404 s->pagetable, 0);
59294e46 405 if (ret < 0) {
32f6439c 406 error_setg(errp, "Error reading pagetable");
24da78db
CA
407 goto fail;
408 }
b71d1c2e 409
24da78db 410 s->free_data_block_offset =
b15deac7 411 ROUND_UP(s->bat_offset + pagetable_size, 512);
15d35bc5 412
24da78db
CA
413 for (i = 0; i < s->max_table_entries; i++) {
414 be32_to_cpus(&s->pagetable[i]);
415 if (s->pagetable[i] != 0xFFFFFFFF) {
416 int64_t next = (512 * (int64_t) s->pagetable[i]) +
417 s->bitmap_size + s->block_size;
15d35bc5 418
24da78db
CA
419 if (next > s->free_data_block_offset) {
420 s->free_data_block_offset = next;
421 }
422 }
15d35bc5 423 }
15d35bc5 424
81caa3cc
EB
425 bs_size = bdrv_getlength(bs->file->bs);
426 if (bs_size < 0) {
427 error_setg_errno(errp, -bs_size, "Unable to learn image size");
428 ret = bs_size;
429 goto fail;
430 }
431 if (s->free_data_block_offset > bs_size) {
fb8fe35f
PL
432 error_setg(errp, "block-vpc: free_data_block_offset points after "
433 "the end of file. The image has been truncated.");
434 ret = -EINVAL;
435 goto fail;
436 }
437
24da78db 438 s->last_bitmap_offset = (int64_t) -1;
6a0f9e82 439
6a0f9e82 440#ifdef CACHE
24da78db
CA
441 s->pageentry_u8 = g_malloc(512);
442 s->pageentry_u32 = s->pageentry_u8;
443 s->pageentry_u16 = s->pageentry_u8;
444 s->last_pagetable = -1;
6a0f9e82 445#endif
24da78db 446 }
6a0f9e82 447
612ff3d8 448 /* Disable migration when VHD images are used */
4026f1c4 449 bdrv_graph_rdlock_main_loop();
81e5f78a
AG
450 error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
451 "does not support live migration",
452 bdrv_get_device_or_node_name(bs));
4026f1c4
KW
453 bdrv_graph_rdunlock_main_loop();
454
e0ee3a8f 455 ret = migrate_add_blocker_normal(&s->migration_blocker, errp);
386f6c07 456 if (ret < 0) {
fe44dc91
AA
457 goto fail;
458 }
459
460 qemu_co_mutex_init(&s->lock);
c317b646 461 qemu_opts_del(opts);
612ff3d8 462
6a0f9e82 463 return 0;
59294e46
KW
464
465fail:
c317b646 466 qemu_opts_del(opts);
97f1c45c 467 qemu_vfree(s->pagetable);
59294e46
KW
468#ifdef CACHE
469 g_free(s->pageentry_u8);
470#endif
471 return ret;
6a0f9e82
FB
472}
473
3fe4b700
JC
474static int vpc_reopen_prepare(BDRVReopenState *state,
475 BlockReopenQueue *queue, Error **errp)
476{
477 return 0;
478}
479
b71d1c2e
AL
480/*
481 * Returns the absolute byte offset of the given sector in the image file.
482 * If the sector is not allocated, -1 is returned instead.
cfc87e00
PM
483 * If an error occurred trying to write an updated block bitmap back to
484 * the file, -2 is returned, and the error value is written to *err.
485 * This can only happen for a write operation.
15d35bc5
AL
486 *
487 * The parameter write must be 1 if the offset will be used for a write
488 * operation (the block bitmaps is updated then), 0 otherwise.
cfc87e00 489 * If write is true then err must not be NULL.
b71d1c2e 490 */
517b5dff
PB
491static int64_t coroutine_fn GRAPH_RDLOCK
492get_image_offset(BlockDriverState *bs, uint64_t offset, bool write, int *err)
6a0f9e82
FB
493{
494 BDRVVPCState *s = bs->opaque;
6a0f9e82 495 uint64_t bitmap_offset, block_offset;
d46b7cc6 496 uint32_t pagetable_index, offset_in_block;
6a0f9e82 497
cfc87e00
PM
498 assert(!(write && err == NULL));
499
2cfacb62 500 pagetable_index = offset / s->block_size;
d46b7cc6 501 offset_in_block = offset % s->block_size;
3b46e624 502
15d35bc5 503 if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff)
9c057d0b 504 return -1; /* not allocated */
6a0f9e82 505
378e2aea 506 bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index];
d46b7cc6 507 block_offset = bitmap_offset + s->bitmap_size + offset_in_block;
15d35bc5 508
9c057d0b
JC
509 /* We must ensure that we don't write to any sectors which are marked as
510 unused in the bitmap. We get away with setting all bits in the block
511 bitmap each time we write to a new block. This might cause Virtual PC to
512 miss sparse read optimization, but it's not a problem in terms of
513 correctness. */
15d35bc5 514 if (write && (s->last_bitmap_offset != bitmap_offset)) {
3c2c599c 515 g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size);
cfc87e00 516 int r;
15d35bc5
AL
517
518 s->last_bitmap_offset = bitmap_offset;
519 memset(bitmap, 0xff, s->bitmap_size);
517b5dff 520 r = bdrv_co_pwrite_sync(bs->file, bitmap_offset, s->bitmap_size, bitmap, 0);
cfc87e00
PM
521 if (r < 0) {
522 *err = r;
523 return -2;
524 }
15d35bc5 525 }
3b46e624 526
b71d1c2e 527 return block_offset;
6a0f9e82
FB
528}
529
15d35bc5
AL
530/*
531 * Writes the footer to the end of the image file. This is needed when the
532 * file grows as it overwrites the old footer
533 *
534 * Returns 0 on success and < 0 on error
535 */
517b5dff 536static int coroutine_fn GRAPH_RDLOCK rewrite_footer(BlockDriverState *bs)
15d35bc5
AL
537{
538 int ret;
539 BDRVVPCState *s = bs->opaque;
540 int64_t offset = s->free_data_block_offset;
541
517b5dff 542 ret = bdrv_co_pwrite_sync(bs->file, offset, sizeof(s->footer), &s->footer, 0);
15d35bc5
AL
543 if (ret < 0)
544 return ret;
545
546 return 0;
547}
548
549/*
550 * Allocates a new block. This involves writing a new footer and updating
551 * the Block Allocation Table to use the space at the old end of the image
552 * file (overwriting the old footer)
553 *
554 * Returns the sectors' offset in the image file on success and < 0 on error
555 */
517b5dff
PB
556static int64_t coroutine_fn GRAPH_RDLOCK
557alloc_block(BlockDriverState *bs, int64_t offset)
15d35bc5
AL
558{
559 BDRVVPCState *s = bs->opaque;
560 int64_t bat_offset;
561 uint32_t index, bat_value;
562 int ret;
3c2c599c 563 g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size);
15d35bc5 564
9c057d0b 565 /* Check if sector_num is valid */
513b0f02
KW
566 if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) {
567 return -EINVAL;
568 }
15d35bc5 569
9c057d0b 570 /* Write entry into in-memory BAT */
513b0f02
KW
571 index = offset / s->block_size;
572 assert(s->pagetable[index] == 0xFFFFFFFF);
15d35bc5
AL
573 s->pagetable[index] = s->free_data_block_offset / 512;
574
9c057d0b 575 /* Initialize the block's bitmap */
15d35bc5 576 memset(bitmap, 0xff, s->bitmap_size);
517b5dff
PB
577 ret = bdrv_co_pwrite_sync(bs->file, s->free_data_block_offset,
578 s->bitmap_size, bitmap, 0);
5bb1cbac
KW
579 if (ret < 0) {
580 return ret;
581 }
15d35bc5 582
9c057d0b 583 /* Write new footer (the old one will be overwritten) */
15d35bc5
AL
584 s->free_data_block_offset += s->block_size + s->bitmap_size;
585 ret = rewrite_footer(bs);
586 if (ret < 0)
587 goto fail;
588
9c057d0b 589 /* Write BAT entry to disk */
15d35bc5 590 bat_offset = s->bat_offset + (4 * index);
a4127c42 591 bat_value = cpu_to_be32(s->pagetable[index]);
517b5dff 592 ret = bdrv_co_pwrite_sync(bs->file, bat_offset, 4, &bat_value, 0);
15d35bc5
AL
593 if (ret < 0)
594 goto fail;
595
cfc87e00 596 return get_image_offset(bs, offset, false, NULL);
15d35bc5
AL
597
598fail:
599 s->free_data_block_offset -= (s->block_size + s->bitmap_size);
513b0f02 600 return ret;
15d35bc5
AL
601}
602
3d47eb0a
EGE
603static int coroutine_fn
604vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
97b00e28
PB
605{
606 BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
97b00e28 607
275734e4 608 if (be32_to_cpu(s->footer.type) != VHD_FIXED) {
97b00e28
PB
609 bdi->cluster_size = s->block_size;
610 }
611
612 return 0;
613}
614
b9b10c35 615static int coroutine_fn GRAPH_RDLOCK
f7ef38dd
VSO
616vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
617 QEMUIOVector *qiov, BdrvRequestFlags flags)
6a0f9e82 618{
6c6ea921 619 BDRVVPCState *s = bs->opaque;
6a0f9e82 620 int ret;
d46b7cc6
KW
621 int64_t image_offset;
622 int64_t n_bytes;
623 int64_t bytes_done = 0;
d46b7cc6 624 QEMUIOVector local_qiov;
6a0f9e82 625
275734e4 626 if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
a03ef88f 627 return bdrv_co_preadv(bs->file, offset, bytes, qiov, 0);
24da78db 628 }
b71d1c2e 629
d46b7cc6
KW
630 qemu_co_mutex_lock(&s->lock);
631 qemu_iovec_init(&local_qiov, qiov->niov);
6c6ea921 632
d46b7cc6 633 while (bytes > 0) {
cfc87e00 634 image_offset = get_image_offset(bs, offset, false, NULL);
d46b7cc6
KW
635 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
636
637 if (image_offset == -1) {
638 qemu_iovec_memset(qiov, bytes_done, 0, n_bytes);
b71d1c2e 639 } else {
d46b7cc6
KW
640 qemu_iovec_reset(&local_qiov);
641 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
642
126734c4 643 qemu_co_mutex_unlock(&s->lock);
a03ef88f 644 ret = bdrv_co_preadv(bs->file, image_offset, n_bytes,
d46b7cc6 645 &local_qiov, 0);
126734c4 646 qemu_co_mutex_lock(&s->lock);
d46b7cc6
KW
647 if (ret < 0) {
648 goto fail;
6c6ea921 649 }
b71d1c2e
AL
650 }
651
d46b7cc6
KW
652 bytes -= n_bytes;
653 offset += n_bytes;
654 bytes_done += n_bytes;
6a0f9e82 655 }
6a0f9e82 656
d46b7cc6
KW
657 ret = 0;
658fail:
659 qemu_iovec_destroy(&local_qiov);
2914caa0 660 qemu_co_mutex_unlock(&s->lock);
d46b7cc6 661
2914caa0
PB
662 return ret;
663}
664
b9b10c35 665static int coroutine_fn GRAPH_RDLOCK
e75abeda
VSO
666vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
667 QEMUIOVector *qiov, BdrvRequestFlags flags)
15d35bc5 668{
6c6ea921 669 BDRVVPCState *s = bs->opaque;
513b0f02
KW
670 int64_t image_offset;
671 int64_t n_bytes;
672 int64_t bytes_done = 0;
c8115f8e 673 int ret = 0;
513b0f02 674 QEMUIOVector local_qiov;
15d35bc5 675
275734e4 676 if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
a03ef88f 677 return bdrv_co_pwritev(bs->file, offset, bytes, qiov, 0);
24da78db 678 }
15d35bc5 679
513b0f02
KW
680 qemu_co_mutex_lock(&s->lock);
681 qemu_iovec_init(&local_qiov, qiov->niov);
682
683 while (bytes > 0) {
cfc87e00
PM
684 image_offset = get_image_offset(bs, offset, true, &ret);
685 if (image_offset == -2) {
686 /* Failed to write block bitmap: can't proceed with write */
687 goto fail;
688 }
513b0f02 689 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
6c6ea921 690
513b0f02
KW
691 if (image_offset == -1) {
692 image_offset = alloc_block(bs, offset);
693 if (image_offset < 0) {
694 ret = image_offset;
695 goto fail;
696 }
15d35bc5
AL
697 }
698
513b0f02
KW
699 qemu_iovec_reset(&local_qiov);
700 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
701
126734c4 702 qemu_co_mutex_unlock(&s->lock);
a03ef88f 703 ret = bdrv_co_pwritev(bs->file, image_offset, n_bytes,
513b0f02 704 &local_qiov, 0);
126734c4 705 qemu_co_mutex_lock(&s->lock);
513b0f02
KW
706 if (ret < 0) {
707 goto fail;
6c6ea921 708 }
15d35bc5 709
513b0f02
KW
710 bytes -= n_bytes;
711 offset += n_bytes;
712 bytes_done += n_bytes;
15d35bc5
AL
713 }
714
513b0f02
KW
715 ret = 0;
716fail:
717 qemu_iovec_destroy(&local_qiov);
e183ef75 718 qemu_co_mutex_unlock(&s->lock);
513b0f02 719
e183ef75
PB
720 return ret;
721}
722
517b5dff
PB
723static int coroutine_fn GRAPH_RDLOCK
724vpc_co_block_status(BlockDriverState *bs, bool want_zero,
725 int64_t offset, int64_t bytes,
726 int64_t *pnum, int64_t *map,
727 BlockDriverState **file)
0cc84887
KW
728{
729 BDRVVPCState *s = bs->opaque;
2f83673b 730 int64_t image_offset;
0cc84887 731 bool allocated;
2f83673b
EB
732 int ret;
733 int64_t n;
0cc84887 734
275734e4 735 if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
2f83673b
EB
736 *pnum = bytes;
737 *map = offset;
7429e207 738 *file = bs->file->bs;
fbc8e1b7 739 return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_RECURSE;
0cc84887
KW
740 }
741
778b087e
PB
742 qemu_co_mutex_lock(&s->lock);
743
2f83673b
EB
744 image_offset = get_image_offset(bs, offset, false, NULL);
745 allocated = (image_offset != -1);
0cc84887 746 *pnum = 0;
2c060c0f 747 ret = BDRV_BLOCK_ZERO;
0cc84887
KW
748
749 do {
750 /* All sectors in a block are contiguous (without using the bitmap) */
2f83673b
EB
751 n = ROUND_UP(offset + 1, s->block_size) - offset;
752 n = MIN(n, bytes);
0cc84887
KW
753
754 *pnum += n;
2f83673b
EB
755 offset += n;
756 bytes -= n;
2ec711dc
PL
757 /* *pnum can't be greater than one block for allocated
758 * sectors since there is always a bitmap in between. */
759 if (allocated) {
7429e207 760 *file = bs->file->bs;
2f83673b
EB
761 *map = image_offset;
762 ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
778b087e 763 break;
2ec711dc 764 }
2f83673b 765 if (bytes == 0) {
0cc84887
KW
766 break;
767 }
2f83673b
EB
768 image_offset = get_image_offset(bs, offset, false, NULL);
769 } while (image_offset == -1);
0cc84887 770
778b087e
PB
771 qemu_co_mutex_unlock(&s->lock);
772 return ret;
0cc84887
KW
773}
774
57c7d9e5
AL
775/*
776 * Calculates the number of cylinders, heads and sectors per cylinder
777 * based on a given number of sectors. This is the algorithm described
778 * in the VHD specification.
779 *
780 * Note that the geometry doesn't always exactly match total_sectors but
781 * may round it down.
6e9ea0c0 782 *
c23fb11b 783 * Returns 0 on success, -EFBIG if the size is larger than 2040 GiB. Override
258d2edb
CA
784 * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB)
785 * and instead allow up to 255 heads.
57c7d9e5 786 */
5f14f31d 787static int calculate_geometry(int64_t total_sectors, uint16_t *cyls,
788 uint8_t *heads, uint8_t *secs_per_cyl)
57c7d9e5
AL
789{
790 uint32_t cyls_times_heads;
791
690cbb09 792 total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY);
57c7d9e5 793
690cbb09 794 if (total_sectors >= 65535LL * 16 * 63) {
57c7d9e5 795 *secs_per_cyl = 255;
690cbb09 796 *heads = 16;
57c7d9e5
AL
797 cyls_times_heads = total_sectors / *secs_per_cyl;
798 } else {
799 *secs_per_cyl = 17;
800 cyls_times_heads = total_sectors / *secs_per_cyl;
13f1493f 801 *heads = DIV_ROUND_UP(cyls_times_heads, 1024);
57c7d9e5 802
690cbb09 803 if (*heads < 4) {
57c7d9e5 804 *heads = 4;
690cbb09 805 }
57c7d9e5
AL
806
807 if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
808 *secs_per_cyl = 31;
809 *heads = 16;
810 cyls_times_heads = total_sectors / *secs_per_cyl;
811 }
812
813 if (cyls_times_heads >= (*heads * 1024)) {
814 *secs_per_cyl = 63;
815 *heads = 16;
816 cyls_times_heads = total_sectors / *secs_per_cyl;
817 }
818 }
819
dede4188 820 *cyls = cyls_times_heads / *heads;
6e9ea0c0
AJ
821
822 return 0;
57c7d9e5
AL
823}
824
517b5dff
PB
825static int coroutine_fn create_dynamic_disk(BlockBackend *blk, VHDFooter *footer,
826 int64_t total_sectors)
57c7d9e5 827{
e326f078 828 VHDDynDiskHeader dyndisk_header;
b0ce8cb0 829 uint8_t bat_sector[512];
57c7d9e5 830 size_t block_size, num_bat_entries;
24da78db 831 int i;
fef6070e
JC
832 int ret;
833 int64_t offset = 0;
57c7d9e5 834
9c057d0b 835 /* Write the footer (twice: at the beginning and at the end) */
57c7d9e5 836 block_size = 0x200000;
3f6de653 837 num_bat_entries = DIV_ROUND_UP(total_sectors, block_size / 512);
57c7d9e5 838
517b5dff 839 ret = blk_co_pwrite(blk, offset, sizeof(*footer), footer, 0);
40a99aac 840 if (ret < 0) {
f0ff243a
BS
841 goto fail;
842 }
57c7d9e5 843
fef6070e 844 offset = 1536 + ((num_bat_entries * 4 + 511) & ~511);
517b5dff 845 ret = blk_co_pwrite(blk, offset, sizeof(*footer), footer, 0);
fef6070e 846 if (ret < 0) {
f0ff243a
BS
847 goto fail;
848 }
57c7d9e5 849
9c057d0b 850 /* Write the initial BAT */
fef6070e 851 offset = 3 * 512;
57c7d9e5 852
b0ce8cb0 853 memset(bat_sector, 0xFF, 512);
13f1493f 854 for (i = 0; i < DIV_ROUND_UP(num_bat_entries * 4, 512); i++) {
517b5dff 855 ret = blk_co_pwrite(blk, offset, 512, bat_sector, 0);
fef6070e 856 if (ret < 0) {
f0ff243a
BS
857 goto fail;
858 }
fef6070e 859 offset += 512;
f0ff243a 860 }
57c7d9e5 861
9c057d0b 862 /* Prepare the Dynamic Disk Header */
3d6101a3 863 memset(&dyndisk_header, 0, sizeof(dyndisk_header));
57c7d9e5 864
e326f078 865 memcpy(dyndisk_header.magic, "cxsparse", 8);
57c7d9e5 866
78439f6a
CA
867 /*
868 * Note: The spec is actually wrong here for data_offset, it says
869 * 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
870 */
e326f078
MA
871 dyndisk_header.data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
872 dyndisk_header.table_offset = cpu_to_be64(3 * 512);
873 dyndisk_header.version = cpu_to_be32(0x00010000);
874 dyndisk_header.block_size = cpu_to_be32(block_size);
875 dyndisk_header.max_table_entries = cpu_to_be32(num_bat_entries);
57c7d9e5 876
3d6101a3
MA
877 dyndisk_header.checksum = cpu_to_be32(
878 vpc_checksum(&dyndisk_header, sizeof(dyndisk_header)));
57c7d9e5 879
9c057d0b 880 /* Write the header */
fef6070e 881 offset = 512;
57c7d9e5 882
517b5dff 883 ret = blk_co_pwrite(blk, offset, sizeof(dyndisk_header), &dyndisk_header, 0);
fef6070e 884 if (ret < 0) {
f0ff243a
BS
885 goto fail;
886 }
f0ff243a 887
1a37e312 888 ret = 0;
24da78db
CA
889 fail:
890 return ret;
891}
892
517b5dff
PB
893static int coroutine_fn create_fixed_disk(BlockBackend *blk, VHDFooter *footer,
894 int64_t total_size, Error **errp)
24da78db 895{
fef6070e 896 int ret;
24da78db
CA
897
898 /* Add footer to total size */
be7c5ddd 899 total_size += sizeof(*footer);
fef6070e 900
517b5dff 901 ret = blk_co_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
fef6070e
JC
902 if (ret < 0) {
903 return ret;
24da78db
CA
904 }
905
517b5dff
PB
906 ret = blk_co_pwrite(blk, total_size - sizeof(*footer), sizeof(*footer),
907 footer, 0);
fef6070e 908 if (ret < 0) {
ed3d2ec9 909 error_setg_errno(errp, -ret, "Unable to write VHD header");
fef6070e
JC
910 return ret;
911 }
24da78db 912
1a37e312 913 return 0;
24da78db
CA
914}
915
1cfeaf38
KW
916static int calculate_rounded_image_size(BlockdevCreateOptionsVpc *vpc_opts,
917 uint16_t *out_cyls,
918 uint8_t *out_heads,
919 uint8_t *out_secs_per_cyl,
920 int64_t *out_total_sectors,
921 Error **errp)
922{
923 int64_t total_size = vpc_opts->size;
924 uint16_t cyls = 0;
925 uint8_t heads = 0;
926 uint8_t secs_per_cyl = 0;
927 int64_t total_sectors;
928 int i;
929
930 /*
931 * Calculate matching total_size and geometry. Increase the number of
932 * sectors requested until we get enough (or fail). This ensures that
933 * qemu-img convert doesn't truncate images, but rather rounds up.
934 *
935 * If the image size can't be represented by a spec conformant CHS geometry,
936 * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use
937 * the image size from the VHD footer to calculate total_sectors.
938 */
939 if (vpc_opts->force_size) {
940 /* This will force the use of total_size for sector count, below */
941 cyls = VHD_CHS_MAX_C;
942 heads = VHD_CHS_MAX_H;
943 secs_per_cyl = VHD_CHS_MAX_S;
944 } else {
945 total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE);
946 for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
947 calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
948 }
949 }
950
951 if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
952 total_sectors = total_size / BDRV_SECTOR_SIZE;
953 /* Allow a maximum disk size of 2040 GiB */
954 if (total_sectors > VHD_MAX_SECTORS) {
955 error_setg(errp, "Disk size is too large, max size is 2040 GiB");
956 return -EFBIG;
957 }
958 } else {
959 total_sectors = (int64_t) cyls * heads * secs_per_cyl;
960 }
961
962 *out_total_sectors = total_sectors;
963 if (out_cyls) {
964 *out_cyls = cyls;
965 *out_heads = heads;
966 *out_secs_per_cyl = secs_per_cyl;
967 }
968
969 return 0;
970}
971
4db7ba3b
KW
972static int coroutine_fn GRAPH_UNLOCKED
973vpc_co_create(BlockdevCreateOptions *opts, Error **errp)
24da78db 974{
182c8835
KW
975 BlockdevCreateOptionsVpc *vpc_opts;
976 BlockBackend *blk = NULL;
977 BlockDriverState *bs = NULL;
978
275734e4 979 VHDFooter footer;
24da78db
CA
980 uint16_t cyls = 0;
981 uint8_t heads = 0;
982 uint8_t secs_per_cyl = 0;
983 int64_t total_sectors;
984 int64_t total_size;
985 int disk_type;
986 int ret = -EIO;
0dbaaa79 987 QemuUUID uuid;
24da78db 988
182c8835
KW
989 assert(opts->driver == BLOCKDEV_DRIVER_VPC);
990 vpc_opts = &opts->u.vpc;
991
992 /* Validate options and set default values */
993 total_size = vpc_opts->size;
994
995 if (!vpc_opts->has_subformat) {
996 vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC;
997 }
998 switch (vpc_opts->subformat) {
999 case BLOCKDEV_VPC_SUBFORMAT_DYNAMIC:
24da78db 1000 disk_type = VHD_DYNAMIC;
182c8835
KW
1001 break;
1002 case BLOCKDEV_VPC_SUBFORMAT_FIXED:
1003 disk_type = VHD_FIXED;
1004 break;
1005 default:
1006 g_assert_not_reached();
24da78db
CA
1007 }
1008
182c8835 1009 /* Create BlockBackend to write to the image */
6ef02851 1010 bs = bdrv_co_open_blockdev_ref(vpc_opts->file, errp);
182c8835
KW
1011 if (bs == NULL) {
1012 return -EIO;
24da78db 1013 }
b8f45cdf 1014
6ef02851
KW
1015 blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
1016 errp);
a3aeeab5
EB
1017 if (!blk) {
1018 ret = -EPERM;
fef6070e 1019 goto out;
4ab15590 1020 }
b8f45cdf
KW
1021 blk_set_allow_write_beyond_eof(blk, true);
1022
1cfeaf38
KW
1023 /* Get geometry and check that it matches the image size*/
1024 ret = calculate_rounded_image_size(vpc_opts, &cyls, &heads, &secs_per_cyl,
1025 &total_sectors, errp);
1026 if (ret < 0) {
1027 goto out;
690cbb09
PL
1028 }
1029
1cfeaf38
KW
1030 if (total_size != total_sectors * BDRV_SECTOR_SIZE) {
1031 error_setg(errp, "The requested image size cannot be represented in "
1032 "CHS geometry");
1033 error_append_hint(errp, "Try size=%llu or force-size=on (the "
1034 "latter makes the image incompatible with "
1035 "Virtual PC)",
1036 total_sectors * BDRV_SECTOR_SIZE);
1037 ret = -EINVAL;
1038 goto out;
24da78db 1039 }
ecd880d9 1040
24da78db 1041 /* Prepare the Hard Disk Footer */
be7c5ddd 1042 memset(&footer, 0, sizeof(footer));
24da78db 1043
275734e4 1044 memcpy(footer.creator, "conectix", 8);
182c8835 1045 if (vpc_opts->force_size) {
275734e4 1046 memcpy(footer.creator_app, "qem2", 4);
fb9245c2 1047 } else {
275734e4 1048 memcpy(footer.creator_app, "qemu", 4);
fb9245c2 1049 }
275734e4 1050 memcpy(footer.creator_os, "Wi2k", 4);
24da78db 1051
275734e4
MA
1052 footer.features = cpu_to_be32(0x02);
1053 footer.version = cpu_to_be32(0x00010000);
24da78db 1054 if (disk_type == VHD_DYNAMIC) {
be7c5ddd 1055 footer.data_offset = cpu_to_be64(sizeof(footer));
24da78db 1056 } else {
275734e4 1057 footer.data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
24da78db 1058 }
275734e4 1059 footer.timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE);
24da78db
CA
1060
1061 /* Version of Virtual PC 2007 */
275734e4
MA
1062 footer.major = cpu_to_be16(0x0005);
1063 footer.minor = cpu_to_be16(0x0003);
1064 footer.orig_size = cpu_to_be64(total_size);
1065 footer.current_size = cpu_to_be64(total_size);
1066 footer.cyls = cpu_to_be16(cyls);
1067 footer.heads = heads;
1068 footer.secs_per_cyl = secs_per_cyl;
24da78db 1069
275734e4 1070 footer.type = cpu_to_be32(disk_type);
24da78db 1071
0dbaaa79 1072 qemu_uuid_generate(&uuid);
275734e4 1073 footer.uuid = uuid;
24da78db 1074
be7c5ddd 1075 footer.checksum = cpu_to_be32(vpc_checksum(&footer, sizeof(footer)));
24da78db
CA
1076
1077 if (disk_type == VHD_DYNAMIC) {
a3d27617 1078 ret = create_dynamic_disk(blk, &footer, total_sectors);
ed3d2ec9
HR
1079 if (ret < 0) {
1080 error_setg(errp, "Unable to create or write VHD header");
1081 }
24da78db 1082 } else {
a3d27617 1083 ret = create_fixed_disk(blk, &footer, total_size, errp);
0211b9be 1084 }
24da78db 1085
fec9921f 1086out:
b2ab5f54
KW
1087 blk_co_unref(blk);
1088 bdrv_co_unref(bs);
182c8835
KW
1089 return ret;
1090}
1091
4db7ba3b 1092static int coroutine_fn GRAPH_UNLOCKED
4ec8df01
KW
1093vpc_co_create_opts(BlockDriver *drv, const char *filename,
1094 QemuOpts *opts, Error **errp)
182c8835
KW
1095{
1096 BlockdevCreateOptions *create_options = NULL;
92adf9db 1097 QDict *qdict;
182c8835
KW
1098 Visitor *v;
1099 BlockDriverState *bs = NULL;
182c8835
KW
1100 int ret;
1101
1102 static const QDictRenames opt_renames[] = {
1103 { VPC_OPT_FORCE_SIZE, "force-size" },
1104 { NULL, NULL },
1105 };
1106
1107 /* Parse options and convert legacy syntax */
1108 qdict = qemu_opts_to_qdict_filtered(opts, NULL, &vpc_create_opts, true);
1109
1110 if (!qdict_rename_keys(qdict, opt_renames, errp)) {
1111 ret = -EINVAL;
1112 goto fail;
1113 }
1114
1115 /* Create and open the file (protocol layer) */
2475a0d0 1116 ret = bdrv_co_create_file(filename, opts, errp);
182c8835 1117 if (ret < 0) {
182c8835
KW
1118 goto fail;
1119 }
1120
6ef02851
KW
1121 bs = bdrv_co_open(filename, NULL, NULL,
1122 BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
182c8835
KW
1123 if (bs == NULL) {
1124 ret = -EIO;
1125 goto fail;
1126 }
1127
1128 /* Now get the QAPI type BlockdevCreateOptions */
1129 qdict_put_str(qdict, "driver", "vpc");
1130 qdict_put_str(qdict, "file", bs->node_name);
1131
af91062e
MA
1132 v = qobject_input_visitor_new_flat_confused(qdict, errp);
1133 if (!v) {
182c8835
KW
1134 ret = -EINVAL;
1135 goto fail;
1136 }
1137
b11a093c 1138 visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp);
182c8835 1139 visit_free(v);
b11a093c 1140 if (!create_options) {
182c8835
KW
1141 ret = -EINVAL;
1142 goto fail;
1143 }
1144
1145 /* Silently round up size */
1146 assert(create_options->driver == BLOCKDEV_DRIVER_VPC);
1147 create_options->u.vpc.size =
1148 ROUND_UP(create_options->u.vpc.size, BDRV_SECTOR_SIZE);
1149
1cfeaf38
KW
1150 if (!create_options->u.vpc.force_size) {
1151 int64_t total_sectors;
1152 ret = calculate_rounded_image_size(&create_options->u.vpc, NULL, NULL,
1153 NULL, &total_sectors, errp);
1154 if (ret < 0) {
1155 goto fail;
1156 }
1157
1158 create_options->u.vpc.size = total_sectors * BDRV_SECTOR_SIZE;
1159 }
1160
1161
182c8835
KW
1162 /* Create the vpc image (format layer) */
1163 ret = vpc_co_create(create_options, errp);
1164
1165fail:
cb3e7f08 1166 qobject_unref(qdict);
b2ab5f54 1167 bdrv_co_unref(bs);
182c8835 1168 qapi_free_BlockdevCreateOptions(create_options);
f0ff243a 1169 return ret;
57c7d9e5
AL
1170}
1171
182c8835 1172
06717986 1173static int GRAPH_RDLOCK vpc_has_zero_init(BlockDriverState *bs)
72c6cc94
KW
1174{
1175 BDRVVPCState *s = bs->opaque;
72c6cc94 1176
275734e4 1177 if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
9a4f4c31 1178 return bdrv_has_zero_init(bs->file->bs);
72c6cc94
KW
1179 } else {
1180 return 1;
1181 }
1182}
1183
6a0f9e82
FB
1184static void vpc_close(BlockDriverState *bs)
1185{
1186 BDRVVPCState *s = bs->opaque;
97f1c45c 1187 qemu_vfree(s->pagetable);
6a0f9e82 1188#ifdef CACHE
7267c094 1189 g_free(s->pageentry_u8);
6a0f9e82 1190#endif
612ff3d8 1191
c8a7fc51 1192 migrate_del_blocker(&s->migration_blocker);
6a0f9e82
FB
1193}
1194
fec9921f
CL
1195static QemuOptsList vpc_create_opts = {
1196 .name = "vpc-create-opts",
1197 .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
1198 .desc = {
1199 {
1200 .name = BLOCK_OPT_SIZE,
1201 .type = QEMU_OPT_SIZE,
1202 .help = "Virtual disk size"
1203 },
1204 {
1205 .name = BLOCK_OPT_SUBFMT,
1206 .type = QEMU_OPT_STRING,
1207 .help =
1208 "Type of virtual hard disk format. Supported formats are "
1209 "{dynamic (default) | fixed} "
1210 },
fb9245c2
JC
1211 {
1212 .name = VPC_OPT_FORCE_SIZE,
1213 .type = QEMU_OPT_BOOL,
1214 .help = "Force disk size calculation to use the actual size "
1215 "specified, rather than using the nearest CHS-based "
1216 "calculation"
1217 },
fec9921f
CL
1218 { /* end of list */ }
1219 }
0e7e1989
KW
1220};
1221
2654267c
HR
1222static const char *const vpc_strong_runtime_opts[] = {
1223 VPC_OPT_SIZE_CALC,
1224
1225 NULL
1226};
1227
5efa9d5a 1228static BlockDriver bdrv_vpc = {
4a411185
KW
1229 .format_name = "vpc",
1230 .instance_size = sizeof(BDRVVPCState),
c68b89ac 1231
72c6cc94
KW
1232 .bdrv_probe = vpc_probe,
1233 .bdrv_open = vpc_open,
1234 .bdrv_close = vpc_close,
1235 .bdrv_reopen_prepare = vpc_reopen_prepare,
69dca43d 1236 .bdrv_child_perm = bdrv_default_perms,
182c8835 1237 .bdrv_co_create = vpc_co_create,
efc75e2a 1238 .bdrv_co_create_opts = vpc_co_create_opts,
0e7e1989 1239
d46b7cc6 1240 .bdrv_co_preadv = vpc_co_preadv,
513b0f02 1241 .bdrv_co_pwritev = vpc_co_pwritev,
2f83673b 1242 .bdrv_co_block_status = vpc_co_block_status,
c68b89ac 1243
3d47eb0a 1244 .bdrv_co_get_info = vpc_co_get_info,
97b00e28 1245
d67066d8 1246 .is_format = true,
fec9921f 1247 .create_opts = &vpc_create_opts,
72c6cc94 1248 .bdrv_has_zero_init = vpc_has_zero_init,
2654267c 1249 .strong_runtime_opts = vpc_strong_runtime_opts,
6a0f9e82 1250};
5efa9d5a
AL
1251
1252static void bdrv_vpc_init(void)
1253{
1254 bdrv_register(&bdrv_vpc);
1255}
1256
1257block_init(bdrv_vpc_init);