Lines Matching +full:- +full:- +full:disable +full:- +full:live +full:- +full:block +full:- +full:migration

2  * Block driver for the VMDK format
28 #include "block/block_int.h"
29 #include "system/block-backend.h"
31 #include "qemu/error-report.h"
36 #include "migration/blocker.h"
45 /* Zeroed-grain enable bit */
57 #define VMDK_ERROR (-1)
59 #define VMDK_UNALLOC (-2)
60 #define VMDK_ZEROED (-3)
243 if (end - p >= strlen("version=X\n")) { in vmdk_probe()
250 if (end - p >= strlen("version=X\r\n")) { in vmdk_probe()
271 BDRVVmdkState *s = bs->opaque; in vmdk_free_extents()
276 for (i = 0; i < s->num_extents; i++) { in vmdk_free_extents()
277 e = &s->extents[i]; in vmdk_free_extents()
278 g_free(e->l1_table); in vmdk_free_extents()
279 g_free(e->l2_cache); in vmdk_free_extents()
280 g_free(e->l1_backup_table); in vmdk_free_extents()
281 g_free(e->type); in vmdk_free_extents()
282 if (e->file != bs->file) { in vmdk_free_extents()
283 bdrv_unref_child(bs, e->file); in vmdk_free_extents()
289 g_free(s->extents); in vmdk_free_extents()
294 BDRVVmdkState *s = bs->opaque; in vmdk_free_last_extent()
296 if (s->num_extents == 0) { in vmdk_free_last_extent()
299 s->num_extents--; in vmdk_free_last_extent()
300 s->extents = g_renew(VmdkExtent, s->extents, s->num_extents); in vmdk_free_last_extent()
303 /* Return -ve errno, or 0 on success and write CID into *pcid. */
311 BDRVVmdkState *s = bs->opaque; in vmdk_read_cid()
315 ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); in vmdk_read_cid()
328 desc[DESC_SIZE - 1] = '\0'; in vmdk_read_cid()
331 ret = -EINVAL; in vmdk_read_cid()
336 ret = -EINVAL; in vmdk_read_cid()
352 BDRVVmdkState *s = bs->opaque; in vmdk_write_cid()
357 if (s->desc_offset == 0) { in vmdk_write_cid()
358 desc_buf_size = bdrv_getlength(bs->file->bs); in vmdk_write_cid()
361 return -EFBIG; in vmdk_write_cid()
369 ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0); in vmdk_write_cid()
374 desc[desc_buf_size - 1] = '\0'; in vmdk_write_cid()
377 ret = -EINVAL; in vmdk_write_cid()
385 snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid); in vmdk_write_cid()
389 ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0); in vmdk_write_cid()
399 BDRVVmdkState *s = bs->opaque; in vmdk_is_cid_valid()
402 if (!s->cid_checked && bs->backing) { in vmdk_is_cid_valid()
403 BlockDriverState *p_bs = bs->backing->bs; in vmdk_is_cid_valid()
405 if (strcmp(p_bs->drv->format_name, "vmdk")) { in vmdk_is_cid_valid()
415 if (s->parent_cid != cur_pcid) { in vmdk_is_cid_valid()
420 s->cid_checked = true; in vmdk_is_cid_valid()
436 assert(state->bs != NULL); in vmdk_reopen_prepare()
437 assert(state->opaque == NULL); in vmdk_reopen_prepare()
439 s = state->bs->opaque; in vmdk_reopen_prepare()
442 state->opaque = rs; in vmdk_reopen_prepare()
445 * Check whether there are any extents stored in bs->file; if bs->file in vmdk_reopen_prepare()
448 rs->extents_using_bs_file = g_new(bool, s->num_extents); in vmdk_reopen_prepare()
449 for (i = 0; i < s->num_extents; i++) { in vmdk_reopen_prepare()
450 rs->extents_using_bs_file[i] = s->extents[i].file == state->bs->file; in vmdk_reopen_prepare()
458 BDRVVmdkReopenState *rs = state->opaque; in vmdk_reopen_clean()
460 g_free(rs->extents_using_bs_file); in vmdk_reopen_clean()
462 state->opaque = NULL; in vmdk_reopen_clean()
467 BDRVVmdkState *s = state->bs->opaque; in vmdk_reopen_commit()
468 BDRVVmdkReopenState *rs = state->opaque; in vmdk_reopen_commit()
474 for (i = 0; i < s->num_extents; i++) { in vmdk_reopen_commit()
475 if (rs->extents_using_bs_file[i]) { in vmdk_reopen_commit()
476 s->extents[i].file = state->bs->file; in vmdk_reopen_commit()
492 BDRVVmdkState *s = bs->opaque; in vmdk_parent_open()
496 ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); in vmdk_parent_open()
508 ret = -EINVAL; in vmdk_parent_open()
511 if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) { in vmdk_parent_open()
512 ret = -EINVAL; in vmdk_parent_open()
516 pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name); in vmdk_parent_open()
517 pstrcpy(bs->backing_file, sizeof(bs->backing_file), in vmdk_parent_open()
518 bs->auto_backing_file); in vmdk_parent_open()
519 pstrcpy(bs->backing_format, sizeof(bs->backing_format), in vmdk_parent_open()
539 BDRVVmdkState *s = bs->opaque; in vmdk_add_extent()
545 return -EFBIG; in vmdk_add_extent()
552 * 8TB - for both VMDK3 & VMDK4 with in vmdk_add_extent()
557 * 64TB - for "ESXi seSparse Extent" in vmdk_add_extent()
564 return -EFBIG; in vmdk_add_extent()
567 nb_sectors = bdrv_nb_sectors(file->bs); in vmdk_add_extent()
572 s->extents = g_renew(VmdkExtent, s->extents, s->num_extents + 1); in vmdk_add_extent()
573 extent = &s->extents[s->num_extents]; in vmdk_add_extent()
574 s->num_extents++; in vmdk_add_extent()
577 extent->file = file; in vmdk_add_extent()
578 extent->flat = flat; in vmdk_add_extent()
579 extent->sectors = sectors; in vmdk_add_extent()
580 extent->l1_table_offset = l1_offset; in vmdk_add_extent()
581 extent->l1_backup_table_offset = l1_backup_offset; in vmdk_add_extent()
582 extent->l1_size = l1_size; in vmdk_add_extent()
583 extent->l1_entry_sectors = l2_size * cluster_sectors; in vmdk_add_extent()
584 extent->l2_size = l2_size; in vmdk_add_extent()
585 extent->cluster_sectors = flat ? sectors : cluster_sectors; in vmdk_add_extent()
586 extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors); in vmdk_add_extent()
587 extent->entry_size = sizeof(uint32_t); in vmdk_add_extent()
589 if (s->num_extents > 1) { in vmdk_add_extent()
590 extent->end_sector = (*(extent - 1)).end_sector + extent->sectors; in vmdk_add_extent()
592 extent->end_sector = extent->sectors; in vmdk_add_extent()
594 bs->total_sectors = extent->end_sector; in vmdk_add_extent()
609 l1_size = extent->l1_size * extent->entry_size; in vmdk_init_tables()
610 extent->l1_table = g_try_malloc(l1_size); in vmdk_init_tables()
611 if (l1_size && extent->l1_table == NULL) { in vmdk_init_tables()
612 return -ENOMEM; in vmdk_init_tables()
615 ret = bdrv_pread(extent->file, extent->l1_table_offset, l1_size, in vmdk_init_tables()
616 extent->l1_table, 0); in vmdk_init_tables()
618 bdrv_refresh_filename(extent->file->bs); in vmdk_init_tables()
619 error_setg_errno(errp, -ret, in vmdk_init_tables()
621 extent->file->bs->filename); in vmdk_init_tables()
624 for (i = 0; i < extent->l1_size; i++) { in vmdk_init_tables()
625 if (extent->entry_size == sizeof(uint64_t)) { in vmdk_init_tables()
626 le64_to_cpus((uint64_t *)extent->l1_table + i); in vmdk_init_tables()
628 assert(extent->entry_size == sizeof(uint32_t)); in vmdk_init_tables()
629 le32_to_cpus((uint32_t *)extent->l1_table + i); in vmdk_init_tables()
633 if (extent->l1_backup_table_offset) { in vmdk_init_tables()
634 assert(!extent->sesparse); in vmdk_init_tables()
635 extent->l1_backup_table = g_try_malloc(l1_size); in vmdk_init_tables()
636 if (l1_size && extent->l1_backup_table == NULL) { in vmdk_init_tables()
637 ret = -ENOMEM; in vmdk_init_tables()
640 ret = bdrv_pread(extent->file, extent->l1_backup_table_offset, in vmdk_init_tables()
641 l1_size, extent->l1_backup_table, 0); in vmdk_init_tables()
643 bdrv_refresh_filename(extent->file->bs); in vmdk_init_tables()
644 error_setg_errno(errp, -ret, in vmdk_init_tables()
646 extent->file->bs->filename); in vmdk_init_tables()
649 for (i = 0; i < extent->l1_size; i++) { in vmdk_init_tables()
650 le32_to_cpus(&extent->l1_backup_table[i]); in vmdk_init_tables()
654 extent->l2_cache = in vmdk_init_tables()
655 g_malloc(extent->entry_size * extent->l2_size * L2_CACHE_SIZE); in vmdk_init_tables()
658 g_free(extent->l1_backup_table); in vmdk_init_tables()
660 g_free(extent->l1_table); in vmdk_init_tables()
675 bdrv_refresh_filename(file->bs); in vmdk_open_vmfs_sparse()
676 error_setg_errno(errp, -ret, in vmdk_open_vmfs_sparse()
678 file->bs->filename); in vmdk_open_vmfs_sparse()
704 /* Strict checks - format not officially documented */
708 header->magic = le64_to_cpu(header->magic); in check_se_sparse_const_header()
709 header->version = le64_to_cpu(header->version); in check_se_sparse_const_header()
710 header->grain_size = le64_to_cpu(header->grain_size); in check_se_sparse_const_header()
711 header->grain_table_size = le64_to_cpu(header->grain_table_size); in check_se_sparse_const_header()
712 header->flags = le64_to_cpu(header->flags); in check_se_sparse_const_header()
713 header->reserved1 = le64_to_cpu(header->reserved1); in check_se_sparse_const_header()
714 header->reserved2 = le64_to_cpu(header->reserved2); in check_se_sparse_const_header()
715 header->reserved3 = le64_to_cpu(header->reserved3); in check_se_sparse_const_header()
716 header->reserved4 = le64_to_cpu(header->reserved4); in check_se_sparse_const_header()
718 header->volatile_header_offset = in check_se_sparse_const_header()
719 le64_to_cpu(header->volatile_header_offset); in check_se_sparse_const_header()
720 header->volatile_header_size = le64_to_cpu(header->volatile_header_size); in check_se_sparse_const_header()
722 header->journal_header_offset = le64_to_cpu(header->journal_header_offset); in check_se_sparse_const_header()
723 header->journal_header_size = le64_to_cpu(header->journal_header_size); in check_se_sparse_const_header()
725 header->journal_offset = le64_to_cpu(header->journal_offset); in check_se_sparse_const_header()
726 header->journal_size = le64_to_cpu(header->journal_size); in check_se_sparse_const_header()
728 header->grain_dir_offset = le64_to_cpu(header->grain_dir_offset); in check_se_sparse_const_header()
729 header->grain_dir_size = le64_to_cpu(header->grain_dir_size); in check_se_sparse_const_header()
731 header->grain_tables_offset = le64_to_cpu(header->grain_tables_offset); in check_se_sparse_const_header()
732 header->grain_tables_size = le64_to_cpu(header->grain_tables_size); in check_se_sparse_const_header()
734 header->free_bitmap_offset = le64_to_cpu(header->free_bitmap_offset); in check_se_sparse_const_header()
735 header->free_bitmap_size = le64_to_cpu(header->free_bitmap_size); in check_se_sparse_const_header()
737 header->backmap_offset = le64_to_cpu(header->backmap_offset); in check_se_sparse_const_header()
738 header->backmap_size = le64_to_cpu(header->backmap_size); in check_se_sparse_const_header()
740 header->grains_offset = le64_to_cpu(header->grains_offset); in check_se_sparse_const_header()
741 header->grains_size = le64_to_cpu(header->grains_size); in check_se_sparse_const_header()
743 if (header->magic != SESPARSE_CONST_HEADER_MAGIC) { in check_se_sparse_const_header()
745 header->magic); in check_se_sparse_const_header()
746 return -EINVAL; in check_se_sparse_const_header()
749 if (header->version != 0x0000000200000001) { in check_se_sparse_const_header()
751 header->version); in check_se_sparse_const_header()
752 return -ENOTSUP; in check_se_sparse_const_header()
755 if (header->grain_size != 8) { in check_se_sparse_const_header()
757 header->grain_size); in check_se_sparse_const_header()
758 return -ENOTSUP; in check_se_sparse_const_header()
761 if (header->grain_table_size != 64) { in check_se_sparse_const_header()
763 header->grain_table_size); in check_se_sparse_const_header()
764 return -ENOTSUP; in check_se_sparse_const_header()
767 if (header->flags != 0) { in check_se_sparse_const_header()
769 header->flags); in check_se_sparse_const_header()
770 return -ENOTSUP; in check_se_sparse_const_header()
773 if (header->reserved1 != 0 || header->reserved2 != 0 || in check_se_sparse_const_header()
774 header->reserved3 != 0 || header->reserved4 != 0) { in check_se_sparse_const_header()
778 header->reserved1, header->reserved2, in check_se_sparse_const_header()
779 header->reserved3, header->reserved4); in check_se_sparse_const_header()
780 return -ENOTSUP; in check_se_sparse_const_header()
784 if (!buffer_is_zero(header->pad, sizeof(header->pad))) { in check_se_sparse_const_header()
785 error_setg(errp, "Unsupported non-zero const header padding"); in check_se_sparse_const_header()
786 return -ENOTSUP; in check_se_sparse_const_header()
795 header->magic = le64_to_cpu(header->magic); in check_se_sparse_volatile_header()
796 header->free_gt_number = le64_to_cpu(header->free_gt_number); in check_se_sparse_volatile_header()
797 header->next_txn_seq_number = le64_to_cpu(header->next_txn_seq_number); in check_se_sparse_volatile_header()
798 header->replay_journal = le64_to_cpu(header->replay_journal); in check_se_sparse_volatile_header()
800 if (header->magic != SESPARSE_VOLATILE_HEADER_MAGIC) { in check_se_sparse_volatile_header()
802 header->magic); in check_se_sparse_volatile_header()
803 return -EINVAL; in check_se_sparse_volatile_header()
806 if (header->replay_journal) { in check_se_sparse_volatile_header()
808 return -ENOTSUP; in check_se_sparse_volatile_header()
812 if (!buffer_is_zero(header->pad, sizeof(header->pad))) { in check_se_sparse_volatile_header()
813 error_setg(errp, "Unsupported non-zero volatile header padding"); in check_se_sparse_volatile_header()
814 return -ENOTSUP; in check_se_sparse_volatile_header()
839 bdrv_refresh_filename(file->bs); in vmdk_open_se_sparse()
840 error_setg_errno(errp, -ret, in vmdk_open_se_sparse()
842 file->bs->filename); in vmdk_open_se_sparse()
857 bdrv_refresh_filename(file->bs); in vmdk_open_se_sparse()
858 error_setg_errno(errp, -ret, in vmdk_open_se_sparse()
860 file->bs->filename); in vmdk_open_se_sparse()
885 extent->sesparse = true; in vmdk_open_se_sparse()
886 extent->sesparse_l2_tables_offset = const_header.grain_tables_offset; in vmdk_open_se_sparse()
887 extent->sesparse_clusters_offset = const_header.grains_offset; in vmdk_open_se_sparse()
888 extent->entry_size = sizeof(uint64_t); in vmdk_open_se_sparse()
908 size = bdrv_getlength(file->bs); in vmdk_read_desc()
910 error_setg_errno(errp, -size, "Could not access file"); in vmdk_read_desc()
922 size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */ in vmdk_read_desc()
927 error_setg_errno(errp, -ret, "Could not read from file"); in vmdk_read_desc()
945 BDRVVmdkState *s = bs->opaque; in vmdk_open_vmdk4()
951 bdrv_refresh_filename(file->bs); in vmdk_open_vmdk4()
952 error_setg_errno(errp, -ret, in vmdk_open_vmdk4()
954 file->bs->filename); in vmdk_open_vmdk4()
955 return -EINVAL; in vmdk_open_vmdk4()
962 return -EINVAL; in vmdk_open_vmdk4()
970 if (!s->create_type) { in vmdk_open_vmdk4()
971 s->create_type = g_strdup("monolithicSparse"); in vmdk_open_vmdk4()
977 * footer starts at offset -1024 from the end: One sector for the in vmdk_open_vmdk4()
978 * footer, and another one for the end-of-stream marker. in vmdk_open_vmdk4()
985 uint8_t pad[512 - 16]; in vmdk_open_vmdk4()
990 uint8_t pad[512 - 4 - sizeof(VMDK4Header)]; in vmdk_open_vmdk4()
996 uint8_t pad[512 - 16]; in vmdk_open_vmdk4()
1000 ret = bdrv_pread(file, bs->file->bs->total_sectors * 512 - 1536, in vmdk_open_vmdk4()
1003 error_setg_errno(errp, -ret, "Failed to read footer"); in vmdk_open_vmdk4()
1016 return -EINVAL; in vmdk_open_vmdk4()
1027 return -ENOTSUP; in vmdk_open_vmdk4()
1031 * persistent changed block tracking (CBT), and backup software can in vmdk_open_vmdk4()
1035 return -EINVAL; in vmdk_open_vmdk4()
1040 return -EINVAL; in vmdk_open_vmdk4()
1047 return -EINVAL; in vmdk_open_vmdk4()
1049 l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) in vmdk_open_vmdk4()
1054 if (bdrv_nb_sectors(file->bs) < le64_to_cpu(header.grain_offset)) { in vmdk_open_vmdk4()
1058 return -EINVAL; in vmdk_open_vmdk4()
1073 extent->compressed = in vmdk_open_vmdk4()
1075 if (extent->compressed) { in vmdk_open_vmdk4()
1076 g_free(s->create_type); in vmdk_open_vmdk4()
1077 s->create_type = g_strdup("streamOptimized"); in vmdk_open_vmdk4()
1079 extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER; in vmdk_open_vmdk4()
1080 extent->version = le32_to_cpu(header.version); in vmdk_open_vmdk4()
1081 extent->has_zero_grain = le32_to_cpu(header.flags) & VMDK4_FLAG_ZERO_GRAIN; in vmdk_open_vmdk4()
1110 if (opt_end == end || buf_size < opt_end - opt_pos + 1) { in vmdk_parse_description()
1113 pstrcpy(buf, opt_end - opt_pos + 1, opt_pos); in vmdk_parse_description()
1132 return -EINVAL; in vmdk_open_sparse()
1164 BDRVVmdkState *s = bs->opaque; in vmdk_parse_extents()
1174 * RW [size in sectors] FLAT "file-name.vmdk" OFFSET in vmdk_parse_extents()
1175 * RW [size in sectors] SPARSE "file-name.vmdk" in vmdk_parse_extents()
1176 * RW [size in sectors] VMFS "file-name.vmdk" in vmdk_parse_extents()
1177 * RW [size in sectors] VMFSSPARSE "file-name.vmdk" in vmdk_parse_extents()
1178 * RW [size in sectors] SESPARSE "file-name.vmdk" in vmdk_parse_extents()
1180 flat_offset = -1; in vmdk_parse_extents()
1211 desc_file_dir = bdrv_dirname(bs->file->bs, errp); in vmdk_parse_extents()
1213 bdrv_refresh_filename(bs->file->bs); in vmdk_parse_extents()
1216 bs->file->bs->filename); in vmdk_parse_extents()
1217 ret = -EINVAL; in vmdk_parse_extents()
1225 ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents); in vmdk_parse_extents()
1230 /* non-flat extents have metadata */ in vmdk_parse_extents()
1240 ret = -EINVAL; in vmdk_parse_extents()
1260 extent->flat_start_offset = flat_offset << 9; in vmdk_parse_extents()
1265 ret = -EINVAL; in vmdk_parse_extents()
1267 ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf, in vmdk_parse_extents()
1281 extent = &s->extents[s->num_extents - 1]; in vmdk_parse_extents()
1283 ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp); in vmdk_parse_extents()
1294 extent = &s->extents[s->num_extents - 1]; in vmdk_parse_extents()
1304 ret = -ENOTSUP; in vmdk_parse_extents()
1307 extent->type = g_strdup(type); in vmdk_parse_extents()
1316 if (np[-1] == '\n') { in vmdk_parse_extents()
1317 np--; in vmdk_parse_extents()
1319 error_setg(errp, "Invalid extent line: %.*s", (int)(np - p), p); in vmdk_parse_extents()
1320 ret = -EINVAL; in vmdk_parse_extents()
1333 BDRVVmdkState *s = bs->opaque; in vmdk_open_desc_file()
1337 ret = -EINVAL; in vmdk_open_desc_file()
1347 ret = -ENOTSUP; in vmdk_open_desc_file()
1350 s->create_type = g_strdup(ct); in vmdk_open_desc_file()
1351 s->desc_offset = 0; in vmdk_open_desc_file()
1362 BDRVVmdkState *s = bs->opaque; in vmdk_open()
1372 buf = vmdk_read_desc(bs->file, 0, errp); in vmdk_open()
1374 return -EINVAL; in vmdk_open()
1381 ret = vmdk_open_sparse(bs, bs->file, flags, buf, options, in vmdk_open()
1383 s->desc_offset = 0x200; in vmdk_open()
1387 bs->file->role &= ~BDRV_CHILD_DATA; in vmdk_open()
1390 bdrv_child_refresh_perms(bs, bs->file, &error_abort); in vmdk_open()
1404 ret = vmdk_read_cid(bs, 0, &s->cid); in vmdk_open()
1408 ret = vmdk_read_cid(bs, 1, &s->parent_cid); in vmdk_open()
1412 qemu_co_mutex_init(&s->lock); in vmdk_open()
1414 /* Disable migration when VMDK images are used */ in vmdk_open()
1415 error_setg(&s->migration_blocker, "The vmdk format used by node '%s' " in vmdk_open()
1416 "does not support live migration", in vmdk_open()
1418 ret = migrate_add_blocker_normal(&s->migration_blocker, errp); in vmdk_open()
1428 g_free(s->create_type); in vmdk_open()
1429 s->create_type = NULL; in vmdk_open()
1437 BDRVVmdkState *s = bs->opaque; in vmdk_refresh_limits()
1440 for (i = 0; i < s->num_extents; i++) { in vmdk_refresh_limits()
1441 if (!s->extents[i].flat) { in vmdk_refresh_limits()
1442 bs->bl.pwrite_zeroes_alignment = in vmdk_refresh_limits()
1443 MAX(bs->bl.pwrite_zeroes_alignment, in vmdk_refresh_limits()
1444 s->extents[i].cluster_sectors << BDRV_SECTOR_BITS); in vmdk_refresh_limits()
1473 cluster_bytes = extent->cluster_sectors << BDRV_SECTOR_BITS; in get_whole_cluster()
1476 copy_from_backing = bs->backing && !zeroed; in get_whole_cluster()
1480 memset(whole_grain + skip_end_bytes, 0, cluster_bytes - skip_end_bytes); in get_whole_cluster()
1484 /* we will be here if it's first write on non-exist grain(cluster). in get_whole_cluster()
1486 if (bs->backing && !vmdk_is_cid_valid(bs)) { in get_whole_cluster()
1494 /* qcow2 emits this on bs->file instead of bs->backing */ in get_whole_cluster()
1495 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); in get_whole_cluster()
1496 ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes, in get_whole_cluster()
1503 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); in get_whole_cluster()
1504 ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes, in get_whole_cluster()
1514 /* qcow2 emits this on bs->file instead of bs->backing */ in get_whole_cluster()
1515 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); in get_whole_cluster()
1516 ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes, in get_whole_cluster()
1517 cluster_bytes - skip_end_bytes, in get_whole_cluster()
1524 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); in get_whole_cluster()
1525 ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes, in get_whole_cluster()
1526 cluster_bytes - skip_end_bytes, in get_whole_cluster()
1545 BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_UPDATE); in vmdk_L2update()
1546 if (bdrv_co_pwrite(extent->file, in vmdk_L2update()
1547 ((int64_t)m_data->l2_offset * 512) in vmdk_L2update()
1548 + (m_data->l2_index * sizeof(offset)), in vmdk_L2update()
1553 if (extent->l1_backup_table_offset != 0) { in vmdk_L2update()
1554 m_data->l2_offset = extent->l1_backup_table[m_data->l1_index]; in vmdk_L2update()
1555 if (bdrv_co_pwrite(extent->file, in vmdk_L2update()
1556 ((int64_t)m_data->l2_offset * 512) in vmdk_L2update()
1557 + (m_data->l2_index * sizeof(offset)), in vmdk_L2update()
1562 if (bdrv_co_flush(extent->file->bs) < 0) { in vmdk_L2update()
1565 if (m_data->l2_cache_entry) { in vmdk_L2update()
1566 *m_data->l2_cache_entry = offset; in vmdk_L2update()
1605 unsigned int l2_size_bytes = extent->l2_size * extent->entry_size; in get_cluster_offset()
1608 m_data->new_allocation = false; in get_cluster_offset()
1610 if (extent->flat) { in get_cluster_offset()
1611 *cluster_offset = extent->flat_start_offset; in get_cluster_offset()
1615 offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE; in get_cluster_offset()
1616 l1_index = (offset >> 9) / extent->l1_entry_sectors; in get_cluster_offset()
1617 if (l1_index >= extent->l1_size) { in get_cluster_offset()
1620 if (extent->sesparse) { in get_cluster_offset()
1623 assert(extent->entry_size == sizeof(uint64_t)); in get_cluster_offset()
1625 l2_offset_u64 = ((uint64_t *)extent->l1_table)[l1_index]; in get_cluster_offset()
1631 * strict check - top most 4 bytes must be 0x10000000 since max in get_cluster_offset()
1632 * supported size is 64TB for disk - so no more than 64TB / 16MB in get_cluster_offset()
1639 l2_offset_u64 = extent->sesparse_l2_tables_offset + in get_cluster_offset()
1647 assert(extent->entry_size == sizeof(uint32_t)); in get_cluster_offset()
1648 l2_offset = ((uint32_t *)extent->l1_table)[l1_index]; in get_cluster_offset()
1654 if (l2_offset == extent->l2_cache_offsets[i]) { in get_cluster_offset()
1656 if (++extent->l2_cache_counts[i] == 0xffffffff) { in get_cluster_offset()
1658 extent->l2_cache_counts[j] >>= 1; in get_cluster_offset()
1661 l2_table = (char *)extent->l2_cache + (i * l2_size_bytes); in get_cluster_offset()
1669 if (extent->l2_cache_counts[i] < min_count) { in get_cluster_offset()
1670 min_count = extent->l2_cache_counts[i]; in get_cluster_offset()
1674 l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes); in get_cluster_offset()
1675 BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_LOAD); in get_cluster_offset()
1676 if (bdrv_co_pread(extent->file, in get_cluster_offset()
1684 extent->l2_cache_offsets[min_index] = l2_offset; in get_cluster_offset()
1685 extent->l2_cache_counts[min_index] = 1; in get_cluster_offset()
1687 l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size; in get_cluster_offset()
1689 m_data->l1_index = l1_index; in get_cluster_offset()
1690 m_data->l2_index = l2_index; in get_cluster_offset()
1691 m_data->l2_offset = l2_offset; in get_cluster_offset()
1692 m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index; in get_cluster_offset()
1695 if (extent->sesparse) { in get_cluster_offset()
1705 /* scsi-unmapped grain - fallthrough */ in get_cluster_offset()
1714 cluster_sector = extent->sesparse_clusters_offset + in get_cluster_offset()
1715 cluster_sector * extent->cluster_sectors; in get_cluster_offset()
1723 if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) { in get_cluster_offset()
1732 assert(!extent->sesparse); in get_cluster_offset()
1734 if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) { in get_cluster_offset()
1738 cluster_sector = extent->next_cluster_sector; in get_cluster_offset()
1739 extent->next_cluster_sector += extent->cluster_sectors; in get_cluster_offset()
1753 m_data->new_allocation = true; in get_cluster_offset()
1766 extent = &s->extents[0]; in find_extent()
1768 while (extent < &s->extents[s->num_extents]) { in find_extent()
1769 if (sector_num < extent->end_sector) { in find_extent()
1781 uint64_t cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE; in vmdk_find_offset_in_cluster()
1784 (extent->end_sector - extent->sectors) * BDRV_SECTOR_SIZE; in vmdk_find_offset_in_cluster()
1785 extent_relative_offset = offset - extent_begin_offset; in vmdk_find_offset_in_cluster()
1794 BDRVVmdkState *s = bs->opaque; in vmdk_co_block_status()
1801 return -EIO; in vmdk_co_block_status()
1803 qemu_co_mutex_lock(&s->lock); in vmdk_co_block_status()
1806 qemu_co_mutex_unlock(&s->lock); in vmdk_co_block_status()
1811 ret = -EIO; in vmdk_co_block_status()
1821 if (!extent->compressed) { in vmdk_co_block_status()
1824 if (extent->flat) { in vmdk_co_block_status()
1830 *file = extent->file->bs; in vmdk_co_block_status()
1834 n = extent->cluster_sectors * BDRV_SECTOR_SIZE - index_in_cluster; in vmdk_co_block_status()
1852 if (extent->compressed) { in vmdk_write_extent()
1857 n_bytes > (extent->cluster_sectors * SECTOR_SIZE) || in vmdk_write_extent()
1858 (n_bytes < (extent->cluster_sectors * SECTOR_SIZE) && in vmdk_write_extent()
1859 offset + n_bytes != extent->end_sector * SECTOR_SIZE)) in vmdk_write_extent()
1861 ret = -EINVAL; in vmdk_write_extent()
1865 if (!extent->has_marker) { in vmdk_write_extent()
1866 ret = -EINVAL; in vmdk_write_extent()
1869 buf_len = (extent->cluster_sectors << 9) * 2; in vmdk_write_extent()
1874 ret = compress(data->data, &buf_len, compressed_data, n_bytes); in vmdk_write_extent()
1878 ret = -EINVAL; in vmdk_write_extent()
1882 data->lba = cpu_to_le64(offset >> BDRV_SECTOR_BITS); in vmdk_write_extent()
1883 data->size = cpu_to_le32(buf_len); in vmdk_write_extent()
1888 BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED); in vmdk_write_extent()
1890 qemu_iovec_init(&local_qiov, qiov->niov); in vmdk_write_extent()
1893 BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_AIO); in vmdk_write_extent()
1897 ret = bdrv_co_pwritev(extent->file, write_offset, n_bytes, in vmdk_write_extent()
1902 if (extent->compressed) { in vmdk_write_extent()
1903 extent->next_cluster_sector = write_end_sector; in vmdk_write_extent()
1905 extent->next_cluster_sector = MAX(extent->next_cluster_sector, in vmdk_write_extent()
1915 if (!extent->compressed) { in vmdk_write_extent()
1934 if (!extent->compressed) { in vmdk_read_extent()
1935 BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_AIO); in vmdk_read_extent()
1936 ret = bdrv_co_preadv(extent->file, in vmdk_read_extent()
1944 cluster_bytes = extent->cluster_sectors * 512; in vmdk_read_extent()
1949 BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_COMPRESSED); in vmdk_read_extent()
1950 ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, in vmdk_read_extent()
1958 if (extent->has_marker) { in vmdk_read_extent()
1960 compressed_data = marker->data; in vmdk_read_extent()
1961 data_len = le32_to_cpu(marker->size); in vmdk_read_extent()
1964 ret = -EINVAL; in vmdk_read_extent()
1969 ret = -EINVAL; in vmdk_read_extent()
1975 ret = -EINVAL; in vmdk_read_extent()
1991 BDRVVmdkState *s = bs->opaque; in vmdk_co_preadv()
1999 qemu_iovec_init(&local_qiov, qiov->niov); in vmdk_co_preadv()
2000 qemu_co_mutex_lock(&s->lock); in vmdk_co_preadv()
2005 ret = -EIO; in vmdk_co_preadv()
2012 n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE in vmdk_co_preadv()
2013 - offset_in_cluster); in vmdk_co_preadv()
2017 if (bs->backing && ret != VMDK_ZEROED) { in vmdk_co_preadv()
2019 ret = -EINVAL; in vmdk_co_preadv()
2026 /* qcow2 emits this on bs->file instead of bs->backing */ in vmdk_co_preadv()
2027 BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); in vmdk_co_preadv()
2028 ret = bdrv_co_preadv(bs->backing, offset, n_bytes, in vmdk_co_preadv()
2046 bytes -= n_bytes; in vmdk_co_preadv()
2053 qemu_co_mutex_unlock(&s->lock); in vmdk_co_preadv()
2062 * if possible, otherwise return -ENOTSUP.
2073 BDRVVmdkState *s = bs->opaque; in vmdk_pwritev()
2081 if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { in vmdk_pwritev()
2084 offset, bs->total_sectors); in vmdk_pwritev()
2085 return -EIO; in vmdk_pwritev()
2091 return -EIO; in vmdk_pwritev()
2093 if (extent->sesparse) { in vmdk_pwritev()
2094 return -ENOTSUP; in vmdk_pwritev()
2097 n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE in vmdk_pwritev()
2098 - offset_in_cluster); in vmdk_pwritev()
2101 !(extent->compressed || zeroed), in vmdk_pwritev()
2104 if (extent->compressed) { in vmdk_pwritev()
2109 return -EIO; in vmdk_pwritev()
2117 return -EINVAL; in vmdk_pwritev()
2121 if (extent->has_zero_grain && in vmdk_pwritev()
2123 n_bytes >= extent->cluster_sectors * BDRV_SECTOR_SIZE) { in vmdk_pwritev()
2124 n_bytes = extent->cluster_sectors * BDRV_SECTOR_SIZE; in vmdk_pwritev()
2129 return -EIO; in vmdk_pwritev()
2133 return -ENOTSUP; in vmdk_pwritev()
2146 return -EIO; in vmdk_pwritev()
2150 bytes -= n_bytes; in vmdk_pwritev()
2156 if (!s->cid_updated) { in vmdk_pwritev()
2161 s->cid_updated = true; in vmdk_pwritev()
2172 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwritev()
2173 qemu_co_mutex_lock(&s->lock); in vmdk_co_pwritev()
2175 qemu_co_mutex_unlock(&s->lock); in vmdk_co_pwritev()
2186 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwritev_compressed()
2190 for (i = 0; i < s->num_extents; i++) { in vmdk_co_pwritev_compressed()
2191 length = bdrv_co_getlength(s->extents[i].file->bs); in vmdk_co_pwritev_compressed()
2196 ret = bdrv_co_truncate(s->extents[i].file, length, false, in vmdk_co_pwritev_compressed()
2212 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwrite_zeroes()
2214 qemu_co_mutex_lock(&s->lock); in vmdk_co_pwrite_zeroes()
2221 qemu_co_mutex_unlock(&s->lock); in vmdk_co_pwrite_zeroes()
2290 error_setg_errno(errp, -ret, "failed to write VMDK magic"); in vmdk_init_extent()
2295 error_setg_errno(errp, -ret, "failed to write VMDK header"); in vmdk_init_extent()
2315 error_setg_errno(errp, -ret, "failed to write VMDK grain directory"); in vmdk_init_extent()
2327 error_setg_errno(errp, -ret, in vmdk_init_extent()
2354 ret = -EIO; in vmdk_create_extent()
2391 if (p - filename >= buf_len) { in filename_decompose()
2394 pstrcpy(path, p - filename + 1, filename); in filename_decompose()
2404 if (q - p >= buf_len) { in filename_decompose()
2407 pstrcpy(prefix, q - p + 1, p); in filename_decompose()
2415 * non-split format.
2416 * idx >= 1: get the n-th extent if in a split subformat
2491 ret = -EINVAL; in vmdk_co_do_create()
2505 creating, exporting, etc. vmdk files with a non-ide adapter type */ in vmdk_co_do_create()
2521 ret = -ENOTSUP; in vmdk_co_do_create()
2526 ret = -ENOTSUP; in vmdk_co_do_create()
2545 ret = -EIO; in vmdk_co_do_create()
2550 blk_bs(blk)->filename); in vmdk_co_do_create()
2556 bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, in vmdk_co_do_create()
2561 ret = -ENOENT; in vmdk_co_do_create()
2570 ret = -EIO; in vmdk_co_do_create()
2573 if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) { in vmdk_co_do_create()
2575 blk_bs(backing)->drv->format_name); in vmdk_co_do_create()
2577 ret = -EINVAL; in vmdk_co_do_create()
2594 int64_t cur_size = MIN(size - created_size, extent_size); in vmdk_co_do_create()
2598 ret = -EINVAL; in vmdk_co_do_create()
2602 blk_bs(extent_blk)->filename); in vmdk_co_do_create()
2609 extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain, in vmdk_co_do_create()
2614 ret = -EINVAL; in vmdk_co_do_create()
2624 ext_desc_lines->str, in vmdk_co_do_create()
2639 error_setg_errno(errp, -ret, "Could not write description"); in vmdk_co_do_create()
2680 if (size == -1) { in vmdk_co_create_opts_cb()
2686 rel_filename = g_strdup_printf("%s%s", data->prefix, data->postfix); in vmdk_co_create_opts_cb()
2688 rel_filename = g_strdup_printf("%s-%c%03d%s", in vmdk_co_create_opts_cb()
2689 data->prefix, in vmdk_co_create_opts_cb()
2690 flat ? 'f' : 's', idx, data->postfix); in vmdk_co_create_opts_cb()
2693 rel_filename = g_strdup_printf("%s-flat%s", data->prefix, data->postfix); in vmdk_co_create_opts_cb()
2696 ext_filename = g_strdup_printf("%s%s", data->path, rel_filename); in vmdk_co_create_opts_cb()
2700 flat, compress, zeroed_grain, &blk, data->opts, in vmdk_co_create_opts_cb()
2740 ret = -EINVAL; in vmdk_co_create_opts()
2745 ret = -EINVAL; in vmdk_co_create_opts()
2770 ret = -EINVAL; in vmdk_co_create_opts()
2787 ret = -EINVAL; in vmdk_co_create_opts()
2829 bs = bdrv_co_open_blockdev_ref(opts->file, errp); in vmdk_co_create_cb()
2832 BlockdevRefList *list = opts->extents; in vmdk_co_create_cb()
2834 if (!list || !list->next) { in vmdk_co_create_cb()
2838 list = list->next; in vmdk_co_create_cb()
2841 error_setg(errp, "Extent [%d] not specified", idx - 1); in vmdk_co_create_cb()
2844 bs = bdrv_co_open_blockdev_ref(list->value, errp); in vmdk_co_create_cb()
2860 if (size != -1) { in vmdk_co_create_cb()
2875 opts = &create_options->u.vmdk; in vmdk_co_create()
2878 if (!QEMU_IS_ALIGNED(opts->size, BDRV_SECTOR_SIZE)) { in vmdk_co_create()
2880 return -EINVAL; in vmdk_co_create()
2883 return vmdk_co_do_create(opts->size, in vmdk_co_create()
2884 opts->subformat, in vmdk_co_create()
2885 opts->adapter_type, in vmdk_co_create()
2886 opts->backing_file, in vmdk_co_create()
2887 opts->hwversion, in vmdk_co_create()
2888 opts->toolsversion, in vmdk_co_create()
2890 opts->zeroed_grain, in vmdk_co_create()
2897 BDRVVmdkState *s = bs->opaque; in vmdk_close()
2900 g_free(s->create_type); in vmdk_close()
2902 migrate_del_blocker(&s->migration_blocker); in vmdk_close()
2911 BDRVVmdkState *s = bs->opaque; in vmdk_co_get_allocated_file_size()
2913 ret = bdrv_co_get_allocated_file_size(bs->file->bs); in vmdk_co_get_allocated_file_size()
2917 for (i = 0; i < s->num_extents; i++) { in vmdk_co_get_allocated_file_size()
2918 if (s->extents[i].file == bs->file) { in vmdk_co_get_allocated_file_size()
2921 r = bdrv_co_get_allocated_file_size(s->extents[i].file->bs); in vmdk_co_get_allocated_file_size()
2933 BDRVVmdkState *s = bs->opaque; in vmdk_has_zero_init()
2937 for (i = 0; i < s->num_extents; i++) { in vmdk_has_zero_init()
2938 if (s->extents[i].flat) { in vmdk_has_zero_init()
2939 if (!bdrv_has_zero_init(s->extents[i].file->bs)) { in vmdk_has_zero_init()
2951 bdrv_refresh_filename(extent->file->bs); in vmdk_get_extent_info()
2953 .filename = g_strdup(extent->file->bs->filename), in vmdk_get_extent_info()
2954 .format = g_strdup(extent->type), in vmdk_get_extent_info()
2955 .virtual_size = extent->sectors * BDRV_SECTOR_SIZE, in vmdk_get_extent_info()
2956 .compressed = extent->compressed, in vmdk_get_extent_info()
2957 .has_compressed = extent->compressed, in vmdk_get_extent_info()
2958 .cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE, in vmdk_get_extent_info()
2959 .has_cluster_size = !extent->flat, in vmdk_get_extent_info()
2968 BDRVVmdkState *s = bs->opaque; in vmdk_co_check()
2976 return -ENOTSUP; in vmdk_co_check()
2988 ret = -EINVAL; in vmdk_co_check()
3001 int64_t extent_len = bdrv_co_getlength(extent->file->bs); in vmdk_co_check()
3013 ret = -EINVAL; in vmdk_co_check()
3017 sector_num += extent->cluster_sectors; in vmdk_co_check()
3020 result->corruptions++; in vmdk_co_check()
3028 BDRVVmdkState *s = bs->opaque; in vmdk_get_specific_info()
3039 *spec_info->u.vmdk.data = (ImageInfoSpecificVmdk) { in vmdk_get_specific_info()
3040 .create_type = g_strdup(s->create_type), in vmdk_get_specific_info()
3041 .cid = s->cid, in vmdk_get_specific_info()
3042 .parent_cid = s->parent_cid, in vmdk_get_specific_info()
3045 tail = &spec_info->u.vmdk.data->extents; in vmdk_get_specific_info()
3046 for (i = 0; i < s->num_extents; i++) { in vmdk_get_specific_info()
3047 QAPI_LIST_APPEND(tail, vmdk_get_extent_info(&s->extents[i])); in vmdk_get_specific_info()
3055 return a->flat == b->flat && in vmdk_extents_type_eq()
3056 a->compressed == b->compressed && in vmdk_extents_type_eq()
3057 (a->flat || a->cluster_sectors == b->cluster_sectors); in vmdk_extents_type_eq()
3064 BDRVVmdkState *s = bs->opaque; in vmdk_co_get_info()
3065 assert(s->num_extents); in vmdk_co_get_info()
3068 for (i = 1; i < s->num_extents; i++) { in vmdk_co_get_info()
3069 if (!vmdk_extents_type_eq(&s->extents[0], &s->extents[i])) { in vmdk_co_get_info()
3070 return -ENOTSUP; in vmdk_co_get_info()
3073 bdi->needs_compressed_writes = s->extents[0].compressed; in vmdk_co_get_info()
3074 if (!s->extents[0].flat) { in vmdk_co_get_info()
3075 bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS; in vmdk_co_get_info()
3086 qobject_ref(bs->file->bs->full_open_options)); in vmdk_gather_child_options()
3089 if (bs->backing) { in vmdk_gather_child_options()
3091 qobject_ref(bs->backing->bs->full_open_options)); in vmdk_gather_child_options()
3099 .name = "vmdk-create-opts",
3151 "using the zeroed-grain GTE feature"