Lines Matching +full:- +full:chs

30 #include "sysemu/block-backend.h"
38 #include "qapi/qobject-input-visitor.h"
39 #include "qapi/qapi-visit-block-core.h"
63 /* always big-endian */
122 /* Backing file name (in UTF-16) */
164 .name = "vpc-runtime-opts",
170 .help = "Force disk size calculation to use either CHS geometry, "
172 "{chs, current_size}"
203 BDRVVPCState *s = bs->opaque; in vpc_parse_options()
211 s->force_use_sz = true; in vpc_parse_options()
212 } else if (!strcmp(size_calc, "chs")) { in vpc_parse_options()
213 s->force_use_chs = true; in vpc_parse_options()
222 BDRVVPCState *s = bs->opaque; in vpc_open()
245 ret = -EINVAL; in vpc_open()
252 ret = -EINVAL; in vpc_open()
256 ret = bdrv_pread(bs->file, 0, sizeof(s->footer), &s->footer, 0); in vpc_open()
262 footer = &s->footer; in vpc_open()
263 if (strncmp(footer->creator, "conectix", 8)) { in vpc_open()
264 int64_t offset = bdrv_getlength(bs->file->bs); in vpc_open()
270 ret = -EINVAL; in vpc_open()
276 ret = bdrv_pread(bs->file, offset - sizeof(*footer), sizeof(*footer), in vpc_open()
281 if (strncmp(footer->creator, "conectix", 8) || in vpc_open()
282 be32_to_cpu(footer->type) != VHD_FIXED) { in vpc_open()
284 ret = -EINVAL; in vpc_open()
290 checksum = be32_to_cpu(footer->checksum); in vpc_open()
291 footer->checksum = 0; in vpc_open()
294 ret = -EINVAL; in vpc_open()
299 footer->checksum = cpu_to_be32(checksum); in vpc_open()
304 bs->total_sectors = (int64_t) in vpc_open()
305 be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl; in vpc_open()
307 /* Microsoft Virtual PC and Microsoft Hyper-V produce and read in vpc_open()
308 * VHD image sizes differently. VPC will rely on CHS geometry, in vpc_open()
309 * while Hyper-V and disk2vhd use the size specified in the footer. in vpc_open()
312 * look at the Creator App field, and look for images that have CHS in vpc_open()
315 * If the CHS geometry is the maximum CHS geometry, then we assume that in vpc_open()
316 * the size is the footer->current_size to avoid truncation. Otherwise, in vpc_open()
317 * we follow the table based on footer->creator_app: in vpc_open()
320 * 'vpc ' : CHS Virtual PC (uses disk geometry) in vpc_open()
321 * 'qemu' : CHS QEMU (uses disk geometry) in vpc_open()
323 * 'win ' : current_size Hyper-V in vpc_open()
330 * that have CHS geometry of the maximum size. in vpc_open()
332 use_chs = (!!strncmp(footer->creator_app, "win ", 4) && in vpc_open()
333 !!strncmp(footer->creator_app, "qem2", 4) && in vpc_open()
334 !!strncmp(footer->creator_app, "d2v ", 4) && in vpc_open()
335 !!strncmp(footer->creator_app, "CTXS", 4) && in vpc_open()
336 !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs; in vpc_open()
338 if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) { in vpc_open()
339 bs->total_sectors = be64_to_cpu(footer->current_size) / in vpc_open()
344 if (bs->total_sectors > VHD_MAX_SECTORS) { in vpc_open()
345 ret = -EFBIG; in vpc_open()
350 ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), in vpc_open()
359 ret = -EINVAL; in vpc_open()
363 s->block_size = be32_to_cpu(dyndisk_header.block_size); in vpc_open()
364 if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) { in vpc_open()
365 error_setg(errp, "Invalid block size %" PRIu32, s->block_size); in vpc_open()
366 ret = -EINVAL; in vpc_open()
369 s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511; in vpc_open()
371 s->max_table_entries = be32_to_cpu(dyndisk_header.max_table_entries); in vpc_open()
373 if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) { in vpc_open()
375 ret = -EINVAL; in vpc_open()
379 computed_size = (uint64_t) s->max_table_entries * s->block_size; in vpc_open()
380 if (computed_size < bs->total_sectors * 512) { in vpc_open()
382 ret = -EINVAL; in vpc_open()
386 if (s->max_table_entries > SIZE_MAX / 4 || in vpc_open()
387 s->max_table_entries > (int) INT_MAX / 4) { in vpc_open()
389 s->max_table_entries); in vpc_open()
390 ret = -EINVAL; in vpc_open()
394 pagetable_size = (uint64_t) s->max_table_entries * 4; in vpc_open()
396 s->pagetable = qemu_try_blockalign(bs->file->bs, pagetable_size); in vpc_open()
397 if (s->pagetable == NULL) { in vpc_open()
399 ret = -ENOMEM; in vpc_open()
403 s->bat_offset = be64_to_cpu(dyndisk_header.table_offset); in vpc_open()
405 ret = bdrv_pread(bs->file, s->bat_offset, pagetable_size, in vpc_open()
406 s->pagetable, 0); in vpc_open()
412 s->free_data_block_offset = in vpc_open()
413 ROUND_UP(s->bat_offset + pagetable_size, 512); in vpc_open()
415 for (i = 0; i < s->max_table_entries; i++) { in vpc_open()
416 be32_to_cpus(&s->pagetable[i]); in vpc_open()
417 if (s->pagetable[i] != 0xFFFFFFFF) { in vpc_open()
418 int64_t next = (512 * (int64_t) s->pagetable[i]) + in vpc_open()
419 s->bitmap_size + s->block_size; in vpc_open()
421 if (next > s->free_data_block_offset) { in vpc_open()
422 s->free_data_block_offset = next; in vpc_open()
427 bs_size = bdrv_getlength(bs->file->bs); in vpc_open()
429 error_setg_errno(errp, -bs_size, "Unable to learn image size"); in vpc_open()
433 if (s->free_data_block_offset > bs_size) { in vpc_open()
434 error_setg(errp, "block-vpc: free_data_block_offset points after " in vpc_open()
436 ret = -EINVAL; in vpc_open()
440 s->last_bitmap_offset = (int64_t) -1; in vpc_open()
443 s->pageentry_u8 = g_malloc(512); in vpc_open()
444 s->pageentry_u32 = s->pageentry_u8; in vpc_open()
445 s->pageentry_u16 = s->pageentry_u8; in vpc_open()
446 s->last_pagetable = -1; in vpc_open()
451 error_setg(&s->migration_blocker, "The vpc format used by node '%s' " in vpc_open()
455 ret = migrate_add_blocker_normal(&s->migration_blocker, errp); in vpc_open()
460 qemu_co_mutex_init(&s->lock); in vpc_open()
467 qemu_vfree(s->pagetable); in vpc_open()
469 g_free(s->pageentry_u8); in vpc_open()
482 * If the sector is not allocated, -1 is returned instead.
484 * the file, -2 is returned, and the error value is written to *err.
494 BDRVVPCState *s = bs->opaque; in get_image_offset()
500 pagetable_index = offset / s->block_size; in get_image_offset()
501 offset_in_block = offset % s->block_size; in get_image_offset()
503 if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff) in get_image_offset()
504 return -1; /* not allocated */ in get_image_offset()
506 bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index]; in get_image_offset()
507 block_offset = bitmap_offset + s->bitmap_size + offset_in_block; in get_image_offset()
514 if (write && (s->last_bitmap_offset != bitmap_offset)) { in get_image_offset()
515 g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size); in get_image_offset()
518 s->last_bitmap_offset = bitmap_offset; in get_image_offset()
519 memset(bitmap, 0xff, s->bitmap_size); in get_image_offset()
520 r = bdrv_co_pwrite_sync(bs->file, bitmap_offset, s->bitmap_size, bitmap, 0); in get_image_offset()
523 return -2; in get_image_offset()
539 BDRVVPCState *s = bs->opaque; in rewrite_footer()
540 int64_t offset = s->free_data_block_offset; in rewrite_footer()
542 ret = bdrv_co_pwrite_sync(bs->file, offset, sizeof(s->footer), &s->footer, 0); in rewrite_footer()
559 BDRVVPCState *s = bs->opaque; in alloc_block()
563 g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size); in alloc_block()
566 if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) { in alloc_block()
567 return -EINVAL; in alloc_block()
570 /* Write entry into in-memory BAT */ in alloc_block()
571 index = offset / s->block_size; in alloc_block()
572 assert(s->pagetable[index] == 0xFFFFFFFF); in alloc_block()
573 s->pagetable[index] = s->free_data_block_offset / 512; in alloc_block()
576 memset(bitmap, 0xff, s->bitmap_size); in alloc_block()
577 ret = bdrv_co_pwrite_sync(bs->file, s->free_data_block_offset, in alloc_block()
578 s->bitmap_size, bitmap, 0); in alloc_block()
584 s->free_data_block_offset += s->block_size + s->bitmap_size; in alloc_block()
590 bat_offset = s->bat_offset + (4 * index); in alloc_block()
591 bat_value = cpu_to_be32(s->pagetable[index]); in alloc_block()
592 ret = bdrv_co_pwrite_sync(bs->file, bat_offset, 4, &bat_value, 0); in alloc_block()
599 s->free_data_block_offset -= (s->block_size + s->bitmap_size); in alloc_block()
606 BDRVVPCState *s = (BDRVVPCState *)bs->opaque; in vpc_co_get_info()
608 if (be32_to_cpu(s->footer.type) != VHD_FIXED) { in vpc_co_get_info()
609 bdi->cluster_size = s->block_size; in vpc_co_get_info()
619 BDRVVPCState *s = bs->opaque; in vpc_co_preadv()
626 if (be32_to_cpu(s->footer.type) == VHD_FIXED) { in vpc_co_preadv()
627 return bdrv_co_preadv(bs->file, offset, bytes, qiov, 0); in vpc_co_preadv()
630 qemu_co_mutex_lock(&s->lock); in vpc_co_preadv()
631 qemu_iovec_init(&local_qiov, qiov->niov); in vpc_co_preadv()
635 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); in vpc_co_preadv()
637 if (image_offset == -1) { in vpc_co_preadv()
643 qemu_co_mutex_unlock(&s->lock); in vpc_co_preadv()
644 ret = bdrv_co_preadv(bs->file, image_offset, n_bytes, in vpc_co_preadv()
646 qemu_co_mutex_lock(&s->lock); in vpc_co_preadv()
652 bytes -= n_bytes; in vpc_co_preadv()
660 qemu_co_mutex_unlock(&s->lock); in vpc_co_preadv()
669 BDRVVPCState *s = bs->opaque; in vpc_co_pwritev()
676 if (be32_to_cpu(s->footer.type) == VHD_FIXED) { in vpc_co_pwritev()
677 return bdrv_co_pwritev(bs->file, offset, bytes, qiov, 0); in vpc_co_pwritev()
680 qemu_co_mutex_lock(&s->lock); in vpc_co_pwritev()
681 qemu_iovec_init(&local_qiov, qiov->niov); in vpc_co_pwritev()
685 if (image_offset == -2) { in vpc_co_pwritev()
689 n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); in vpc_co_pwritev()
691 if (image_offset == -1) { in vpc_co_pwritev()
702 qemu_co_mutex_unlock(&s->lock); in vpc_co_pwritev()
703 ret = bdrv_co_pwritev(bs->file, image_offset, n_bytes, in vpc_co_pwritev()
705 qemu_co_mutex_lock(&s->lock); in vpc_co_pwritev()
710 bytes -= n_bytes; in vpc_co_pwritev()
718 qemu_co_mutex_unlock(&s->lock); in vpc_co_pwritev()
729 BDRVVPCState *s = bs->opaque; in vpc_co_block_status()
735 if (be32_to_cpu(s->footer.type) == VHD_FIXED) { in vpc_co_block_status()
738 *file = bs->file->bs; in vpc_co_block_status()
742 qemu_co_mutex_lock(&s->lock); in vpc_co_block_status()
745 allocated = (image_offset != -1); in vpc_co_block_status()
751 n = ROUND_UP(offset + 1, s->block_size) - offset; in vpc_co_block_status()
756 bytes -= n; in vpc_co_block_status()
760 *file = bs->file->bs; in vpc_co_block_status()
769 } while (image_offset == -1); in vpc_co_block_status()
771 qemu_co_mutex_unlock(&s->lock); in vpc_co_block_status()
783 * Returns 0 on success, -EFBIG if the size is larger than 2040 GiB. Override
784 * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB)
906 ret = blk_co_pwrite(blk, total_size - sizeof(*footer), sizeof(*footer), in create_fixed_disk()
909 error_setg_errno(errp, -ret, "Unable to write VHD header"); in create_fixed_disk()
923 int64_t total_size = vpc_opts->size; in calculate_rounded_image_size()
933 * qemu-img convert doesn't truncate images, but rather rounds up. in calculate_rounded_image_size()
935 * If the image size can't be represented by a spec conformant CHS geometry, in calculate_rounded_image_size()
939 if (vpc_opts->force_size) { in calculate_rounded_image_size()
956 return -EFBIG; in calculate_rounded_image_size()
986 int ret = -EIO; in vpc_co_create()
989 assert(opts->driver == BLOCKDEV_DRIVER_VPC); in vpc_co_create()
990 vpc_opts = &opts->u.vpc; in vpc_co_create()
993 total_size = vpc_opts->size; in vpc_co_create()
995 if (!vpc_opts->has_subformat) { in vpc_co_create()
996 vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC; in vpc_co_create()
998 switch (vpc_opts->subformat) { in vpc_co_create()
1010 bs = bdrv_co_open_blockdev_ref(vpc_opts->file, errp); in vpc_co_create()
1012 return -EIO; in vpc_co_create()
1018 ret = -EPERM; in vpc_co_create()
1032 "CHS geometry"); in vpc_co_create()
1033 error_append_hint(errp, "Try size=%llu or force-size=on (the " in vpc_co_create()
1037 ret = -EINVAL; in vpc_co_create()
1045 if (vpc_opts->force_size) { in vpc_co_create()
1059 footer.timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE); in vpc_co_create()
1103 { VPC_OPT_FORCE_SIZE, "force-size" }, in vpc_co_create_opts()
1111 ret = -EINVAL; in vpc_co_create_opts()
1124 ret = -EIO; in vpc_co_create_opts()
1130 qdict_put_str(qdict, "file", bs->node_name); in vpc_co_create_opts()
1134 ret = -EINVAL; in vpc_co_create_opts()
1141 ret = -EINVAL; in vpc_co_create_opts()
1146 assert(create_options->driver == BLOCKDEV_DRIVER_VPC); in vpc_co_create_opts()
1147 create_options->u.vpc.size = in vpc_co_create_opts()
1148 ROUND_UP(create_options->u.vpc.size, BDRV_SECTOR_SIZE); in vpc_co_create_opts()
1150 if (!create_options->u.vpc.force_size) { in vpc_co_create_opts()
1152 ret = calculate_rounded_image_size(&create_options->u.vpc, NULL, NULL, in vpc_co_create_opts()
1158 create_options->u.vpc.size = total_sectors * BDRV_SECTOR_SIZE; in vpc_co_create_opts()
1175 BDRVVPCState *s = bs->opaque; in vpc_has_zero_init()
1177 if (be32_to_cpu(s->footer.type) == VHD_FIXED) { in vpc_has_zero_init()
1178 return bdrv_has_zero_init(bs->file->bs); in vpc_has_zero_init()
1186 BDRVVPCState *s = bs->opaque; in vpc_close()
1187 qemu_vfree(s->pagetable); in vpc_close()
1189 g_free(s->pageentry_u8); in vpc_close()
1192 migrate_del_blocker(&s->migration_blocker); in vpc_close()
1196 .name = "vpc-create-opts",
1215 "specified, rather than using the nearest CHS-based "