Lines Matching +full:- +full:- +full:disable +full:- +full:sparse
29 #include "system/block-backend.h"
31 #include "qemu/error-report.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()
275 for (i = 0; i < s->num_extents; i++) { in vmdk_free_extents()
276 e = &s->extents[i]; in vmdk_free_extents()
277 g_free(e->l1_table); in vmdk_free_extents()
278 g_free(e->l2_cache); in vmdk_free_extents()
279 g_free(e->l1_backup_table); in vmdk_free_extents()
280 g_free(e->type); in vmdk_free_extents()
281 if (e->file != bs->file) { in vmdk_free_extents()
282 bdrv_unref_child(bs, e->file); in vmdk_free_extents()
287 g_free(s->extents); in vmdk_free_extents()
292 BDRVVmdkState *s = bs->opaque; in vmdk_free_last_extent()
294 if (s->num_extents == 0) { in vmdk_free_last_extent()
297 s->num_extents--; in vmdk_free_last_extent()
298 s->extents = g_renew(VmdkExtent, s->extents, s->num_extents); in vmdk_free_last_extent()
301 /* Return -ve errno, or 0 on success and write CID into *pcid. */
309 BDRVVmdkState *s = bs->opaque; in vmdk_read_cid()
313 ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); in vmdk_read_cid()
326 desc[DESC_SIZE - 1] = '\0'; in vmdk_read_cid()
329 ret = -EINVAL; in vmdk_read_cid()
334 ret = -EINVAL; in vmdk_read_cid()
350 BDRVVmdkState *s = bs->opaque; in vmdk_write_cid()
355 if (s->desc_offset == 0) { in vmdk_write_cid()
356 desc_buf_size = bdrv_getlength(bs->file->bs); in vmdk_write_cid()
359 return -EFBIG; in vmdk_write_cid()
367 ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0); in vmdk_write_cid()
372 desc[desc_buf_size - 1] = '\0'; in vmdk_write_cid()
375 ret = -EINVAL; in vmdk_write_cid()
383 snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid); in vmdk_write_cid()
387 ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0); in vmdk_write_cid()
397 BDRVVmdkState *s = bs->opaque; in vmdk_is_cid_valid()
400 if (!s->cid_checked && bs->backing) { in vmdk_is_cid_valid()
401 BlockDriverState *p_bs = bs->backing->bs; in vmdk_is_cid_valid()
403 if (strcmp(p_bs->drv->format_name, "vmdk")) { in vmdk_is_cid_valid()
413 if (s->parent_cid != cur_pcid) { in vmdk_is_cid_valid()
418 s->cid_checked = true; in vmdk_is_cid_valid()
434 assert(state->bs != NULL); in vmdk_reopen_prepare()
435 assert(state->opaque == NULL); in vmdk_reopen_prepare()
437 s = state->bs->opaque; in vmdk_reopen_prepare()
440 state->opaque = rs; in vmdk_reopen_prepare()
443 * Check whether there are any extents stored in bs->file; if bs->file in vmdk_reopen_prepare()
446 rs->extents_using_bs_file = g_new(bool, s->num_extents); in vmdk_reopen_prepare()
447 for (i = 0; i < s->num_extents; i++) { in vmdk_reopen_prepare()
448 rs->extents_using_bs_file[i] = s->extents[i].file == state->bs->file; in vmdk_reopen_prepare()
456 BDRVVmdkReopenState *rs = state->opaque; in vmdk_reopen_clean()
458 g_free(rs->extents_using_bs_file); in vmdk_reopen_clean()
460 state->opaque = NULL; in vmdk_reopen_clean()
465 BDRVVmdkState *s = state->bs->opaque; in vmdk_reopen_commit()
466 BDRVVmdkReopenState *rs = state->opaque; in vmdk_reopen_commit()
472 for (i = 0; i < s->num_extents; i++) { in vmdk_reopen_commit()
473 if (rs->extents_using_bs_file[i]) { in vmdk_reopen_commit()
474 s->extents[i].file = state->bs->file; in vmdk_reopen_commit()
490 BDRVVmdkState *s = bs->opaque; in vmdk_parent_open()
494 ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); in vmdk_parent_open()
506 ret = -EINVAL; in vmdk_parent_open()
509 if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) { in vmdk_parent_open()
510 ret = -EINVAL; in vmdk_parent_open()
514 pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name); in vmdk_parent_open()
515 pstrcpy(bs->backing_file, sizeof(bs->backing_file), in vmdk_parent_open()
516 bs->auto_backing_file); in vmdk_parent_open()
517 pstrcpy(bs->backing_format, sizeof(bs->backing_format), in vmdk_parent_open()
537 BDRVVmdkState *s = bs->opaque; in vmdk_add_extent()
543 return -EFBIG; in vmdk_add_extent()
550 * 8TB - for both VMDK3 & VMDK4 with in vmdk_add_extent()
555 * 64TB - for "ESXi seSparse Extent" in vmdk_add_extent()
562 return -EFBIG; in vmdk_add_extent()
565 nb_sectors = bdrv_nb_sectors(file->bs); in vmdk_add_extent()
570 s->extents = g_renew(VmdkExtent, s->extents, s->num_extents + 1); in vmdk_add_extent()
571 extent = &s->extents[s->num_extents]; in vmdk_add_extent()
572 s->num_extents++; in vmdk_add_extent()
575 extent->file = file; in vmdk_add_extent()
576 extent->flat = flat; in vmdk_add_extent()
577 extent->sectors = sectors; in vmdk_add_extent()
578 extent->l1_table_offset = l1_offset; in vmdk_add_extent()
579 extent->l1_backup_table_offset = l1_backup_offset; in vmdk_add_extent()
580 extent->l1_size = l1_size; in vmdk_add_extent()
581 extent->l1_entry_sectors = l2_size * cluster_sectors; in vmdk_add_extent()
582 extent->l2_size = l2_size; in vmdk_add_extent()
583 extent->cluster_sectors = flat ? sectors : cluster_sectors; in vmdk_add_extent()
584 extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors); in vmdk_add_extent()
585 extent->entry_size = sizeof(uint32_t); in vmdk_add_extent()
587 if (s->num_extents > 1) { in vmdk_add_extent()
588 extent->end_sector = (*(extent - 1)).end_sector + extent->sectors; in vmdk_add_extent()
590 extent->end_sector = extent->sectors; in vmdk_add_extent()
592 bs->total_sectors = extent->end_sector; in vmdk_add_extent()
607 l1_size = extent->l1_size * extent->entry_size; in vmdk_init_tables()
608 extent->l1_table = g_try_malloc(l1_size); in vmdk_init_tables()
609 if (l1_size && extent->l1_table == NULL) { in vmdk_init_tables()
610 return -ENOMEM; in vmdk_init_tables()
613 ret = bdrv_pread(extent->file, extent->l1_table_offset, l1_size, in vmdk_init_tables()
614 extent->l1_table, 0); in vmdk_init_tables()
616 bdrv_refresh_filename(extent->file->bs); in vmdk_init_tables()
617 error_setg_errno(errp, -ret, in vmdk_init_tables()
619 extent->file->bs->filename); in vmdk_init_tables()
622 for (i = 0; i < extent->l1_size; i++) { in vmdk_init_tables()
623 if (extent->entry_size == sizeof(uint64_t)) { in vmdk_init_tables()
624 le64_to_cpus((uint64_t *)extent->l1_table + i); in vmdk_init_tables()
626 assert(extent->entry_size == sizeof(uint32_t)); in vmdk_init_tables()
627 le32_to_cpus((uint32_t *)extent->l1_table + i); in vmdk_init_tables()
631 if (extent->l1_backup_table_offset) { in vmdk_init_tables()
632 assert(!extent->sesparse); in vmdk_init_tables()
633 extent->l1_backup_table = g_try_malloc(l1_size); in vmdk_init_tables()
634 if (l1_size && extent->l1_backup_table == NULL) { in vmdk_init_tables()
635 ret = -ENOMEM; in vmdk_init_tables()
638 ret = bdrv_pread(extent->file, extent->l1_backup_table_offset, in vmdk_init_tables()
639 l1_size, extent->l1_backup_table, 0); in vmdk_init_tables()
641 bdrv_refresh_filename(extent->file->bs); in vmdk_init_tables()
642 error_setg_errno(errp, -ret, in vmdk_init_tables()
644 extent->file->bs->filename); in vmdk_init_tables()
647 for (i = 0; i < extent->l1_size; i++) { in vmdk_init_tables()
648 le32_to_cpus(&extent->l1_backup_table[i]); in vmdk_init_tables()
652 extent->l2_cache = in vmdk_init_tables()
653 g_malloc(extent->entry_size * extent->l2_size * L2_CACHE_SIZE); in vmdk_init_tables()
656 g_free(extent->l1_backup_table); in vmdk_init_tables()
658 g_free(extent->l1_table); in vmdk_init_tables()
673 bdrv_refresh_filename(file->bs); in vmdk_open_vmfs_sparse()
674 error_setg_errno(errp, -ret, in vmdk_open_vmfs_sparse()
676 file->bs->filename); in vmdk_open_vmfs_sparse()
702 /* Strict checks - format not officially documented */
706 header->magic = le64_to_cpu(header->magic); in check_se_sparse_const_header()
707 header->version = le64_to_cpu(header->version); in check_se_sparse_const_header()
708 header->grain_size = le64_to_cpu(header->grain_size); in check_se_sparse_const_header()
709 header->grain_table_size = le64_to_cpu(header->grain_table_size); in check_se_sparse_const_header()
710 header->flags = le64_to_cpu(header->flags); in check_se_sparse_const_header()
711 header->reserved1 = le64_to_cpu(header->reserved1); in check_se_sparse_const_header()
712 header->reserved2 = le64_to_cpu(header->reserved2); in check_se_sparse_const_header()
713 header->reserved3 = le64_to_cpu(header->reserved3); in check_se_sparse_const_header()
714 header->reserved4 = le64_to_cpu(header->reserved4); in check_se_sparse_const_header()
716 header->volatile_header_offset = in check_se_sparse_const_header()
717 le64_to_cpu(header->volatile_header_offset); in check_se_sparse_const_header()
718 header->volatile_header_size = le64_to_cpu(header->volatile_header_size); in check_se_sparse_const_header()
720 header->journal_header_offset = le64_to_cpu(header->journal_header_offset); in check_se_sparse_const_header()
721 header->journal_header_size = le64_to_cpu(header->journal_header_size); in check_se_sparse_const_header()
723 header->journal_offset = le64_to_cpu(header->journal_offset); in check_se_sparse_const_header()
724 header->journal_size = le64_to_cpu(header->journal_size); in check_se_sparse_const_header()
726 header->grain_dir_offset = le64_to_cpu(header->grain_dir_offset); in check_se_sparse_const_header()
727 header->grain_dir_size = le64_to_cpu(header->grain_dir_size); in check_se_sparse_const_header()
729 header->grain_tables_offset = le64_to_cpu(header->grain_tables_offset); in check_se_sparse_const_header()
730 header->grain_tables_size = le64_to_cpu(header->grain_tables_size); in check_se_sparse_const_header()
732 header->free_bitmap_offset = le64_to_cpu(header->free_bitmap_offset); in check_se_sparse_const_header()
733 header->free_bitmap_size = le64_to_cpu(header->free_bitmap_size); in check_se_sparse_const_header()
735 header->backmap_offset = le64_to_cpu(header->backmap_offset); in check_se_sparse_const_header()
736 header->backmap_size = le64_to_cpu(header->backmap_size); in check_se_sparse_const_header()
738 header->grains_offset = le64_to_cpu(header->grains_offset); in check_se_sparse_const_header()
739 header->grains_size = le64_to_cpu(header->grains_size); in check_se_sparse_const_header()
741 if (header->magic != SESPARSE_CONST_HEADER_MAGIC) { in check_se_sparse_const_header()
743 header->magic); in check_se_sparse_const_header()
744 return -EINVAL; in check_se_sparse_const_header()
747 if (header->version != 0x0000000200000001) { in check_se_sparse_const_header()
749 header->version); in check_se_sparse_const_header()
750 return -ENOTSUP; in check_se_sparse_const_header()
753 if (header->grain_size != 8) { in check_se_sparse_const_header()
755 header->grain_size); in check_se_sparse_const_header()
756 return -ENOTSUP; in check_se_sparse_const_header()
759 if (header->grain_table_size != 64) { in check_se_sparse_const_header()
761 header->grain_table_size); in check_se_sparse_const_header()
762 return -ENOTSUP; in check_se_sparse_const_header()
765 if (header->flags != 0) { in check_se_sparse_const_header()
767 header->flags); in check_se_sparse_const_header()
768 return -ENOTSUP; in check_se_sparse_const_header()
771 if (header->reserved1 != 0 || header->reserved2 != 0 || in check_se_sparse_const_header()
772 header->reserved3 != 0 || header->reserved4 != 0) { in check_se_sparse_const_header()
776 header->reserved1, header->reserved2, in check_se_sparse_const_header()
777 header->reserved3, header->reserved4); in check_se_sparse_const_header()
778 return -ENOTSUP; in check_se_sparse_const_header()
782 if (!buffer_is_zero(header->pad, sizeof(header->pad))) { in check_se_sparse_const_header()
783 error_setg(errp, "Unsupported non-zero const header padding"); in check_se_sparse_const_header()
784 return -ENOTSUP; in check_se_sparse_const_header()
793 header->magic = le64_to_cpu(header->magic); in check_se_sparse_volatile_header()
794 header->free_gt_number = le64_to_cpu(header->free_gt_number); in check_se_sparse_volatile_header()
795 header->next_txn_seq_number = le64_to_cpu(header->next_txn_seq_number); in check_se_sparse_volatile_header()
796 header->replay_journal = le64_to_cpu(header->replay_journal); in check_se_sparse_volatile_header()
798 if (header->magic != SESPARSE_VOLATILE_HEADER_MAGIC) { in check_se_sparse_volatile_header()
800 header->magic); in check_se_sparse_volatile_header()
801 return -EINVAL; in check_se_sparse_volatile_header()
804 if (header->replay_journal) { in check_se_sparse_volatile_header()
806 return -ENOTSUP; in check_se_sparse_volatile_header()
810 if (!buffer_is_zero(header->pad, sizeof(header->pad))) { in check_se_sparse_volatile_header()
811 error_setg(errp, "Unsupported non-zero volatile header padding"); in check_se_sparse_volatile_header()
812 return -ENOTSUP; in check_se_sparse_volatile_header()
837 bdrv_refresh_filename(file->bs); in vmdk_open_se_sparse()
838 error_setg_errno(errp, -ret, in vmdk_open_se_sparse()
840 file->bs->filename); in vmdk_open_se_sparse()
855 bdrv_refresh_filename(file->bs); in vmdk_open_se_sparse()
856 error_setg_errno(errp, -ret, in vmdk_open_se_sparse()
858 file->bs->filename); in vmdk_open_se_sparse()
883 extent->sesparse = true; in vmdk_open_se_sparse()
884 extent->sesparse_l2_tables_offset = const_header.grain_tables_offset; in vmdk_open_se_sparse()
885 extent->sesparse_clusters_offset = const_header.grains_offset; in vmdk_open_se_sparse()
886 extent->entry_size = sizeof(uint64_t); in vmdk_open_se_sparse()
906 size = bdrv_getlength(file->bs); in vmdk_read_desc()
908 error_setg_errno(errp, -size, "Could not access file"); in vmdk_read_desc()
913 /* Both descriptor file and sparse image must be much larger than 4 in vmdk_read_desc()
920 size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */ in vmdk_read_desc()
925 error_setg_errno(errp, -ret, "Could not read from file"); in vmdk_read_desc()
943 BDRVVmdkState *s = bs->opaque; in vmdk_open_vmdk4()
949 bdrv_refresh_filename(file->bs); in vmdk_open_vmdk4()
950 error_setg_errno(errp, -ret, in vmdk_open_vmdk4()
952 file->bs->filename); in vmdk_open_vmdk4()
953 return -EINVAL; in vmdk_open_vmdk4()
960 return -EINVAL; in vmdk_open_vmdk4()
968 if (!s->create_type) { in vmdk_open_vmdk4()
969 s->create_type = g_strdup("monolithicSparse"); in vmdk_open_vmdk4()
975 * footer starts at offset -1024 from the end: One sector for the in vmdk_open_vmdk4()
976 * footer, and another one for the end-of-stream marker. in vmdk_open_vmdk4()
983 uint8_t pad[512 - 16]; in vmdk_open_vmdk4()
988 uint8_t pad[512 - 4 - sizeof(VMDK4Header)]; in vmdk_open_vmdk4()
994 uint8_t pad[512 - 16]; in vmdk_open_vmdk4()
998 ret = bdrv_pread(file, bs->file->bs->total_sectors * 512 - 1536, in vmdk_open_vmdk4()
1001 error_setg_errno(errp, -ret, "Failed to read footer"); in vmdk_open_vmdk4()
1014 return -EINVAL; in vmdk_open_vmdk4()
1025 return -ENOTSUP; in vmdk_open_vmdk4()
1033 return -EINVAL; in vmdk_open_vmdk4()
1038 return -EINVAL; in vmdk_open_vmdk4()
1045 return -EINVAL; in vmdk_open_vmdk4()
1047 l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) in vmdk_open_vmdk4()
1052 if (bdrv_nb_sectors(file->bs) < le64_to_cpu(header.grain_offset)) { in vmdk_open_vmdk4()
1056 return -EINVAL; in vmdk_open_vmdk4()
1071 extent->compressed = in vmdk_open_vmdk4()
1073 if (extent->compressed) { in vmdk_open_vmdk4()
1074 g_free(s->create_type); in vmdk_open_vmdk4()
1075 s->create_type = g_strdup("streamOptimized"); in vmdk_open_vmdk4()
1077 extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER; in vmdk_open_vmdk4()
1078 extent->version = le32_to_cpu(header.version); in vmdk_open_vmdk4()
1079 extent->has_zero_grain = le32_to_cpu(header.flags) & VMDK4_FLAG_ZERO_GRAIN; in vmdk_open_vmdk4()
1108 if (opt_end == end || buf_size < opt_end - opt_pos + 1) { in vmdk_parse_description()
1111 pstrcpy(buf, opt_end - opt_pos + 1, opt_pos); in vmdk_parse_description()
1130 return -EINVAL; in vmdk_open_sparse()
1162 BDRVVmdkState *s = bs->opaque; in vmdk_parse_extents()
1172 * RW [size in sectors] FLAT "file-name.vmdk" OFFSET in vmdk_parse_extents()
1173 * RW [size in sectors] SPARSE "file-name.vmdk" in vmdk_parse_extents()
1174 * RW [size in sectors] VMFS "file-name.vmdk" in vmdk_parse_extents()
1175 * RW [size in sectors] VMFSSPARSE "file-name.vmdk" in vmdk_parse_extents()
1176 * RW [size in sectors] SESPARSE "file-name.vmdk" in vmdk_parse_extents()
1178 flat_offset = -1; in vmdk_parse_extents()
1198 (strcmp(type, "FLAT") && strcmp(type, "SPARSE") && in vmdk_parse_extents()
1209 desc_file_dir = bdrv_dirname(bs->file->bs, errp); in vmdk_parse_extents()
1211 bdrv_refresh_filename(bs->file->bs); in vmdk_parse_extents()
1214 bs->file->bs->filename); in vmdk_parse_extents()
1215 ret = -EINVAL; in vmdk_parse_extents()
1223 ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents); in vmdk_parse_extents()
1228 /* non-flat extents have metadata */ in vmdk_parse_extents()
1240 ret = -EINVAL; in vmdk_parse_extents()
1258 extent->flat_start_offset = flat_offset << 9; in vmdk_parse_extents()
1259 } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) { in vmdk_parse_extents()
1260 /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/ in vmdk_parse_extents()
1263 ret = -EINVAL; in vmdk_parse_extents()
1265 ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf, in vmdk_parse_extents()
1277 extent = &s->extents[s->num_extents - 1]; in vmdk_parse_extents()
1279 ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp); in vmdk_parse_extents()
1288 extent = &s->extents[s->num_extents - 1]; in vmdk_parse_extents()
1296 ret = -ENOTSUP; in vmdk_parse_extents()
1299 extent->type = g_strdup(type); in vmdk_parse_extents()
1308 if (np[-1] == '\n') { in vmdk_parse_extents()
1309 np--; in vmdk_parse_extents()
1311 error_setg(errp, "Invalid extent line: %.*s", (int)(np - p), p); in vmdk_parse_extents()
1312 ret = -EINVAL; in vmdk_parse_extents()
1325 BDRVVmdkState *s = bs->opaque; in vmdk_open_desc_file()
1329 ret = -EINVAL; in vmdk_open_desc_file()
1339 ret = -ENOTSUP; in vmdk_open_desc_file()
1342 s->create_type = g_strdup(ct); in vmdk_open_desc_file()
1343 s->desc_offset = 0; in vmdk_open_desc_file()
1354 BDRVVmdkState *s = bs->opaque; in vmdk_open()
1364 buf = vmdk_read_desc(bs->file, 0, errp); in vmdk_open()
1366 return -EINVAL; in vmdk_open()
1373 ret = vmdk_open_sparse(bs, bs->file, flags, buf, options, in vmdk_open()
1375 s->desc_offset = 0x200; in vmdk_open()
1379 bs->file->role &= ~BDRV_CHILD_DATA; in vmdk_open()
1382 bdrv_child_refresh_perms(bs, bs->file, &error_abort); in vmdk_open()
1396 ret = vmdk_read_cid(bs, 0, &s->cid); in vmdk_open()
1400 ret = vmdk_read_cid(bs, 1, &s->parent_cid); in vmdk_open()
1404 qemu_co_mutex_init(&s->lock); in vmdk_open()
1406 /* Disable migration when VMDK images are used */ in vmdk_open()
1407 error_setg(&s->migration_blocker, "The vmdk format used by node '%s' " in vmdk_open()
1410 ret = migrate_add_blocker_normal(&s->migration_blocker, errp); in vmdk_open()
1420 g_free(s->create_type); in vmdk_open()
1421 s->create_type = NULL; in vmdk_open()
1429 BDRVVmdkState *s = bs->opaque; in vmdk_refresh_limits()
1432 for (i = 0; i < s->num_extents; i++) { in vmdk_refresh_limits()
1433 if (!s->extents[i].flat) { in vmdk_refresh_limits()
1434 bs->bl.pwrite_zeroes_alignment = in vmdk_refresh_limits()
1435 MAX(bs->bl.pwrite_zeroes_alignment, in vmdk_refresh_limits()
1436 s->extents[i].cluster_sectors << BDRV_SECTOR_BITS); in vmdk_refresh_limits()
1465 cluster_bytes = extent->cluster_sectors << BDRV_SECTOR_BITS; in get_whole_cluster()
1468 copy_from_backing = bs->backing && !zeroed; in get_whole_cluster()
1472 memset(whole_grain + skip_end_bytes, 0, cluster_bytes - skip_end_bytes); in get_whole_cluster()
1476 /* we will be here if it's first write on non-exist grain(cluster). in get_whole_cluster()
1478 if (bs->backing && !vmdk_is_cid_valid(bs)) { in get_whole_cluster()
1486 /* qcow2 emits this on bs->file instead of bs->backing */ in get_whole_cluster()
1487 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); in get_whole_cluster()
1488 ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes, in get_whole_cluster()
1495 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); in get_whole_cluster()
1496 ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes, in get_whole_cluster()
1506 /* qcow2 emits this on bs->file instead of bs->backing */ in get_whole_cluster()
1507 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); in get_whole_cluster()
1508 ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes, in get_whole_cluster()
1509 cluster_bytes - skip_end_bytes, in get_whole_cluster()
1516 BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); in get_whole_cluster()
1517 ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes, in get_whole_cluster()
1518 cluster_bytes - skip_end_bytes, in get_whole_cluster()
1537 BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_UPDATE); in vmdk_L2update()
1538 if (bdrv_co_pwrite(extent->file, in vmdk_L2update()
1539 ((int64_t)m_data->l2_offset * 512) in vmdk_L2update()
1540 + (m_data->l2_index * sizeof(offset)), in vmdk_L2update()
1545 if (extent->l1_backup_table_offset != 0) { in vmdk_L2update()
1546 m_data->l2_offset = extent->l1_backup_table[m_data->l1_index]; in vmdk_L2update()
1547 if (bdrv_co_pwrite(extent->file, in vmdk_L2update()
1548 ((int64_t)m_data->l2_offset * 512) in vmdk_L2update()
1549 + (m_data->l2_index * sizeof(offset)), in vmdk_L2update()
1554 if (bdrv_co_flush(extent->file->bs) < 0) { in vmdk_L2update()
1557 if (m_data->l2_cache_entry) { in vmdk_L2update()
1558 *m_data->l2_cache_entry = offset; in vmdk_L2update()
1573 * For sparse extents, look up in L1, L2 table. If allocate is true, return an
1597 unsigned int l2_size_bytes = extent->l2_size * extent->entry_size; in get_cluster_offset()
1600 m_data->new_allocation = false; in get_cluster_offset()
1602 if (extent->flat) { in get_cluster_offset()
1603 *cluster_offset = extent->flat_start_offset; in get_cluster_offset()
1607 offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE; in get_cluster_offset()
1608 l1_index = (offset >> 9) / extent->l1_entry_sectors; in get_cluster_offset()
1609 if (l1_index >= extent->l1_size) { in get_cluster_offset()
1612 if (extent->sesparse) { in get_cluster_offset()
1615 assert(extent->entry_size == sizeof(uint64_t)); in get_cluster_offset()
1617 l2_offset_u64 = ((uint64_t *)extent->l1_table)[l1_index]; in get_cluster_offset()
1623 * strict check - top most 4 bytes must be 0x10000000 since max in get_cluster_offset()
1624 * supported size is 64TB for disk - so no more than 64TB / 16MB in get_cluster_offset()
1631 l2_offset_u64 = extent->sesparse_l2_tables_offset + in get_cluster_offset()
1639 assert(extent->entry_size == sizeof(uint32_t)); in get_cluster_offset()
1640 l2_offset = ((uint32_t *)extent->l1_table)[l1_index]; in get_cluster_offset()
1646 if (l2_offset == extent->l2_cache_offsets[i]) { in get_cluster_offset()
1648 if (++extent->l2_cache_counts[i] == 0xffffffff) { in get_cluster_offset()
1650 extent->l2_cache_counts[j] >>= 1; in get_cluster_offset()
1653 l2_table = (char *)extent->l2_cache + (i * l2_size_bytes); in get_cluster_offset()
1661 if (extent->l2_cache_counts[i] < min_count) { in get_cluster_offset()
1662 min_count = extent->l2_cache_counts[i]; in get_cluster_offset()
1666 l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes); in get_cluster_offset()
1667 BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_LOAD); in get_cluster_offset()
1668 if (bdrv_co_pread(extent->file, in get_cluster_offset()
1676 extent->l2_cache_offsets[min_index] = l2_offset; in get_cluster_offset()
1677 extent->l2_cache_counts[min_index] = 1; in get_cluster_offset()
1679 l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size; in get_cluster_offset()
1681 m_data->l1_index = l1_index; in get_cluster_offset()
1682 m_data->l2_index = l2_index; in get_cluster_offset()
1683 m_data->l2_offset = l2_offset; in get_cluster_offset()
1684 m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index; in get_cluster_offset()
1687 if (extent->sesparse) { in get_cluster_offset()
1697 /* scsi-unmapped grain - fallthrough */ in get_cluster_offset()
1706 cluster_sector = extent->sesparse_clusters_offset + in get_cluster_offset()
1707 cluster_sector * extent->cluster_sectors; in get_cluster_offset()
1715 if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) { in get_cluster_offset()
1724 assert(!extent->sesparse); in get_cluster_offset()
1726 if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) { in get_cluster_offset()
1730 cluster_sector = extent->next_cluster_sector; in get_cluster_offset()
1731 extent->next_cluster_sector += extent->cluster_sectors; in get_cluster_offset()
1745 m_data->new_allocation = true; in get_cluster_offset()
1758 extent = &s->extents[0]; in find_extent()
1760 while (extent < &s->extents[s->num_extents]) { in find_extent()
1761 if (sector_num < extent->end_sector) { in find_extent()
1773 uint64_t cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE; in vmdk_find_offset_in_cluster()
1776 (extent->end_sector - extent->sectors) * BDRV_SECTOR_SIZE; in vmdk_find_offset_in_cluster()
1777 extent_relative_offset = offset - extent_begin_offset; in vmdk_find_offset_in_cluster()
1786 BDRVVmdkState *s = bs->opaque; in vmdk_co_block_status()
1793 return -EIO; in vmdk_co_block_status()
1795 qemu_co_mutex_lock(&s->lock); in vmdk_co_block_status()
1798 qemu_co_mutex_unlock(&s->lock); in vmdk_co_block_status()
1803 ret = -EIO; in vmdk_co_block_status()
1813 if (!extent->compressed) { in vmdk_co_block_status()
1816 if (extent->flat) { in vmdk_co_block_status()
1822 *file = extent->file->bs; in vmdk_co_block_status()
1826 n = extent->cluster_sectors * BDRV_SECTOR_SIZE - index_in_cluster; in vmdk_co_block_status()
1844 if (extent->compressed) { in vmdk_write_extent()
1849 n_bytes > (extent->cluster_sectors * SECTOR_SIZE) || in vmdk_write_extent()
1850 (n_bytes < (extent->cluster_sectors * SECTOR_SIZE) && in vmdk_write_extent()
1851 offset + n_bytes != extent->end_sector * SECTOR_SIZE)) in vmdk_write_extent()
1853 ret = -EINVAL; in vmdk_write_extent()
1857 if (!extent->has_marker) { in vmdk_write_extent()
1858 ret = -EINVAL; in vmdk_write_extent()
1861 buf_len = (extent->cluster_sectors << 9) * 2; in vmdk_write_extent()
1866 ret = compress(data->data, &buf_len, compressed_data, n_bytes); in vmdk_write_extent()
1870 ret = -EINVAL; in vmdk_write_extent()
1874 data->lba = cpu_to_le64(offset >> BDRV_SECTOR_BITS); in vmdk_write_extent()
1875 data->size = cpu_to_le32(buf_len); in vmdk_write_extent()
1880 BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED); in vmdk_write_extent()
1882 qemu_iovec_init(&local_qiov, qiov->niov); in vmdk_write_extent()
1885 BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_AIO); in vmdk_write_extent()
1889 ret = bdrv_co_pwritev(extent->file, write_offset, n_bytes, in vmdk_write_extent()
1894 if (extent->compressed) { in vmdk_write_extent()
1895 extent->next_cluster_sector = write_end_sector; in vmdk_write_extent()
1897 extent->next_cluster_sector = MAX(extent->next_cluster_sector, in vmdk_write_extent()
1907 if (!extent->compressed) { in vmdk_write_extent()
1926 if (!extent->compressed) { in vmdk_read_extent()
1927 BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_AIO); in vmdk_read_extent()
1928 ret = bdrv_co_preadv(extent->file, in vmdk_read_extent()
1936 cluster_bytes = extent->cluster_sectors * 512; in vmdk_read_extent()
1941 BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_COMPRESSED); in vmdk_read_extent()
1942 ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, in vmdk_read_extent()
1950 if (extent->has_marker) { in vmdk_read_extent()
1952 compressed_data = marker->data; in vmdk_read_extent()
1953 data_len = le32_to_cpu(marker->size); in vmdk_read_extent()
1956 ret = -EINVAL; in vmdk_read_extent()
1961 ret = -EINVAL; in vmdk_read_extent()
1967 ret = -EINVAL; in vmdk_read_extent()
1983 BDRVVmdkState *s = bs->opaque; in vmdk_co_preadv()
1991 qemu_iovec_init(&local_qiov, qiov->niov); in vmdk_co_preadv()
1992 qemu_co_mutex_lock(&s->lock); in vmdk_co_preadv()
1997 ret = -EIO; in vmdk_co_preadv()
2004 n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE in vmdk_co_preadv()
2005 - offset_in_cluster); in vmdk_co_preadv()
2009 if (bs->backing && ret != VMDK_ZEROED) { in vmdk_co_preadv()
2011 ret = -EINVAL; in vmdk_co_preadv()
2018 /* qcow2 emits this on bs->file instead of bs->backing */ in vmdk_co_preadv()
2019 BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); in vmdk_co_preadv()
2020 ret = bdrv_co_preadv(bs->backing, offset, n_bytes, in vmdk_co_preadv()
2038 bytes -= n_bytes; in vmdk_co_preadv()
2045 qemu_co_mutex_unlock(&s->lock); in vmdk_co_preadv()
2054 * if possible, otherwise return -ENOTSUP.
2065 BDRVVmdkState *s = bs->opaque; in vmdk_pwritev()
2073 if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { in vmdk_pwritev()
2076 offset, bs->total_sectors); in vmdk_pwritev()
2077 return -EIO; in vmdk_pwritev()
2083 return -EIO; in vmdk_pwritev()
2085 if (extent->sesparse) { in vmdk_pwritev()
2086 return -ENOTSUP; in vmdk_pwritev()
2089 n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE in vmdk_pwritev()
2090 - offset_in_cluster); in vmdk_pwritev()
2093 !(extent->compressed || zeroed), in vmdk_pwritev()
2096 if (extent->compressed) { in vmdk_pwritev()
2101 return -EIO; in vmdk_pwritev()
2109 return -EINVAL; in vmdk_pwritev()
2113 if (extent->has_zero_grain && in vmdk_pwritev()
2115 n_bytes >= extent->cluster_sectors * BDRV_SECTOR_SIZE) { in vmdk_pwritev()
2116 n_bytes = extent->cluster_sectors * BDRV_SECTOR_SIZE; in vmdk_pwritev()
2121 return -EIO; in vmdk_pwritev()
2125 return -ENOTSUP; in vmdk_pwritev()
2138 return -EIO; in vmdk_pwritev()
2142 bytes -= n_bytes; in vmdk_pwritev()
2148 if (!s->cid_updated) { in vmdk_pwritev()
2153 s->cid_updated = true; in vmdk_pwritev()
2164 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwritev()
2165 qemu_co_mutex_lock(&s->lock); in vmdk_co_pwritev()
2167 qemu_co_mutex_unlock(&s->lock); in vmdk_co_pwritev()
2178 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwritev_compressed()
2182 for (i = 0; i < s->num_extents; i++) { in vmdk_co_pwritev_compressed()
2183 length = bdrv_co_getlength(s->extents[i].file->bs); in vmdk_co_pwritev_compressed()
2188 ret = bdrv_co_truncate(s->extents[i].file, length, false, in vmdk_co_pwritev_compressed()
2204 BDRVVmdkState *s = bs->opaque; in vmdk_co_pwrite_zeroes()
2206 qemu_co_mutex_lock(&s->lock); in vmdk_co_pwrite_zeroes()
2213 qemu_co_mutex_unlock(&s->lock); in vmdk_co_pwrite_zeroes()
2282 error_setg_errno(errp, -ret, "failed to write VMDK magic"); in vmdk_init_extent()
2287 error_setg_errno(errp, -ret, "failed to write VMDK header"); in vmdk_init_extent()
2307 error_setg_errno(errp, -ret, "failed to write VMDK grain directory"); in vmdk_init_extent()
2319 error_setg_errno(errp, -ret, in vmdk_init_extent()
2346 ret = -EIO; in vmdk_create_extent()
2383 if (p - filename >= buf_len) { in filename_decompose()
2386 pstrcpy(path, p - filename + 1, filename); in filename_decompose()
2396 if (q - p >= buf_len) { in filename_decompose()
2399 pstrcpy(prefix, q - p + 1, p); in filename_decompose()
2407 * non-split format.
2408 * idx >= 1: get the n-th extent if in a split subformat
2483 ret = -EINVAL; in vmdk_co_do_create()
2497 creating, exporting, etc. vmdk files with a non-ide adapter type */ in vmdk_co_do_create()
2509 extent_line_fmt = "RW %" PRId64 " SPARSE \"%s\"\n"; in vmdk_co_do_create()
2513 ret = -ENOTSUP; in vmdk_co_do_create()
2518 ret = -ENOTSUP; in vmdk_co_do_create()
2537 ret = -EIO; in vmdk_co_do_create()
2542 blk_bs(blk)->filename); in vmdk_co_do_create()
2548 bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, in vmdk_co_do_create()
2553 ret = -ENOENT; in vmdk_co_do_create()
2562 ret = -EIO; in vmdk_co_do_create()
2565 if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) { in vmdk_co_do_create()
2567 blk_bs(backing)->drv->format_name); in vmdk_co_do_create()
2569 ret = -EINVAL; in vmdk_co_do_create()
2586 int64_t cur_size = MIN(size - created_size, extent_size); in vmdk_co_do_create()
2590 ret = -EINVAL; in vmdk_co_do_create()
2594 blk_bs(extent_blk)->filename); in vmdk_co_do_create()
2601 extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain, in vmdk_co_do_create()
2606 ret = -EINVAL; in vmdk_co_do_create()
2616 ext_desc_lines->str, in vmdk_co_do_create()
2631 error_setg_errno(errp, -ret, "Could not write description"); in vmdk_co_do_create()
2672 if (size == -1) { in vmdk_co_create_opts_cb()
2678 rel_filename = g_strdup_printf("%s%s", data->prefix, data->postfix); in vmdk_co_create_opts_cb()
2680 rel_filename = g_strdup_printf("%s-%c%03d%s", in vmdk_co_create_opts_cb()
2681 data->prefix, in vmdk_co_create_opts_cb()
2682 flat ? 'f' : 's', idx, data->postfix); in vmdk_co_create_opts_cb()
2685 rel_filename = g_strdup_printf("%s-flat%s", data->prefix, data->postfix); in vmdk_co_create_opts_cb()
2688 ext_filename = g_strdup_printf("%s%s", data->path, rel_filename); in vmdk_co_create_opts_cb()
2692 flat, compress, zeroed_grain, &blk, data->opts, in vmdk_co_create_opts_cb()
2732 ret = -EINVAL; in vmdk_co_create_opts()
2737 ret = -EINVAL; in vmdk_co_create_opts()
2762 ret = -EINVAL; in vmdk_co_create_opts()
2779 ret = -EINVAL; in vmdk_co_create_opts()
2821 bs = bdrv_co_open_blockdev_ref(opts->file, errp); in vmdk_co_create_cb()
2824 BlockdevRefList *list = opts->extents; in vmdk_co_create_cb()
2826 if (!list || !list->next) { in vmdk_co_create_cb()
2830 list = list->next; in vmdk_co_create_cb()
2833 error_setg(errp, "Extent [%d] not specified", idx - 1); in vmdk_co_create_cb()
2836 bs = bdrv_co_open_blockdev_ref(list->value, errp); in vmdk_co_create_cb()
2852 if (size != -1) { in vmdk_co_create_cb()
2867 opts = &create_options->u.vmdk; in vmdk_co_create()
2870 if (!QEMU_IS_ALIGNED(opts->size, BDRV_SECTOR_SIZE)) { in vmdk_co_create()
2872 return -EINVAL; in vmdk_co_create()
2875 return vmdk_co_do_create(opts->size, in vmdk_co_create()
2876 opts->subformat, in vmdk_co_create()
2877 opts->adapter_type, in vmdk_co_create()
2878 opts->backing_file, in vmdk_co_create()
2879 opts->hwversion, in vmdk_co_create()
2880 opts->toolsversion, in vmdk_co_create()
2882 opts->zeroed_grain, in vmdk_co_create()
2889 BDRVVmdkState *s = bs->opaque; in vmdk_close()
2892 g_free(s->create_type); in vmdk_close()
2894 migrate_del_blocker(&s->migration_blocker); in vmdk_close()
2903 BDRVVmdkState *s = bs->opaque; in vmdk_co_get_allocated_file_size()
2905 ret = bdrv_co_get_allocated_file_size(bs->file->bs); in vmdk_co_get_allocated_file_size()
2909 for (i = 0; i < s->num_extents; i++) { in vmdk_co_get_allocated_file_size()
2910 if (s->extents[i].file == bs->file) { in vmdk_co_get_allocated_file_size()
2913 r = bdrv_co_get_allocated_file_size(s->extents[i].file->bs); in vmdk_co_get_allocated_file_size()
2925 BDRVVmdkState *s = bs->opaque; in vmdk_has_zero_init()
2929 for (i = 0; i < s->num_extents; i++) { in vmdk_has_zero_init()
2930 if (s->extents[i].flat) { in vmdk_has_zero_init()
2931 if (!bdrv_has_zero_init(s->extents[i].file->bs)) { in vmdk_has_zero_init()
2943 bdrv_refresh_filename(extent->file->bs); in vmdk_get_extent_info()
2945 .filename = g_strdup(extent->file->bs->filename), in vmdk_get_extent_info()
2946 .format = g_strdup(extent->type), in vmdk_get_extent_info()
2947 .virtual_size = extent->sectors * BDRV_SECTOR_SIZE, in vmdk_get_extent_info()
2948 .compressed = extent->compressed, in vmdk_get_extent_info()
2949 .has_compressed = extent->compressed, in vmdk_get_extent_info()
2950 .cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE, in vmdk_get_extent_info()
2951 .has_cluster_size = !extent->flat, in vmdk_get_extent_info()
2960 BDRVVmdkState *s = bs->opaque; in vmdk_co_check()
2968 return -ENOTSUP; in vmdk_co_check()
2980 ret = -EINVAL; in vmdk_co_check()
2993 int64_t extent_len = bdrv_co_getlength(extent->file->bs); in vmdk_co_check()
3005 ret = -EINVAL; in vmdk_co_check()
3009 sector_num += extent->cluster_sectors; in vmdk_co_check()
3012 result->corruptions++; in vmdk_co_check()
3020 BDRVVmdkState *s = bs->opaque; in vmdk_get_specific_info()
3031 *spec_info->u.vmdk.data = (ImageInfoSpecificVmdk) { in vmdk_get_specific_info()
3032 .create_type = g_strdup(s->create_type), in vmdk_get_specific_info()
3033 .cid = s->cid, in vmdk_get_specific_info()
3034 .parent_cid = s->parent_cid, in vmdk_get_specific_info()
3037 tail = &spec_info->u.vmdk.data->extents; in vmdk_get_specific_info()
3038 for (i = 0; i < s->num_extents; i++) { in vmdk_get_specific_info()
3039 QAPI_LIST_APPEND(tail, vmdk_get_extent_info(&s->extents[i])); in vmdk_get_specific_info()
3047 return a->flat == b->flat && in vmdk_extents_type_eq()
3048 a->compressed == b->compressed && in vmdk_extents_type_eq()
3049 (a->flat || a->cluster_sectors == b->cluster_sectors); in vmdk_extents_type_eq()
3056 BDRVVmdkState *s = bs->opaque; in vmdk_co_get_info()
3057 assert(s->num_extents); in vmdk_co_get_info()
3060 for (i = 1; i < s->num_extents; i++) { in vmdk_co_get_info()
3061 if (!vmdk_extents_type_eq(&s->extents[0], &s->extents[i])) { in vmdk_co_get_info()
3062 return -ENOTSUP; in vmdk_co_get_info()
3065 bdi->needs_compressed_writes = s->extents[0].compressed; in vmdk_co_get_info()
3066 if (!s->extents[0].flat) { in vmdk_co_get_info()
3067 bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS; in vmdk_co_get_info()
3078 qobject_ref(bs->file->bs->full_open_options)); in vmdk_gather_child_options()
3081 if (bs->backing) { in vmdk_gather_child_options()
3083 qobject_ref(bs->backing->bs->full_open_options)); in vmdk_gather_child_options()
3091 .name = "vmdk-create-opts",
3143 "using the zeroed-grain GTE feature"