1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "qapi/error.h"
28#include "block/block_int.h"
29#include "block/qdict.h"
30#include "sysemu/block-backend.h"
31#include "qemu/module.h"
32#include "qemu/option.h"
33#include "migration/blocker.h"
34#include "qemu/bswap.h"
35#include "qemu/uuid.h"
36#include "qapi/qmp/qdict.h"
37#include "qapi/qobject-input-visitor.h"
38#include "qapi/qapi-visit-block-core.h"
39
40
41
42#define HEADER_SIZE 512
43
44
45
46enum vhd_type {
47 VHD_FIXED = 2,
48 VHD_DYNAMIC = 3,
49 VHD_DIFFERENCING = 4,
50};
51
52
53#define VHD_TIMESTAMP_BASE 946684800
54
55#define VHD_CHS_MAX_C 65535LL
56#define VHD_CHS_MAX_H 16
57#define VHD_CHS_MAX_S 255
58
59#define VHD_MAX_SECTORS 0xff000000
60#define VHD_MAX_GEOMETRY (VHD_CHS_MAX_C * VHD_CHS_MAX_H * VHD_CHS_MAX_S)
61
62#define VPC_OPT_FORCE_SIZE "force_size"
63
64
65typedef struct vhd_footer {
66 char creator[8];
67 uint32_t features;
68 uint32_t version;
69
70
71 uint64_t data_offset;
72
73
74 uint32_t timestamp;
75
76 char creator_app[4];
77 uint16_t major;
78 uint16_t minor;
79 char creator_os[4];
80
81 uint64_t orig_size;
82 uint64_t current_size;
83
84 uint16_t cyls;
85 uint8_t heads;
86 uint8_t secs_per_cyl;
87
88 uint32_t type;
89
90
91
92 uint32_t checksum;
93
94
95 QemuUUID uuid;
96
97 uint8_t in_saved_state;
98} QEMU_PACKED VHDFooter;
99
100typedef struct vhd_dyndisk_header {
101 char magic[8];
102
103
104 uint64_t data_offset;
105
106
107 uint64_t table_offset;
108
109 uint32_t version;
110 uint32_t max_table_entries;
111
112
113 uint32_t block_size;
114
115 uint32_t checksum;
116 uint8_t parent_uuid[16];
117 uint32_t parent_timestamp;
118 uint32_t reserved;
119
120
121 uint8_t parent_name[512];
122
123 struct {
124 uint32_t platform;
125 uint32_t data_space;
126 uint32_t data_length;
127 uint32_t reserved;
128 uint64_t data_offset;
129 } parent_locator[8];
130} QEMU_PACKED VHDDynDiskHeader;
131
132typedef struct BDRVVPCState {
133 CoMutex lock;
134 uint8_t footer_buf[HEADER_SIZE];
135 uint64_t free_data_block_offset;
136 int max_table_entries;
137 uint32_t *pagetable;
138 uint64_t bat_offset;
139 uint64_t last_bitmap_offset;
140
141 uint32_t block_size;
142 uint32_t bitmap_size;
143 bool force_use_chs;
144 bool force_use_sz;
145
146#ifdef CACHE
147 uint8_t *pageentry_u8;
148 uint32_t *pageentry_u32;
149 uint16_t *pageentry_u16;
150
151 uint64_t last_bitmap;
152#endif
153
154 Error *migration_blocker;
155} BDRVVPCState;
156
157#define VPC_OPT_SIZE_CALC "force_size_calc"
158static QemuOptsList vpc_runtime_opts = {
159 .name = "vpc-runtime-opts",
160 .head = QTAILQ_HEAD_INITIALIZER(vpc_runtime_opts.head),
161 .desc = {
162 {
163 .name = VPC_OPT_SIZE_CALC,
164 .type = QEMU_OPT_STRING,
165 .help = "Force disk size calculation to use either CHS geometry, "
166 "or use the disk current_size specified in the VHD footer. "
167 "{chs, current_size}"
168 },
169 { }
170 }
171};
172
173static QemuOptsList vpc_create_opts;
174
175static uint32_t vpc_checksum(uint8_t* buf, size_t size)
176{
177 uint32_t res = 0;
178 int i;
179
180 for (i = 0; i < size; i++)
181 res += buf[i];
182
183 return ~res;
184}
185
186
187static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
188{
189 if (buf_size >= 8 && !strncmp((char *)buf, "conectix", 8))
190 return 100;
191 return 0;
192}
193
194static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts,
195 Error **errp)
196{
197 BDRVVPCState *s = bs->opaque;
198 const char *size_calc;
199
200 size_calc = qemu_opt_get(opts, VPC_OPT_SIZE_CALC);
201
202 if (!size_calc) {
203
204 } else if (!strcmp(size_calc, "current_size")) {
205 s->force_use_sz = true;
206 } else if (!strcmp(size_calc, "chs")) {
207 s->force_use_chs = true;
208 } else {
209 error_setg(errp, "Invalid size calculation mode: '%s'", size_calc);
210 }
211}
212
213static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
214 Error **errp)
215{
216 BDRVVPCState *s = bs->opaque;
217 int i;
218 VHDFooter *footer;
219 VHDDynDiskHeader *dyndisk_header;
220 QemuOpts *opts = NULL;
221 Error *local_err = NULL;
222 bool use_chs;
223 uint8_t buf[HEADER_SIZE];
224 uint32_t checksum;
225 uint64_t computed_size;
226 uint64_t pagetable_size;
227 int disk_type = VHD_DYNAMIC;
228 int ret;
229 int64_t bs_size;
230
231 bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
232 false, errp);
233 if (!bs->file) {
234 return -EINVAL;
235 }
236
237 opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
238 qemu_opts_absorb_qdict(opts, options, &local_err);
239 if (local_err) {
240 error_propagate(errp, local_err);
241 ret = -EINVAL;
242 goto fail;
243 }
244
245 vpc_parse_options(bs, opts, &local_err);
246 if (local_err) {
247 error_propagate(errp, local_err);
248 ret = -EINVAL;
249 goto fail;
250 }
251
252 ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE);
253 if (ret < 0) {
254 error_setg(errp, "Unable to read VHD header");
255 goto fail;
256 }
257
258 footer = (VHDFooter *) s->footer_buf;
259 if (strncmp(footer->creator, "conectix", 8)) {
260 int64_t offset = bdrv_getlength(bs->file->bs);
261 if (offset < 0) {
262 ret = offset;
263 error_setg(errp, "Invalid file size");
264 goto fail;
265 } else if (offset < HEADER_SIZE) {
266 ret = -EINVAL;
267 error_setg(errp, "File too small for a VHD header");
268 goto fail;
269 }
270
271
272 ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf,
273 HEADER_SIZE);
274 if (ret < 0) {
275 goto fail;
276 }
277 if (strncmp(footer->creator, "conectix", 8)) {
278 error_setg(errp, "invalid VPC image");
279 ret = -EINVAL;
280 goto fail;
281 }
282 disk_type = VHD_FIXED;
283 }
284
285 checksum = be32_to_cpu(footer->checksum);
286 footer->checksum = 0;
287 if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum) {
288 error_setg(errp, "Incorrect header checksum");
289 ret = -EINVAL;
290 goto fail;
291 }
292
293
294 footer->checksum = cpu_to_be32(checksum);
295
296
297
298
299 bs->total_sectors = (int64_t)
300 be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 use_chs = (!!strncmp(footer->creator_app, "win ", 4) &&
328 !!strncmp(footer->creator_app, "qem2", 4) &&
329 !!strncmp(footer->creator_app, "d2v ", 4) &&
330 !!strncmp(footer->creator_app, "CTXS", 4) &&
331 !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs;
332
333 if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) {
334 bs->total_sectors = be64_to_cpu(footer->current_size) /
335 BDRV_SECTOR_SIZE;
336 }
337
338
339 if (bs->total_sectors > VHD_MAX_SECTORS) {
340 ret = -EFBIG;
341 goto fail;
342 }
343
344 if (disk_type == VHD_DYNAMIC) {
345 ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
346 HEADER_SIZE);
347 if (ret < 0) {
348 error_setg(errp, "Error reading dynamic VHD header");
349 goto fail;
350 }
351
352 dyndisk_header = (VHDDynDiskHeader *) buf;
353
354 if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
355 error_setg(errp, "Invalid header magic");
356 ret = -EINVAL;
357 goto fail;
358 }
359
360 s->block_size = be32_to_cpu(dyndisk_header->block_size);
361 if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
362 error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
363 ret = -EINVAL;
364 goto fail;
365 }
366 s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
367
368 s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
369
370 if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
371 error_setg(errp, "Too many blocks");
372 ret = -EINVAL;
373 goto fail;
374 }
375
376 computed_size = (uint64_t) s->max_table_entries * s->block_size;
377 if (computed_size < bs->total_sectors * 512) {
378 error_setg(errp, "Page table too small");
379 ret = -EINVAL;
380 goto fail;
381 }
382
383 if (s->max_table_entries > SIZE_MAX / 4 ||
384 s->max_table_entries > (int) INT_MAX / 4) {
385 error_setg(errp, "Max Table Entries too large (%" PRId32 ")",
386 s->max_table_entries);
387 ret = -EINVAL;
388 goto fail;
389 }
390
391 pagetable_size = (uint64_t) s->max_table_entries * 4;
392
393 s->pagetable = qemu_try_blockalign(bs->file->bs, pagetable_size);
394 if (s->pagetable == NULL) {
395 error_setg(errp, "Unable to allocate memory for page table");
396 ret = -ENOMEM;
397 goto fail;
398 }
399
400 s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
401
402 ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
403 pagetable_size);
404 if (ret < 0) {
405 error_setg(errp, "Error reading pagetable");
406 goto fail;
407 }
408
409 s->free_data_block_offset =
410 ROUND_UP(s->bat_offset + pagetable_size, 512);
411
412 for (i = 0; i < s->max_table_entries; i++) {
413 be32_to_cpus(&s->pagetable[i]);
414 if (s->pagetable[i] != 0xFFFFFFFF) {
415 int64_t next = (512 * (int64_t) s->pagetable[i]) +
416 s->bitmap_size + s->block_size;
417
418 if (next > s->free_data_block_offset) {
419 s->free_data_block_offset = next;
420 }
421 }
422 }
423
424 bs_size = bdrv_getlength(bs->file->bs);
425 if (bs_size < 0) {
426 error_setg_errno(errp, -bs_size, "Unable to learn image size");
427 ret = bs_size;
428 goto fail;
429 }
430 if (s->free_data_block_offset > bs_size) {
431 error_setg(errp, "block-vpc: free_data_block_offset points after "
432 "the end of file. The image has been truncated.");
433 ret = -EINVAL;
434 goto fail;
435 }
436
437 s->last_bitmap_offset = (int64_t) -1;
438
439#ifdef CACHE
440 s->pageentry_u8 = g_malloc(512);
441 s->pageentry_u32 = s->pageentry_u8;
442 s->pageentry_u16 = s->pageentry_u8;
443 s->last_pagetable = -1;
444#endif
445 }
446
447
448 error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
449 "does not support live migration",
450 bdrv_get_device_or_node_name(bs));
451 ret = migrate_add_blocker(s->migration_blocker, &local_err);
452 if (local_err) {
453 error_propagate(errp, local_err);
454 error_free(s->migration_blocker);
455 goto fail;
456 }
457
458 qemu_co_mutex_init(&s->lock);
459 qemu_opts_del(opts);
460
461 return 0;
462
463fail:
464 qemu_opts_del(opts);
465 qemu_vfree(s->pagetable);
466#ifdef CACHE
467 g_free(s->pageentry_u8);
468#endif
469 return ret;
470}
471
472static int vpc_reopen_prepare(BDRVReopenState *state,
473 BlockReopenQueue *queue, Error **errp)
474{
475 return 0;
476}
477
478
479
480
481
482
483
484
485
486
487
488
489static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
490 bool write, int *err)
491{
492 BDRVVPCState *s = bs->opaque;
493 uint64_t bitmap_offset, block_offset;
494 uint32_t pagetable_index, offset_in_block;
495
496 assert(!(write && err == NULL));
497
498 pagetable_index = offset / s->block_size;
499 offset_in_block = offset % s->block_size;
500
501 if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff)
502 return -1;
503
504 bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index];
505 block_offset = bitmap_offset + s->bitmap_size + offset_in_block;
506
507
508
509
510
511
512 if (write && (s->last_bitmap_offset != bitmap_offset)) {
513 uint8_t bitmap[s->bitmap_size];
514 int r;
515
516 s->last_bitmap_offset = bitmap_offset;
517 memset(bitmap, 0xff, s->bitmap_size);
518 r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
519 if (r < 0) {
520 *err = r;
521 return -2;
522 }
523 }
524
525 return block_offset;
526}
527
528
529
530
531
532
533
534static int rewrite_footer(BlockDriverState* bs)
535{
536 int ret;
537 BDRVVPCState *s = bs->opaque;
538 int64_t offset = s->free_data_block_offset;
539
540 ret = bdrv_pwrite_sync(bs->file, offset, s->footer_buf, HEADER_SIZE);
541 if (ret < 0)
542 return ret;
543
544 return 0;
545}
546
547
548
549
550
551
552
553
554static int64_t alloc_block(BlockDriverState* bs, int64_t offset)
555{
556 BDRVVPCState *s = bs->opaque;
557 int64_t bat_offset;
558 uint32_t index, bat_value;
559 int ret;
560 uint8_t bitmap[s->bitmap_size];
561
562
563 if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) {
564 return -EINVAL;
565 }
566
567
568 index = offset / s->block_size;
569 assert(s->pagetable[index] == 0xFFFFFFFF);
570 s->pagetable[index] = s->free_data_block_offset / 512;
571
572
573 memset(bitmap, 0xff, s->bitmap_size);
574 ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
575 s->bitmap_size);
576 if (ret < 0) {
577 return ret;
578 }
579
580
581 s->free_data_block_offset += s->block_size + s->bitmap_size;
582 ret = rewrite_footer(bs);
583 if (ret < 0)
584 goto fail;
585
586
587 bat_offset = s->bat_offset + (4 * index);
588 bat_value = cpu_to_be32(s->pagetable[index]);
589 ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4);
590 if (ret < 0)
591 goto fail;
592
593 return get_image_offset(bs, offset, false, NULL);
594
595fail:
596 s->free_data_block_offset -= (s->block_size + s->bitmap_size);
597 return ret;
598}
599
600static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
601{
602 BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
603 VHDFooter *footer = (VHDFooter *) s->footer_buf;
604
605 if (be32_to_cpu(footer->type) != VHD_FIXED) {
606 bdi->cluster_size = s->block_size;
607 }
608
609 bdi->unallocated_blocks_are_zero = true;
610 return 0;
611}
612
613static int coroutine_fn
614vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
615 QEMUIOVector *qiov, int flags)
616{
617 BDRVVPCState *s = bs->opaque;
618 int ret;
619 int64_t image_offset;
620 int64_t n_bytes;
621 int64_t bytes_done = 0;
622 VHDFooter *footer = (VHDFooter *) s->footer_buf;
623 QEMUIOVector local_qiov;
624
625 if (be32_to_cpu(footer->type) == VHD_FIXED) {
626 return bdrv_co_preadv(bs->file, offset, bytes, qiov, 0);
627 }
628
629 qemu_co_mutex_lock(&s->lock);
630 qemu_iovec_init(&local_qiov, qiov->niov);
631
632 while (bytes > 0) {
633 image_offset = get_image_offset(bs, offset, false, NULL);
634 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
635
636 if (image_offset == -1) {
637 qemu_iovec_memset(qiov, bytes_done, 0, n_bytes);
638 } else {
639 qemu_iovec_reset(&local_qiov);
640 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
641
642 ret = bdrv_co_preadv(bs->file, image_offset, n_bytes,
643 &local_qiov, 0);
644 if (ret < 0) {
645 goto fail;
646 }
647 }
648
649 bytes -= n_bytes;
650 offset += n_bytes;
651 bytes_done += n_bytes;
652 }
653
654 ret = 0;
655fail:
656 qemu_iovec_destroy(&local_qiov);
657 qemu_co_mutex_unlock(&s->lock);
658
659 return ret;
660}
661
662static int coroutine_fn
663vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
664 QEMUIOVector *qiov, int flags)
665{
666 BDRVVPCState *s = bs->opaque;
667 int64_t image_offset;
668 int64_t n_bytes;
669 int64_t bytes_done = 0;
670 int ret = 0;
671 VHDFooter *footer = (VHDFooter *) s->footer_buf;
672 QEMUIOVector local_qiov;
673
674 if (be32_to_cpu(footer->type) == VHD_FIXED) {
675 return bdrv_co_pwritev(bs->file, offset, bytes, qiov, 0);
676 }
677
678 qemu_co_mutex_lock(&s->lock);
679 qemu_iovec_init(&local_qiov, qiov->niov);
680
681 while (bytes > 0) {
682 image_offset = get_image_offset(bs, offset, true, &ret);
683 if (image_offset == -2) {
684
685 goto fail;
686 }
687 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
688
689 if (image_offset == -1) {
690 image_offset = alloc_block(bs, offset);
691 if (image_offset < 0) {
692 ret = image_offset;
693 goto fail;
694 }
695 }
696
697 qemu_iovec_reset(&local_qiov);
698 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
699
700 ret = bdrv_co_pwritev(bs->file, image_offset, n_bytes,
701 &local_qiov, 0);
702 if (ret < 0) {
703 goto fail;
704 }
705
706 bytes -= n_bytes;
707 offset += n_bytes;
708 bytes_done += n_bytes;
709 }
710
711 ret = 0;
712fail:
713 qemu_iovec_destroy(&local_qiov);
714 qemu_co_mutex_unlock(&s->lock);
715
716 return ret;
717}
718
719static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
720 bool want_zero,
721 int64_t offset, int64_t bytes,
722 int64_t *pnum, int64_t *map,
723 BlockDriverState **file)
724{
725 BDRVVPCState *s = bs->opaque;
726 VHDFooter *footer = (VHDFooter*) s->footer_buf;
727 int64_t image_offset;
728 bool allocated;
729 int ret;
730 int64_t n;
731
732 if (be32_to_cpu(footer->type) == VHD_FIXED) {
733 *pnum = bytes;
734 *map = offset;
735 *file = bs->file->bs;
736 return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
737 }
738
739 qemu_co_mutex_lock(&s->lock);
740
741 image_offset = get_image_offset(bs, offset, false, NULL);
742 allocated = (image_offset != -1);
743 *pnum = 0;
744 ret = 0;
745
746 do {
747
748 n = ROUND_UP(offset + 1, s->block_size) - offset;
749 n = MIN(n, bytes);
750
751 *pnum += n;
752 offset += n;
753 bytes -= n;
754
755
756 if (allocated) {
757 *file = bs->file->bs;
758 *map = image_offset;
759 ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
760 break;
761 }
762 if (bytes == 0) {
763 break;
764 }
765 image_offset = get_image_offset(bs, offset, false, NULL);
766 } while (image_offset == -1);
767
768 qemu_co_mutex_unlock(&s->lock);
769 return ret;
770}
771
772
773
774
775
776
777
778
779
780
781
782
783
784static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
785 uint8_t* heads, uint8_t* secs_per_cyl)
786{
787 uint32_t cyls_times_heads;
788
789 total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY);
790
791 if (total_sectors >= 65535LL * 16 * 63) {
792 *secs_per_cyl = 255;
793 *heads = 16;
794 cyls_times_heads = total_sectors / *secs_per_cyl;
795 } else {
796 *secs_per_cyl = 17;
797 cyls_times_heads = total_sectors / *secs_per_cyl;
798 *heads = DIV_ROUND_UP(cyls_times_heads, 1024);
799
800 if (*heads < 4) {
801 *heads = 4;
802 }
803
804 if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
805 *secs_per_cyl = 31;
806 *heads = 16;
807 cyls_times_heads = total_sectors / *secs_per_cyl;
808 }
809
810 if (cyls_times_heads >= (*heads * 1024)) {
811 *secs_per_cyl = 63;
812 *heads = 16;
813 cyls_times_heads = total_sectors / *secs_per_cyl;
814 }
815 }
816
817 *cyls = cyls_times_heads / *heads;
818
819 return 0;
820}
821
822static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
823 int64_t total_sectors)
824{
825 VHDDynDiskHeader *dyndisk_header =
826 (VHDDynDiskHeader *) buf;
827 size_t block_size, num_bat_entries;
828 int i;
829 int ret;
830 int64_t offset = 0;
831
832
833 block_size = 0x200000;
834 num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512);
835
836 ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
837 if (ret < 0) {
838 goto fail;
839 }
840
841 offset = 1536 + ((num_bat_entries * 4 + 511) & ~511);
842 ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
843 if (ret < 0) {
844 goto fail;
845 }
846
847
848 offset = 3 * 512;
849
850 memset(buf, 0xFF, 512);
851 for (i = 0; i < DIV_ROUND_UP(num_bat_entries * 4, 512); i++) {
852 ret = blk_pwrite(blk, offset, buf, 512, 0);
853 if (ret < 0) {
854 goto fail;
855 }
856 offset += 512;
857 }
858
859
860 memset(buf, 0, 1024);
861
862 memcpy(dyndisk_header->magic, "cxsparse", 8);
863
864
865
866
867
868 dyndisk_header->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
869 dyndisk_header->table_offset = cpu_to_be64(3 * 512);
870 dyndisk_header->version = cpu_to_be32(0x00010000);
871 dyndisk_header->block_size = cpu_to_be32(block_size);
872 dyndisk_header->max_table_entries = cpu_to_be32(num_bat_entries);
873
874 dyndisk_header->checksum = cpu_to_be32(vpc_checksum(buf, 1024));
875
876
877 offset = 512;
878
879 ret = blk_pwrite(blk, offset, buf, 1024, 0);
880 if (ret < 0) {
881 goto fail;
882 }
883
884 fail:
885 return ret;
886}
887
888static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
889 int64_t total_size, Error **errp)
890{
891 int ret;
892
893
894 total_size += HEADER_SIZE;
895
896 ret = blk_truncate(blk, total_size, PREALLOC_MODE_OFF, errp);
897 if (ret < 0) {
898 return ret;
899 }
900
901 ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
902 if (ret < 0) {
903 error_setg_errno(errp, -ret, "Unable to write VHD header");
904 return ret;
905 }
906
907 return ret;
908}
909
910static int calculate_rounded_image_size(BlockdevCreateOptionsVpc *vpc_opts,
911 uint16_t *out_cyls,
912 uint8_t *out_heads,
913 uint8_t *out_secs_per_cyl,
914 int64_t *out_total_sectors,
915 Error **errp)
916{
917 int64_t total_size = vpc_opts->size;
918 uint16_t cyls = 0;
919 uint8_t heads = 0;
920 uint8_t secs_per_cyl = 0;
921 int64_t total_sectors;
922 int i;
923
924
925
926
927
928
929
930
931
932
933 if (vpc_opts->force_size) {
934
935 cyls = VHD_CHS_MAX_C;
936 heads = VHD_CHS_MAX_H;
937 secs_per_cyl = VHD_CHS_MAX_S;
938 } else {
939 total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE);
940 for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
941 calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
942 }
943 }
944
945 if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
946 total_sectors = total_size / BDRV_SECTOR_SIZE;
947
948 if (total_sectors > VHD_MAX_SECTORS) {
949 error_setg(errp, "Disk size is too large, max size is 2040 GiB");
950 return -EFBIG;
951 }
952 } else {
953 total_sectors = (int64_t) cyls * heads * secs_per_cyl;
954 }
955
956 *out_total_sectors = total_sectors;
957 if (out_cyls) {
958 *out_cyls = cyls;
959 *out_heads = heads;
960 *out_secs_per_cyl = secs_per_cyl;
961 }
962
963 return 0;
964}
965
966static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
967 Error **errp)
968{
969 BlockdevCreateOptionsVpc *vpc_opts;
970 BlockBackend *blk = NULL;
971 BlockDriverState *bs = NULL;
972
973 uint8_t buf[1024];
974 VHDFooter *footer = (VHDFooter *) buf;
975 uint16_t cyls = 0;
976 uint8_t heads = 0;
977 uint8_t secs_per_cyl = 0;
978 int64_t total_sectors;
979 int64_t total_size;
980 int disk_type;
981 int ret = -EIO;
982
983 assert(opts->driver == BLOCKDEV_DRIVER_VPC);
984 vpc_opts = &opts->u.vpc;
985
986
987 total_size = vpc_opts->size;
988
989 if (!vpc_opts->has_subformat) {
990 vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC;
991 }
992 switch (vpc_opts->subformat) {
993 case BLOCKDEV_VPC_SUBFORMAT_DYNAMIC:
994 disk_type = VHD_DYNAMIC;
995 break;
996 case BLOCKDEV_VPC_SUBFORMAT_FIXED:
997 disk_type = VHD_FIXED;
998 break;
999 default:
1000 g_assert_not_reached();
1001 }
1002
1003
1004 bs = bdrv_open_blockdev_ref(vpc_opts->file, errp);
1005 if (bs == NULL) {
1006 return -EIO;
1007 }
1008
1009 blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
1010 ret = blk_insert_bs(blk, bs, errp);
1011 if (ret < 0) {
1012 goto out;
1013 }
1014 blk_set_allow_write_beyond_eof(blk, true);
1015
1016
1017 ret = calculate_rounded_image_size(vpc_opts, &cyls, &heads, &secs_per_cyl,
1018 &total_sectors, errp);
1019 if (ret < 0) {
1020 goto out;
1021 }
1022
1023 if (total_size != total_sectors * BDRV_SECTOR_SIZE) {
1024 error_setg(errp, "The requested image size cannot be represented in "
1025 "CHS geometry");
1026 error_append_hint(errp, "Try size=%llu or force-size=on (the "
1027 "latter makes the image incompatible with "
1028 "Virtual PC)",
1029 total_sectors * BDRV_SECTOR_SIZE);
1030 ret = -EINVAL;
1031 goto out;
1032 }
1033
1034
1035 memset(buf, 0, 1024);
1036
1037 memcpy(footer->creator, "conectix", 8);
1038 if (vpc_opts->force_size) {
1039 memcpy(footer->creator_app, "qem2", 4);
1040 } else {
1041 memcpy(footer->creator_app, "qemu", 4);
1042 }
1043 memcpy(footer->creator_os, "Wi2k", 4);
1044
1045 footer->features = cpu_to_be32(0x02);
1046 footer->version = cpu_to_be32(0x00010000);
1047 if (disk_type == VHD_DYNAMIC) {
1048 footer->data_offset = cpu_to_be64(HEADER_SIZE);
1049 } else {
1050 footer->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
1051 }
1052 footer->timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE);
1053
1054
1055 footer->major = cpu_to_be16(0x0005);
1056 footer->minor = cpu_to_be16(0x0003);
1057 footer->orig_size = cpu_to_be64(total_size);
1058 footer->current_size = cpu_to_be64(total_size);
1059 footer->cyls = cpu_to_be16(cyls);
1060 footer->heads = heads;
1061 footer->secs_per_cyl = secs_per_cyl;
1062
1063 footer->type = cpu_to_be32(disk_type);
1064
1065 qemu_uuid_generate(&footer->uuid);
1066
1067 footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));
1068
1069 if (disk_type == VHD_DYNAMIC) {
1070 ret = create_dynamic_disk(blk, buf, total_sectors);
1071 if (ret < 0) {
1072 error_setg(errp, "Unable to create or write VHD header");
1073 }
1074 } else {
1075 ret = create_fixed_disk(blk, buf, total_size, errp);
1076 }
1077
1078out:
1079 blk_unref(blk);
1080 bdrv_unref(bs);
1081 return ret;
1082}
1083
1084static int coroutine_fn vpc_co_create_opts(const char *filename,
1085 QemuOpts *opts, Error **errp)
1086{
1087 BlockdevCreateOptions *create_options = NULL;
1088 QDict *qdict;
1089 Visitor *v;
1090 BlockDriverState *bs = NULL;
1091 Error *local_err = NULL;
1092 int ret;
1093
1094 static const QDictRenames opt_renames[] = {
1095 { VPC_OPT_FORCE_SIZE, "force-size" },
1096 { NULL, NULL },
1097 };
1098
1099
1100 qdict = qemu_opts_to_qdict_filtered(opts, NULL, &vpc_create_opts, true);
1101
1102 if (!qdict_rename_keys(qdict, opt_renames, errp)) {
1103 ret = -EINVAL;
1104 goto fail;
1105 }
1106
1107
1108 ret = bdrv_create_file(filename, opts, &local_err);
1109 if (ret < 0) {
1110 error_propagate(errp, local_err);
1111 goto fail;
1112 }
1113
1114 bs = bdrv_open(filename, NULL, NULL,
1115 BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
1116 if (bs == NULL) {
1117 ret = -EIO;
1118 goto fail;
1119 }
1120
1121
1122 qdict_put_str(qdict, "driver", "vpc");
1123 qdict_put_str(qdict, "file", bs->node_name);
1124
1125 v = qobject_input_visitor_new_flat_confused(qdict, errp);
1126 if (!v) {
1127 ret = -EINVAL;
1128 goto fail;
1129 }
1130
1131 visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
1132 visit_free(v);
1133
1134 if (local_err) {
1135 error_propagate(errp, local_err);
1136 ret = -EINVAL;
1137 goto fail;
1138 }
1139
1140
1141 assert(create_options->driver == BLOCKDEV_DRIVER_VPC);
1142 create_options->u.vpc.size =
1143 ROUND_UP(create_options->u.vpc.size, BDRV_SECTOR_SIZE);
1144
1145 if (!create_options->u.vpc.force_size) {
1146 int64_t total_sectors;
1147 ret = calculate_rounded_image_size(&create_options->u.vpc, NULL, NULL,
1148 NULL, &total_sectors, errp);
1149 if (ret < 0) {
1150 goto fail;
1151 }
1152
1153 create_options->u.vpc.size = total_sectors * BDRV_SECTOR_SIZE;
1154 }
1155
1156
1157
1158 ret = vpc_co_create(create_options, errp);
1159
1160fail:
1161 qobject_unref(qdict);
1162 bdrv_unref(bs);
1163 qapi_free_BlockdevCreateOptions(create_options);
1164 return ret;
1165}
1166
1167
1168static int vpc_has_zero_init(BlockDriverState *bs)
1169{
1170 BDRVVPCState *s = bs->opaque;
1171 VHDFooter *footer = (VHDFooter *) s->footer_buf;
1172
1173 if (be32_to_cpu(footer->type) == VHD_FIXED) {
1174 return bdrv_has_zero_init(bs->file->bs);
1175 } else {
1176 return 1;
1177 }
1178}
1179
1180static void vpc_close(BlockDriverState *bs)
1181{
1182 BDRVVPCState *s = bs->opaque;
1183 qemu_vfree(s->pagetable);
1184#ifdef CACHE
1185 g_free(s->pageentry_u8);
1186#endif
1187
1188 migrate_del_blocker(s->migration_blocker);
1189 error_free(s->migration_blocker);
1190}
1191
1192static QemuOptsList vpc_create_opts = {
1193 .name = "vpc-create-opts",
1194 .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
1195 .desc = {
1196 {
1197 .name = BLOCK_OPT_SIZE,
1198 .type = QEMU_OPT_SIZE,
1199 .help = "Virtual disk size"
1200 },
1201 {
1202 .name = BLOCK_OPT_SUBFMT,
1203 .type = QEMU_OPT_STRING,
1204 .help =
1205 "Type of virtual hard disk format. Supported formats are "
1206 "{dynamic (default) | fixed} "
1207 },
1208 {
1209 .name = VPC_OPT_FORCE_SIZE,
1210 .type = QEMU_OPT_BOOL,
1211 .help = "Force disk size calculation to use the actual size "
1212 "specified, rather than using the nearest CHS-based "
1213 "calculation"
1214 },
1215 { }
1216 }
1217};
1218
1219static BlockDriver bdrv_vpc = {
1220 .format_name = "vpc",
1221 .instance_size = sizeof(BDRVVPCState),
1222
1223 .bdrv_probe = vpc_probe,
1224 .bdrv_open = vpc_open,
1225 .bdrv_close = vpc_close,
1226 .bdrv_reopen_prepare = vpc_reopen_prepare,
1227 .bdrv_child_perm = bdrv_format_default_perms,
1228 .bdrv_co_create = vpc_co_create,
1229 .bdrv_co_create_opts = vpc_co_create_opts,
1230
1231 .bdrv_co_preadv = vpc_co_preadv,
1232 .bdrv_co_pwritev = vpc_co_pwritev,
1233 .bdrv_co_block_status = vpc_co_block_status,
1234
1235 .bdrv_get_info = vpc_get_info,
1236
1237 .create_opts = &vpc_create_opts,
1238 .bdrv_has_zero_init = vpc_has_zero_init,
1239};
1240
1241static void bdrv_vpc_init(void)
1242{
1243 bdrv_register(&bdrv_vpc);
1244}
1245
1246block_init(bdrv_vpc_init);
1247