]> Git Repo - qemu.git/blame - block/vpc.c
Merge remote-tracking branch 'remotes/kraxel/tags/pull-ui-20160513-1' into staging
[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 <[email protected]>
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 */
80c71a24 25#include "qemu/osdep.h"
da34e65c 26#include "qapi/error.h"
faf07963 27#include "qemu-common.h"
737e150e 28#include "block/block_int.h"
b8f45cdf 29#include "sysemu/block-backend.h"
1de7afc9 30#include "qemu/module.h"
caf71f86 31#include "migration/migration.h"
1fe1fa51
CA
32#if defined(CONFIG_UUID)
33#include <uuid/uuid.h>
34#endif
6a0f9e82
FB
35
36/**************************************************************/
37
38#define HEADER_SIZE 512
39
40//#define CACHE
41
2cfacb62
AL
42enum vhd_type {
43 VHD_FIXED = 2,
44 VHD_DYNAMIC = 3,
45 VHD_DIFFERENCING = 4,
46};
47
9c057d0b 48/* Seconds since Jan 1, 2000 0:00:00 (UTC) */
57c7d9e5
AL
49#define VHD_TIMESTAMP_BASE 946684800
50
fb9245c2
JC
51#define VHD_CHS_MAX_C 65535LL
52#define VHD_CHS_MAX_H 16
53#define VHD_CHS_MAX_S 255
54
c23fb11b 55#define VHD_MAX_SECTORS 0xff000000 /* 2040 GiB max image size */
fb9245c2
JC
56#define VHD_MAX_GEOMETRY (VHD_CHS_MAX_C * VHD_CHS_MAX_H * VHD_CHS_MAX_S)
57
58#define VPC_OPT_FORCE_SIZE "force_size"
97f1c45c 59
9c057d0b 60/* always big-endian */
e54835c0 61typedef struct vhd_footer {
9c057d0b 62 char creator[8]; /* "conectix" */
2cfacb62
AL
63 uint32_t features;
64 uint32_t version;
65
9c057d0b 66 /* Offset of next header structure, 0xFFFFFFFF if none */
2cfacb62
AL
67 uint64_t data_offset;
68
9c057d0b 69 /* Seconds since Jan 1, 2000 0:00:00 (UTC) */
2cfacb62
AL
70 uint32_t timestamp;
71
9c057d0b 72 char creator_app[4]; /* e.g., "vpc " */
2cfacb62
AL
73 uint16_t major;
74 uint16_t minor;
9c057d0b 75 char creator_os[4]; /* "Wi2k" */
2cfacb62
AL
76
77 uint64_t orig_size;
03671ded 78 uint64_t current_size;
2cfacb62
AL
79
80 uint16_t cyls;
81 uint8_t heads;
82 uint8_t secs_per_cyl;
83
84 uint32_t type;
85
9c057d0b
JC
86 /* Checksum of the Hard Disk Footer ("one's complement of the sum of all
87 the bytes in the footer without the checksum field") */
2cfacb62
AL
88 uint32_t checksum;
89
9c057d0b 90 /* UUID used to identify a parent hard disk (backing file) */
2cfacb62
AL
91 uint8_t uuid[16];
92
93 uint8_t in_saved_state;
e54835c0 94} QEMU_PACKED VHDFooter;
b9fa33a6 95
e54835c0 96typedef struct vhd_dyndisk_header {
9c057d0b 97 char magic[8]; /* "cxsparse" */
2cfacb62 98
9c057d0b 99 /* Offset of next header structure, 0xFFFFFFFF if none */
2cfacb62
AL
100 uint64_t data_offset;
101
9c057d0b 102 /* Offset of the Block Allocation Table (BAT) */
2cfacb62
AL
103 uint64_t table_offset;
104
105 uint32_t version;
9c057d0b 106 uint32_t max_table_entries; /* 32bit/entry */
2cfacb62 107
9c057d0b 108 /* 2 MB by default, must be a power of two */
2cfacb62
AL
109 uint32_t block_size;
110
111 uint32_t checksum;
112 uint8_t parent_uuid[16];
113 uint32_t parent_timestamp;
114 uint32_t reserved;
115
9c057d0b 116 /* Backing file name (in UTF-16) */
2cfacb62
AL
117 uint8_t parent_name[512];
118
119 struct {
120 uint32_t platform;
121 uint32_t data_space;
122 uint32_t data_length;
123 uint32_t reserved;
124 uint64_t data_offset;
125 } parent_locator[8];
e54835c0 126} QEMU_PACKED VHDDynDiskHeader;
6a0f9e82
FB
127
128typedef struct BDRVVPCState {
848c66e8 129 CoMutex lock;
15d35bc5
AL
130 uint8_t footer_buf[HEADER_SIZE];
131 uint64_t free_data_block_offset;
2cfacb62 132 int max_table_entries;
6a0f9e82 133 uint32_t *pagetable;
15d35bc5
AL
134 uint64_t bat_offset;
135 uint64_t last_bitmap_offset;
6a0f9e82 136
2cfacb62 137 uint32_t block_size;
15d35bc5 138 uint32_t bitmap_size;
c540d53a
JC
139 bool force_use_chs;
140 bool force_use_sz;
15d35bc5 141
6a0f9e82
FB
142#ifdef CACHE
143 uint8_t *pageentry_u8;
144 uint32_t *pageentry_u32;
145 uint16_t *pageentry_u16;
3b46e624 146
6a0f9e82
FB
147 uint64_t last_bitmap;
148#endif
612ff3d8
KW
149
150 Error *migration_blocker;
6a0f9e82
FB
151} BDRVVPCState;
152
c540d53a
JC
153#define VPC_OPT_SIZE_CALC "force_size_calc"
154static QemuOptsList vpc_runtime_opts = {
155 .name = "vpc-runtime-opts",
156 .head = QTAILQ_HEAD_INITIALIZER(vpc_runtime_opts.head),
157 .desc = {
158 {
159 .name = VPC_OPT_SIZE_CALC,
160 .type = QEMU_OPT_STRING,
161 .help = "Force disk size calculation to use either CHS geometry, "
162 "or use the disk current_size specified in the VHD footer. "
163 "{chs, current_size}"
164 },
165 { /* end of list */ }
166 }
167};
168
57c7d9e5
AL
169static uint32_t vpc_checksum(uint8_t* buf, size_t size)
170{
171 uint32_t res = 0;
172 int i;
173
174 for (i = 0; i < size; i++)
175 res += buf[i];
176
177 return ~res;
178}
179
180
6a0f9e82
FB
181static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
182{
ffe8ab83 183 if (buf_size >= 8 && !strncmp((char *)buf, "conectix", 8))
6a0f9e82 184 return 100;
6a0f9e82
FB
185 return 0;
186}
187
c540d53a
JC
188static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts,
189 Error **errp)
190{
191 BDRVVPCState *s = bs->opaque;
192 const char *size_calc;
193
194 size_calc = qemu_opt_get(opts, VPC_OPT_SIZE_CALC);
195
196 if (!size_calc) {
197 /* no override, use autodetect only */
198 } else if (!strcmp(size_calc, "current_size")) {
199 s->force_use_sz = true;
200 } else if (!strcmp(size_calc, "chs")) {
201 s->force_use_chs = true;
202 } else {
203 error_setg(errp, "Invalid size calculation mode: '%s'", size_calc);
204 }
205}
206
015a1036
HR
207static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
208 Error **errp)
6a0f9e82
FB
209{
210 BDRVVPCState *s = bs->opaque;
66f82cee 211 int i;
e54835c0
JC
212 VHDFooter *footer;
213 VHDDynDiskHeader *dyndisk_header;
c540d53a
JC
214 QemuOpts *opts = NULL;
215 Error *local_err = NULL;
216 bool use_chs;
b9fa33a6 217 uint8_t buf[HEADER_SIZE];
57c7d9e5 218 uint32_t checksum;
97f1c45c 219 uint64_t computed_size;
b15deac7 220 uint64_t pagetable_size;
24da78db 221 int disk_type = VHD_DYNAMIC;
59294e46 222 int ret;
6a0f9e82 223
c540d53a
JC
224 opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
225 qemu_opts_absorb_qdict(opts, options, &local_err);
226 if (local_err) {
227 error_propagate(errp, local_err);
228 ret = -EINVAL;
229 goto fail;
230 }
231
232 vpc_parse_options(bs, opts, &local_err);
233 if (local_err) {
234 error_propagate(errp, local_err);
235 ret = -EINVAL;
236 goto fail;
237 }
238
9a4f4c31 239 ret = bdrv_pread(bs->file->bs, 0, s->footer_buf, HEADER_SIZE);
59294e46 240 if (ret < 0) {
32f6439c 241 error_setg(errp, "Unable to read VHD header");
6a0f9e82 242 goto fail;
59294e46 243 }
6a0f9e82 244
e54835c0 245 footer = (VHDFooter *) s->footer_buf;
24da78db 246 if (strncmp(footer->creator, "conectix", 8)) {
9a4f4c31 247 int64_t offset = bdrv_getlength(bs->file->bs);
59294e46
KW
248 if (offset < 0) {
249 ret = offset;
32f6439c 250 error_setg(errp, "Invalid file size");
59294e46
KW
251 goto fail;
252 } else if (offset < HEADER_SIZE) {
253 ret = -EINVAL;
32f6439c 254 error_setg(errp, "File too small for a VHD header");
24da78db
CA
255 goto fail;
256 }
59294e46 257
24da78db 258 /* If a fixed disk, the footer is found only at the end of the file */
9a4f4c31 259 ret = bdrv_pread(bs->file->bs, offset-HEADER_SIZE, s->footer_buf,
59294e46
KW
260 HEADER_SIZE);
261 if (ret < 0) {
24da78db
CA
262 goto fail;
263 }
264 if (strncmp(footer->creator, "conectix", 8)) {
76abe407
PB
265 error_setg(errp, "invalid VPC image");
266 ret = -EINVAL;
24da78db
CA
267 goto fail;
268 }
269 disk_type = VHD_FIXED;
270 }
6a0f9e82 271
57c7d9e5
AL
272 checksum = be32_to_cpu(footer->checksum);
273 footer->checksum = 0;
274 if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum)
275 fprintf(stderr, "block-vpc: The header checksum of '%s' is "
66f82cee 276 "incorrect.\n", bs->filename);
57c7d9e5 277
c088b691 278 /* Write 'checksum' back to footer, or else will leave it with zero. */
a4127c42 279 footer->checksum = cpu_to_be32(checksum);
c088b691 280
9c057d0b
JC
281 /* The visible size of a image in Virtual PC depends on the geometry
282 rather than on the size stored in the footer (the size in the footer
283 is too large usually) */
33ccf667
SH
284 bs->total_sectors = (int64_t)
285 be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
1fa79228 286
c540d53a
JC
287 /* Microsoft Virtual PC and Microsoft Hyper-V produce and read
288 * VHD image sizes differently. VPC will rely on CHS geometry,
289 * while Hyper-V and disk2vhd use the size specified in the footer.
290 *
291 * We use a couple of approaches to try and determine the correct method:
292 * look at the Creator App field, and look for images that have CHS
293 * geometry that is the maximum value.
294 *
295 * If the CHS geometry is the maximum CHS geometry, then we assume that
296 * the size is the footer->current_size to avoid truncation. Otherwise,
297 * we follow the table based on footer->creator_app:
298 *
299 * Known creator apps:
300 * 'vpc ' : CHS Virtual PC (uses disk geometry)
301 * 'qemu' : CHS QEMU (uses disk geometry)
fb9245c2 302 * 'qem2' : current_size QEMU (uses current_size)
c540d53a
JC
303 * 'win ' : current_size Hyper-V
304 * 'd2v ' : current_size Disk2vhd
9bdfb9e8 305 * 'tap\0' : current_size XenServer
bab246db 306 * 'CTXS' : current_size XenConverter
c540d53a
JC
307 *
308 * The user can override the table values via drive options, however
309 * even with an override we will still use current_size for images
310 * that have CHS geometry of the maximum size.
311 */
312 use_chs = (!!strncmp(footer->creator_app, "win ", 4) &&
fb9245c2 313 !!strncmp(footer->creator_app, "qem2", 4) &&
9bdfb9e8 314 !!strncmp(footer->creator_app, "d2v ", 4) &&
bab246db 315 !!strncmp(footer->creator_app, "CTXS", 4) &&
9bdfb9e8 316 !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs;
c540d53a
JC
317
318 if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) {
03671ded 319 bs->total_sectors = be64_to_cpu(footer->current_size) /
c540d53a 320 BDRV_SECTOR_SIZE;
0173e7bb
PL
321 }
322
c23fb11b
JC
323 /* Allow a maximum disk size of 2040 GiB */
324 if (bs->total_sectors > VHD_MAX_SECTORS) {
59294e46 325 ret = -EFBIG;
efc8243d
SH
326 goto fail;
327 }
328
24da78db 329 if (disk_type == VHD_DYNAMIC) {
9a4f4c31 330 ret = bdrv_pread(bs->file->bs, be64_to_cpu(footer->data_offset), buf,
59294e46
KW
331 HEADER_SIZE);
332 if (ret < 0) {
32f6439c 333 error_setg(errp, "Error reading dynamic VHD header");
24da78db
CA
334 goto fail;
335 }
b9fa33a6 336
e54835c0 337 dyndisk_header = (VHDDynDiskHeader *) buf;
6a0f9e82 338
24da78db 339 if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
32f6439c 340 error_setg(errp, "Invalid header magic");
59294e46 341 ret = -EINVAL;
24da78db
CA
342 goto fail;
343 }
6a0f9e82 344
24da78db 345 s->block_size = be32_to_cpu(dyndisk_header->block_size);
5e71dfad
KW
346 if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
347 error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
348 ret = -EINVAL;
349 goto fail;
350 }
24da78db 351 s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
15d35bc5 352
24da78db 353 s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
97f1c45c
JC
354
355 if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
32f6439c 356 error_setg(errp, "Too many blocks");
97f1c45c
JC
357 ret = -EINVAL;
358 goto fail;
359 }
97f1c45c
JC
360
361 computed_size = (uint64_t) s->max_table_entries * s->block_size;
362 if (computed_size < bs->total_sectors * 512) {
32f6439c 363 error_setg(errp, "Page table too small");
97f1c45c
JC
364 ret = -EINVAL;
365 goto fail;
366 }
367
b15deac7
JC
368 if (s->max_table_entries > SIZE_MAX / 4 ||
369 s->max_table_entries > (int) INT_MAX / 4) {
370 error_setg(errp, "Max Table Entries too large (%" PRId32 ")",
371 s->max_table_entries);
372 ret = -EINVAL;
373 goto fail;
374 }
375
376 pagetable_size = (uint64_t) s->max_table_entries * 4;
377
9a4f4c31 378 s->pagetable = qemu_try_blockalign(bs->file->bs, pagetable_size);
5fb09cd5 379 if (s->pagetable == NULL) {
32f6439c 380 error_setg(errp, "Unable to allocate memory for page table");
5fb09cd5
KW
381 ret = -ENOMEM;
382 goto fail;
383 }
b71d1c2e 384
24da78db 385 s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
59294e46 386
9a4f4c31
KW
387 ret = bdrv_pread(bs->file->bs, s->bat_offset, s->pagetable,
388 pagetable_size);
59294e46 389 if (ret < 0) {
32f6439c 390 error_setg(errp, "Error reading pagetable");
24da78db
CA
391 goto fail;
392 }
b71d1c2e 393
24da78db 394 s->free_data_block_offset =
b15deac7 395 ROUND_UP(s->bat_offset + pagetable_size, 512);
15d35bc5 396
24da78db
CA
397 for (i = 0; i < s->max_table_entries; i++) {
398 be32_to_cpus(&s->pagetable[i]);
399 if (s->pagetable[i] != 0xFFFFFFFF) {
400 int64_t next = (512 * (int64_t) s->pagetable[i]) +
401 s->bitmap_size + s->block_size;
15d35bc5 402
24da78db
CA
403 if (next > s->free_data_block_offset) {
404 s->free_data_block_offset = next;
405 }
406 }
15d35bc5 407 }
15d35bc5 408
9a4f4c31 409 if (s->free_data_block_offset > bdrv_getlength(bs->file->bs)) {
fb8fe35f
PL
410 error_setg(errp, "block-vpc: free_data_block_offset points after "
411 "the end of file. The image has been truncated.");
412 ret = -EINVAL;
413 goto fail;
414 }
415
24da78db 416 s->last_bitmap_offset = (int64_t) -1;
6a0f9e82 417
6a0f9e82 418#ifdef CACHE
24da78db
CA
419 s->pageentry_u8 = g_malloc(512);
420 s->pageentry_u32 = s->pageentry_u8;
421 s->pageentry_u16 = s->pageentry_u8;
422 s->last_pagetable = -1;
6a0f9e82 423#endif
24da78db 424 }
6a0f9e82 425
848c66e8 426 qemu_co_mutex_init(&s->lock);
612ff3d8
KW
427
428 /* Disable migration when VHD images are used */
81e5f78a
AG
429 error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
430 "does not support live migration",
431 bdrv_get_device_or_node_name(bs));
612ff3d8
KW
432 migrate_add_blocker(s->migration_blocker);
433
6a0f9e82 434 return 0;
59294e46
KW
435
436fail:
97f1c45c 437 qemu_vfree(s->pagetable);
59294e46
KW
438#ifdef CACHE
439 g_free(s->pageentry_u8);
440#endif
441 return ret;
6a0f9e82
FB
442}
443
3fe4b700
JC
444static int vpc_reopen_prepare(BDRVReopenState *state,
445 BlockReopenQueue *queue, Error **errp)
446{
447 return 0;
448}
449
b71d1c2e
AL
450/*
451 * Returns the absolute byte offset of the given sector in the image file.
452 * If the sector is not allocated, -1 is returned instead.
15d35bc5
AL
453 *
454 * The parameter write must be 1 if the offset will be used for a write
455 * operation (the block bitmaps is updated then), 0 otherwise.
b71d1c2e 456 */
d46b7cc6
KW
457static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
458 bool write)
6a0f9e82
FB
459{
460 BDRVVPCState *s = bs->opaque;
6a0f9e82 461 uint64_t bitmap_offset, block_offset;
d46b7cc6 462 uint32_t pagetable_index, offset_in_block;
6a0f9e82 463
2cfacb62 464 pagetable_index = offset / s->block_size;
d46b7cc6 465 offset_in_block = offset % s->block_size;
3b46e624 466
15d35bc5 467 if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff)
9c057d0b 468 return -1; /* not allocated */
6a0f9e82 469
378e2aea 470 bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index];
d46b7cc6 471 block_offset = bitmap_offset + s->bitmap_size + offset_in_block;
15d35bc5 472
9c057d0b
JC
473 /* We must ensure that we don't write to any sectors which are marked as
474 unused in the bitmap. We get away with setting all bits in the block
475 bitmap each time we write to a new block. This might cause Virtual PC to
476 miss sparse read optimization, but it's not a problem in terms of
477 correctness. */
15d35bc5
AL
478 if (write && (s->last_bitmap_offset != bitmap_offset)) {
479 uint8_t bitmap[s->bitmap_size];
480
481 s->last_bitmap_offset = bitmap_offset;
482 memset(bitmap, 0xff, s->bitmap_size);
9a4f4c31 483 bdrv_pwrite_sync(bs->file->bs, bitmap_offset, bitmap, s->bitmap_size);
15d35bc5 484 }
3b46e624 485
b71d1c2e 486 return block_offset;
6a0f9e82
FB
487}
488
d46b7cc6
KW
489static inline int64_t get_sector_offset(BlockDriverState *bs,
490 int64_t sector_num, bool write)
491{
492 return get_image_offset(bs, sector_num * BDRV_SECTOR_SIZE, write);
493}
494
15d35bc5
AL
495/*
496 * Writes the footer to the end of the image file. This is needed when the
497 * file grows as it overwrites the old footer
498 *
499 * Returns 0 on success and < 0 on error
500 */
501static int rewrite_footer(BlockDriverState* bs)
502{
503 int ret;
504 BDRVVPCState *s = bs->opaque;
505 int64_t offset = s->free_data_block_offset;
506
9a4f4c31 507 ret = bdrv_pwrite_sync(bs->file->bs, offset, s->footer_buf, HEADER_SIZE);
15d35bc5
AL
508 if (ret < 0)
509 return ret;
510
511 return 0;
512}
513
514/*
515 * Allocates a new block. This involves writing a new footer and updating
516 * the Block Allocation Table to use the space at the old end of the image
517 * file (overwriting the old footer)
518 *
519 * Returns the sectors' offset in the image file on success and < 0 on error
520 */
513b0f02 521static int64_t alloc_block(BlockDriverState* bs, int64_t offset)
15d35bc5
AL
522{
523 BDRVVPCState *s = bs->opaque;
524 int64_t bat_offset;
525 uint32_t index, bat_value;
526 int ret;
527 uint8_t bitmap[s->bitmap_size];
528
9c057d0b 529 /* Check if sector_num is valid */
513b0f02
KW
530 if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) {
531 return -EINVAL;
532 }
15d35bc5 533
9c057d0b 534 /* Write entry into in-memory BAT */
513b0f02
KW
535 index = offset / s->block_size;
536 assert(s->pagetable[index] == 0xFFFFFFFF);
15d35bc5
AL
537 s->pagetable[index] = s->free_data_block_offset / 512;
538
9c057d0b 539 /* Initialize the block's bitmap */
15d35bc5 540 memset(bitmap, 0xff, s->bitmap_size);
9a4f4c31 541 ret = bdrv_pwrite_sync(bs->file->bs, s->free_data_block_offset, bitmap,
078a458e 542 s->bitmap_size);
5bb1cbac
KW
543 if (ret < 0) {
544 return ret;
545 }
15d35bc5 546
9c057d0b 547 /* Write new footer (the old one will be overwritten) */
15d35bc5
AL
548 s->free_data_block_offset += s->block_size + s->bitmap_size;
549 ret = rewrite_footer(bs);
550 if (ret < 0)
551 goto fail;
552
9c057d0b 553 /* Write BAT entry to disk */
15d35bc5 554 bat_offset = s->bat_offset + (4 * index);
a4127c42 555 bat_value = cpu_to_be32(s->pagetable[index]);
9a4f4c31 556 ret = bdrv_pwrite_sync(bs->file->bs, bat_offset, &bat_value, 4);
15d35bc5
AL
557 if (ret < 0)
558 goto fail;
559
513b0f02 560 return get_image_offset(bs, offset, false);
15d35bc5
AL
561
562fail:
563 s->free_data_block_offset -= (s->block_size + s->bitmap_size);
513b0f02 564 return ret;
15d35bc5
AL
565}
566
97b00e28
PB
567static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
568{
569 BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
570 VHDFooter *footer = (VHDFooter *) s->footer_buf;
571
0d4cc3e7 572 if (be32_to_cpu(footer->type) != VHD_FIXED) {
97b00e28
PB
573 bdi->cluster_size = s->block_size;
574 }
575
95de6d70 576 bdi->unallocated_blocks_are_zero = true;
97b00e28
PB
577 return 0;
578}
579
d46b7cc6
KW
580static int coroutine_fn
581vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
582 QEMUIOVector *qiov, int flags)
6a0f9e82 583{
6c6ea921 584 BDRVVPCState *s = bs->opaque;
6a0f9e82 585 int ret;
d46b7cc6
KW
586 int64_t image_offset;
587 int64_t n_bytes;
588 int64_t bytes_done = 0;
e54835c0 589 VHDFooter *footer = (VHDFooter *) s->footer_buf;
d46b7cc6 590 QEMUIOVector local_qiov;
6a0f9e82 591
0d4cc3e7 592 if (be32_to_cpu(footer->type) == VHD_FIXED) {
d46b7cc6 593 return bdrv_co_preadv(bs->file->bs, offset, bytes, qiov, 0);
24da78db 594 }
b71d1c2e 595
d46b7cc6
KW
596 qemu_co_mutex_lock(&s->lock);
597 qemu_iovec_init(&local_qiov, qiov->niov);
6c6ea921 598
d46b7cc6
KW
599 while (bytes > 0) {
600 image_offset = get_image_offset(bs, offset, false);
601 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
602
603 if (image_offset == -1) {
604 qemu_iovec_memset(qiov, bytes_done, 0, n_bytes);
b71d1c2e 605 } else {
d46b7cc6
KW
606 qemu_iovec_reset(&local_qiov);
607 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
608
609 ret = bdrv_co_preadv(bs->file->bs, image_offset, n_bytes,
610 &local_qiov, 0);
611 if (ret < 0) {
612 goto fail;
6c6ea921 613 }
b71d1c2e
AL
614 }
615
d46b7cc6
KW
616 bytes -= n_bytes;
617 offset += n_bytes;
618 bytes_done += n_bytes;
6a0f9e82 619 }
6a0f9e82 620
d46b7cc6
KW
621 ret = 0;
622fail:
623 qemu_iovec_destroy(&local_qiov);
2914caa0 624 qemu_co_mutex_unlock(&s->lock);
d46b7cc6 625
2914caa0
PB
626 return ret;
627}
628
513b0f02
KW
629static int coroutine_fn
630vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
631 QEMUIOVector *qiov, int flags)
15d35bc5 632{
6c6ea921 633 BDRVVPCState *s = bs->opaque;
513b0f02
KW
634 int64_t image_offset;
635 int64_t n_bytes;
636 int64_t bytes_done = 0;
15d35bc5 637 int ret;
e54835c0 638 VHDFooter *footer = (VHDFooter *) s->footer_buf;
513b0f02 639 QEMUIOVector local_qiov;
15d35bc5 640
0d4cc3e7 641 if (be32_to_cpu(footer->type) == VHD_FIXED) {
513b0f02 642 return bdrv_co_pwritev(bs->file->bs, offset, bytes, qiov, 0);
24da78db 643 }
15d35bc5 644
513b0f02
KW
645 qemu_co_mutex_lock(&s->lock);
646 qemu_iovec_init(&local_qiov, qiov->niov);
647
648 while (bytes > 0) {
649 image_offset = get_image_offset(bs, offset, true);
650 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
6c6ea921 651
513b0f02
KW
652 if (image_offset == -1) {
653 image_offset = alloc_block(bs, offset);
654 if (image_offset < 0) {
655 ret = image_offset;
656 goto fail;
657 }
15d35bc5
AL
658 }
659
513b0f02
KW
660 qemu_iovec_reset(&local_qiov);
661 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
662
663 ret = bdrv_co_pwritev(bs->file->bs, image_offset, n_bytes,
664 &local_qiov, 0);
665 if (ret < 0) {
666 goto fail;
6c6ea921 667 }
15d35bc5 668
513b0f02
KW
669 bytes -= n_bytes;
670 offset += n_bytes;
671 bytes_done += n_bytes;
15d35bc5
AL
672 }
673
513b0f02
KW
674 ret = 0;
675fail:
676 qemu_iovec_destroy(&local_qiov);
e183ef75 677 qemu_co_mutex_unlock(&s->lock);
513b0f02 678
e183ef75
PB
679 return ret;
680}
681
0cc84887 682static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
67a0fd2a 683 int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
0cc84887
KW
684{
685 BDRVVPCState *s = bs->opaque;
686 VHDFooter *footer = (VHDFooter*) s->footer_buf;
2ec711dc 687 int64_t start, offset;
0cc84887
KW
688 bool allocated;
689 int n;
690
691 if (be32_to_cpu(footer->type) == VHD_FIXED) {
692 *pnum = nb_sectors;
7429e207 693 *file = bs->file->bs;
0cc84887
KW
694 return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
695 (sector_num << BDRV_SECTOR_BITS);
696 }
697
698 offset = get_sector_offset(bs, sector_num, 0);
699 start = offset;
700 allocated = (offset != -1);
701 *pnum = 0;
702
703 do {
704 /* All sectors in a block are contiguous (without using the bitmap) */
705 n = ROUND_UP(sector_num + 1, s->block_size / BDRV_SECTOR_SIZE)
706 - sector_num;
707 n = MIN(n, nb_sectors);
708
709 *pnum += n;
710 sector_num += n;
711 nb_sectors -= n;
2ec711dc
PL
712 /* *pnum can't be greater than one block for allocated
713 * sectors since there is always a bitmap in between. */
714 if (allocated) {
7429e207 715 *file = bs->file->bs;
2ec711dc
PL
716 return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
717 }
0cc84887
KW
718 if (nb_sectors == 0) {
719 break;
720 }
0cc84887 721 offset = get_sector_offset(bs, sector_num, 0);
2ec711dc 722 } while (offset == -1);
0cc84887 723
2ec711dc 724 return 0;
0cc84887
KW
725}
726
57c7d9e5
AL
727/*
728 * Calculates the number of cylinders, heads and sectors per cylinder
729 * based on a given number of sectors. This is the algorithm described
730 * in the VHD specification.
731 *
732 * Note that the geometry doesn't always exactly match total_sectors but
733 * may round it down.
6e9ea0c0 734 *
c23fb11b 735 * Returns 0 on success, -EFBIG if the size is larger than 2040 GiB. Override
258d2edb
CA
736 * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB)
737 * and instead allow up to 255 heads.
57c7d9e5 738 */
6e9ea0c0 739static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
57c7d9e5
AL
740 uint8_t* heads, uint8_t* secs_per_cyl)
741{
742 uint32_t cyls_times_heads;
743
690cbb09 744 total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY);
57c7d9e5 745
690cbb09 746 if (total_sectors >= 65535LL * 16 * 63) {
57c7d9e5 747 *secs_per_cyl = 255;
690cbb09 748 *heads = 16;
57c7d9e5
AL
749 cyls_times_heads = total_sectors / *secs_per_cyl;
750 } else {
751 *secs_per_cyl = 17;
752 cyls_times_heads = total_sectors / *secs_per_cyl;
753 *heads = (cyls_times_heads + 1023) / 1024;
754
690cbb09 755 if (*heads < 4) {
57c7d9e5 756 *heads = 4;
690cbb09 757 }
57c7d9e5
AL
758
759 if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
760 *secs_per_cyl = 31;
761 *heads = 16;
762 cyls_times_heads = total_sectors / *secs_per_cyl;
763 }
764
765 if (cyls_times_heads >= (*heads * 1024)) {
766 *secs_per_cyl = 63;
767 *heads = 16;
768 cyls_times_heads = total_sectors / *secs_per_cyl;
769 }
770 }
771
dede4188 772 *cyls = cyls_times_heads / *heads;
6e9ea0c0
AJ
773
774 return 0;
57c7d9e5
AL
775}
776
b8f45cdf 777static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
fef6070e 778 int64_t total_sectors)
57c7d9e5 779{
e54835c0
JC
780 VHDDynDiskHeader *dyndisk_header =
781 (VHDDynDiskHeader *) buf;
57c7d9e5 782 size_t block_size, num_bat_entries;
24da78db 783 int i;
fef6070e
JC
784 int ret;
785 int64_t offset = 0;
57c7d9e5 786
9c057d0b 787 /* Write the footer (twice: at the beginning and at the end) */
57c7d9e5
AL
788 block_size = 0x200000;
789 num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512);
790
8341f00d 791 ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
40a99aac 792 if (ret < 0) {
f0ff243a
BS
793 goto fail;
794 }
57c7d9e5 795
fef6070e 796 offset = 1536 + ((num_bat_entries * 4 + 511) & ~511);
8341f00d 797 ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
fef6070e 798 if (ret < 0) {
f0ff243a
BS
799 goto fail;
800 }
57c7d9e5 801
9c057d0b 802 /* Write the initial BAT */
fef6070e 803 offset = 3 * 512;
57c7d9e5
AL
804
805 memset(buf, 0xFF, 512);
f0ff243a 806 for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++) {
8341f00d 807 ret = blk_pwrite(blk, offset, buf, 512, 0);
fef6070e 808 if (ret < 0) {
f0ff243a
BS
809 goto fail;
810 }
fef6070e 811 offset += 512;
f0ff243a 812 }
57c7d9e5 813
9c057d0b 814 /* Prepare the Dynamic Disk Header */
57c7d9e5
AL
815 memset(buf, 0, 1024);
816
5ec4d682 817 memcpy(dyndisk_header->magic, "cxsparse", 8);
57c7d9e5 818
78439f6a
CA
819 /*
820 * Note: The spec is actually wrong here for data_offset, it says
821 * 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
822 */
a4127c42
SH
823 dyndisk_header->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
824 dyndisk_header->table_offset = cpu_to_be64(3 * 512);
825 dyndisk_header->version = cpu_to_be32(0x00010000);
826 dyndisk_header->block_size = cpu_to_be32(block_size);
827 dyndisk_header->max_table_entries = cpu_to_be32(num_bat_entries);
57c7d9e5 828
a4127c42 829 dyndisk_header->checksum = cpu_to_be32(vpc_checksum(buf, 1024));
57c7d9e5 830
9c057d0b 831 /* Write the header */
fef6070e 832 offset = 512;
57c7d9e5 833
8341f00d 834 ret = blk_pwrite(blk, offset, buf, 1024, 0);
fef6070e 835 if (ret < 0) {
f0ff243a
BS
836 goto fail;
837 }
f0ff243a 838
24da78db
CA
839 fail:
840 return ret;
841}
842
b8f45cdf 843static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
fef6070e 844 int64_t total_size)
24da78db 845{
fef6070e 846 int ret;
24da78db
CA
847
848 /* Add footer to total size */
fef6070e
JC
849 total_size += HEADER_SIZE;
850
b8f45cdf 851 ret = blk_truncate(blk, total_size);
fef6070e
JC
852 if (ret < 0) {
853 return ret;
24da78db
CA
854 }
855
8341f00d 856 ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
fef6070e
JC
857 if (ret < 0) {
858 return ret;
859 }
24da78db 860
24da78db
CA
861 return ret;
862}
863
fec9921f 864static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
24da78db
CA
865{
866 uint8_t buf[1024];
e54835c0 867 VHDFooter *footer = (VHDFooter *) buf;
fec9921f 868 char *disk_type_param;
fef6070e 869 int i;
24da78db
CA
870 uint16_t cyls = 0;
871 uint8_t heads = 0;
872 uint8_t secs_per_cyl = 0;
873 int64_t total_sectors;
874 int64_t total_size;
875 int disk_type;
876 int ret = -EIO;
fb9245c2 877 bool force_size;
fef6070e 878 Error *local_err = NULL;
b8f45cdf 879 BlockBackend *blk = NULL;
24da78db
CA
880
881 /* Read out options */
c2eb918e
HT
882 total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
883 BDRV_SECTOR_SIZE);
fec9921f
CL
884 disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
885 if (disk_type_param) {
886 if (!strcmp(disk_type_param, "dynamic")) {
24da78db 887 disk_type = VHD_DYNAMIC;
fec9921f 888 } else if (!strcmp(disk_type_param, "fixed")) {
24da78db
CA
889 disk_type = VHD_FIXED;
890 } else {
0211b9be 891 error_setg(errp, "Invalid disk type, %s", disk_type_param);
fec9921f
CL
892 ret = -EINVAL;
893 goto out;
24da78db
CA
894 }
895 } else {
896 disk_type = VHD_DYNAMIC;
897 }
898
fb9245c2
JC
899 force_size = qemu_opt_get_bool_del(opts, VPC_OPT_FORCE_SIZE, false);
900
fef6070e
JC
901 ret = bdrv_create_file(filename, opts, &local_err);
902 if (ret < 0) {
903 error_propagate(errp, local_err);
fec9921f 904 goto out;
24da78db 905 }
b8f45cdf 906
efaa7c4e 907 blk = blk_new_open(filename, NULL, NULL,
72e775c7 908 BDRV_O_RDWR | BDRV_O_PROTOCOL, &local_err);
b8f45cdf 909 if (blk == NULL) {
fef6070e 910 error_propagate(errp, local_err);
b8f45cdf 911 ret = -EIO;
fef6070e 912 goto out;
4ab15590
CL
913 }
914
b8f45cdf
KW
915 blk_set_allow_write_beyond_eof(blk, true);
916
ecd880d9
KW
917 /*
918 * Calculate matching total_size and geometry. Increase the number of
919 * sectors requested until we get enough (or fail). This ensures that
920 * qemu-img convert doesn't truncate images, but rather rounds up.
690cbb09 921 *
fb9245c2 922 * If the image size can't be represented by a spec conformant CHS geometry,
690cbb09
PL
923 * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use
924 * the image size from the VHD footer to calculate total_sectors.
ecd880d9 925 */
fb9245c2
JC
926 if (force_size) {
927 /* This will force the use of total_size for sector count, below */
928 cyls = VHD_CHS_MAX_C;
929 heads = VHD_CHS_MAX_H;
930 secs_per_cyl = VHD_CHS_MAX_S;
931 } else {
932 total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE);
933 for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
934 calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
935 }
690cbb09
PL
936 }
937
938 if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
939 total_sectors = total_size / BDRV_SECTOR_SIZE;
c23fb11b 940 /* Allow a maximum disk size of 2040 GiB */
690cbb09 941 if (total_sectors > VHD_MAX_SECTORS) {
0211b9be 942 error_setg(errp, "Disk size is too large, max size is 2040 GiB");
24da78db 943 ret = -EFBIG;
fef6070e 944 goto out;
24da78db 945 }
690cbb09
PL
946 } else {
947 total_sectors = (int64_t)cyls * heads * secs_per_cyl;
948 total_size = total_sectors * BDRV_SECTOR_SIZE;
24da78db 949 }
ecd880d9 950
24da78db
CA
951 /* Prepare the Hard Disk Footer */
952 memset(buf, 0, 1024);
953
954 memcpy(footer->creator, "conectix", 8);
fb9245c2
JC
955 if (force_size) {
956 memcpy(footer->creator_app, "qem2", 4);
957 } else {
958 memcpy(footer->creator_app, "qemu", 4);
959 }
24da78db
CA
960 memcpy(footer->creator_os, "Wi2k", 4);
961
a4127c42
SH
962 footer->features = cpu_to_be32(0x02);
963 footer->version = cpu_to_be32(0x00010000);
24da78db 964 if (disk_type == VHD_DYNAMIC) {
a4127c42 965 footer->data_offset = cpu_to_be64(HEADER_SIZE);
24da78db 966 } else {
a4127c42 967 footer->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
24da78db 968 }
a4127c42 969 footer->timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE);
24da78db
CA
970
971 /* Version of Virtual PC 2007 */
a4127c42
SH
972 footer->major = cpu_to_be16(0x0005);
973 footer->minor = cpu_to_be16(0x0003);
3f3f20dc 974 footer->orig_size = cpu_to_be64(total_size);
03671ded 975 footer->current_size = cpu_to_be64(total_size);
a4127c42 976 footer->cyls = cpu_to_be16(cyls);
24da78db
CA
977 footer->heads = heads;
978 footer->secs_per_cyl = secs_per_cyl;
979
a4127c42 980 footer->type = cpu_to_be32(disk_type);
24da78db 981
1fe1fa51
CA
982#if defined(CONFIG_UUID)
983 uuid_generate(footer->uuid);
984#endif
24da78db 985
a4127c42 986 footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));
24da78db
CA
987
988 if (disk_type == VHD_DYNAMIC) {
b8f45cdf 989 ret = create_dynamic_disk(blk, buf, total_sectors);
24da78db 990 } else {
b8f45cdf 991 ret = create_fixed_disk(blk, buf, total_size);
24da78db 992 }
0211b9be
JC
993 if (ret < 0) {
994 error_setg(errp, "Unable to create or write VHD header");
995 }
24da78db 996
fec9921f 997out:
b8f45cdf 998 blk_unref(blk);
fec9921f 999 g_free(disk_type_param);
f0ff243a 1000 return ret;
57c7d9e5
AL
1001}
1002
72c6cc94
KW
1003static int vpc_has_zero_init(BlockDriverState *bs)
1004{
1005 BDRVVPCState *s = bs->opaque;
e54835c0 1006 VHDFooter *footer = (VHDFooter *) s->footer_buf;
72c6cc94 1007
0d4cc3e7 1008 if (be32_to_cpu(footer->type) == VHD_FIXED) {
9a4f4c31 1009 return bdrv_has_zero_init(bs->file->bs);
72c6cc94
KW
1010 } else {
1011 return 1;
1012 }
1013}
1014
6a0f9e82
FB
1015static void vpc_close(BlockDriverState *bs)
1016{
1017 BDRVVPCState *s = bs->opaque;
97f1c45c 1018 qemu_vfree(s->pagetable);
6a0f9e82 1019#ifdef CACHE
7267c094 1020 g_free(s->pageentry_u8);
6a0f9e82 1021#endif
612ff3d8
KW
1022
1023 migrate_del_blocker(s->migration_blocker);
1024 error_free(s->migration_blocker);
6a0f9e82
FB
1025}
1026
fec9921f
CL
1027static QemuOptsList vpc_create_opts = {
1028 .name = "vpc-create-opts",
1029 .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
1030 .desc = {
1031 {
1032 .name = BLOCK_OPT_SIZE,
1033 .type = QEMU_OPT_SIZE,
1034 .help = "Virtual disk size"
1035 },
1036 {
1037 .name = BLOCK_OPT_SUBFMT,
1038 .type = QEMU_OPT_STRING,
1039 .help =
1040 "Type of virtual hard disk format. Supported formats are "
1041 "{dynamic (default) | fixed} "
1042 },
fb9245c2
JC
1043 {
1044 .name = VPC_OPT_FORCE_SIZE,
1045 .type = QEMU_OPT_BOOL,
1046 .help = "Force disk size calculation to use the actual size "
1047 "specified, rather than using the nearest CHS-based "
1048 "calculation"
1049 },
fec9921f
CL
1050 { /* end of list */ }
1051 }
0e7e1989
KW
1052};
1053
5efa9d5a 1054static BlockDriver bdrv_vpc = {
4a411185
KW
1055 .format_name = "vpc",
1056 .instance_size = sizeof(BDRVVPCState),
c68b89ac 1057
72c6cc94
KW
1058 .bdrv_probe = vpc_probe,
1059 .bdrv_open = vpc_open,
1060 .bdrv_close = vpc_close,
1061 .bdrv_reopen_prepare = vpc_reopen_prepare,
c282e1fd 1062 .bdrv_create = vpc_create,
0e7e1989 1063
d46b7cc6 1064 .bdrv_co_preadv = vpc_co_preadv,
513b0f02 1065 .bdrv_co_pwritev = vpc_co_pwritev,
0cc84887 1066 .bdrv_co_get_block_status = vpc_co_get_block_status,
c68b89ac 1067
97b00e28
PB
1068 .bdrv_get_info = vpc_get_info,
1069
fec9921f 1070 .create_opts = &vpc_create_opts,
72c6cc94 1071 .bdrv_has_zero_init = vpc_has_zero_init,
6a0f9e82 1072};
5efa9d5a
AL
1073
1074static void bdrv_vpc_init(void)
1075{
1076 bdrv_register(&bdrv_vpc);
1077}
1078
1079block_init(bdrv_vpc_init);
This page took 0.785869 seconds and 4 git commands to generate.