Block patches:

- The SSH block driver now uses libssh instead of libssh2
 - The VMDK block driver gets read-only support for the seSparse
   subformat
 - Various fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl0Q4XASHG1yZWl0ekBy
 ZWRoYXQuY29tAAoJEPQH2wBh1c9AIU8H+wVaUzYwlIZIgUkC6A9ZiCNbur9TngnZ
 ywt9kc4CW8kEuIHm/m87qayt6cwWlw6OnWktQW14HHEqFVKdg2LwbJN20yG3a+tm
 YAkwcfkIbJ6ZMKx2QZ4TTwov6rbf57yQtwxPtkxXMMMe488WYoN/wZig25+6BYgU
 Z8FLhSW36TVAjbYAxuO+O9/JSx4DzjmHFnTkwW3XRLFYRMmH+eY3jB2T90W2zV/8
 QDDTo8ZvdaSASKlMRnH4iik8lX4QXKRTjfprTzuynoth0Zvtt8jarpfLKKSPyf8Z
 9bpEHBGFxYSyapGq1fHt9Le1jNx3lPVpzVsbEeGpai0FjnHXg+fntDQ=
 =YFoG
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2019-06-24' into staging

Block patches:
- The SSH block driver now uses libssh instead of libssh2
- The VMDK block driver gets read-only support for the seSparse
  subformat
- Various fixes

# gpg: Signature made Mon 24 Jun 2019 15:42:56 BST
# gpg:                using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40
# gpg:                issuer "mreitz@redhat.com"
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full]
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2019-06-24:
  iotests: Fix 205 for concurrent runs
  ssh: switch from libssh2 to libssh
  vmdk: Add read-only support for seSparse snapshots
  vmdk: Reduce the max bound for L1 table size
  vmdk: Fix comment regarding max l1_size coverage
  iotest 134: test cluster-misaligned encrypted write
  blockdev: enable non-root nodes for transaction drive-backup source
  nvme: do not advertise support for unsupported arbitration mechanism

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-07-01 11:28:28 +01:00
commit 7fec76a022
20 changed files with 828 additions and 389 deletions

View File

@ -31,7 +31,7 @@ addons:
- libseccomp-dev
- libspice-protocol-dev
- libspice-server-dev
- libssh2-1-dev
- libssh-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvte-2.91-dev
@ -270,7 +270,7 @@ matrix:
- libseccomp-dev
- libspice-protocol-dev
- libspice-server-dev
- libssh2-1-dev
- libssh-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvte-2.91-dev

View File

@ -31,7 +31,7 @@ block-obj-$(CONFIG_CURL) += curl.o
block-obj-$(CONFIG_RBD) += rbd.o
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
block-obj-$(CONFIG_VXHS) += vxhs.o
block-obj-$(CONFIG_LIBSSH2) += ssh.o
block-obj-$(CONFIG_LIBSSH) += ssh.o
block-obj-y += accounting.o dirty-bitmap.o
block-obj-y += write-threshold.o
block-obj-y += backup.o
@ -52,8 +52,8 @@ rbd.o-libs := $(RBD_LIBS)
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
gluster.o-libs := $(GLUSTERFS_LIBS)
vxhs.o-libs := $(VXHS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
ssh.o-cflags := $(LIBSSH_CFLAGS)
ssh.o-libs := $(LIBSSH_LIBS)
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
dmg-bz2.o-libs := $(BZIP2_LIBS)

File diff suppressed because it is too large Load Diff

View File

@ -171,19 +171,21 @@ nbd_client_connect_success(const char *export_name) "export '%s'"
# ssh.c
ssh_restart_coroutine(void *co) "co=%p"
ssh_flush(void) "fsync"
ssh_check_host_key_knownhosts(const char *key) "host key OK: %s"
ssh_check_host_key_knownhosts(void) "host key OK"
ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o"
ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p"
ssh_co_yield_back(int sock) "s->sock=%d - back"
ssh_getlength(int64_t length) "length=%" PRIi64
ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64
ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu"
ssh_read_return(ssize_t ret) "sftp_read returned %zd"
ssh_read_buf(void *buf, size_t size, size_t actual_size) "sftp_read buf=%p size=%zu (actual size=%zu)"
ssh_read_return(ssize_t ret, int sftp_err) "sftp_read returned %zd (sftp error=%d)"
ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu"
ssh_write_return(ssize_t ret) "sftp_write returned %zd"
ssh_write_buf(void *buf, size_t size, size_t actual_size) "sftp_write buf=%p size=%zu (actual size=%zu)"
ssh_write_return(ssize_t ret, int sftp_err) "sftp_write returned %zd (sftp error=%d)"
ssh_seek(int64_t offset) "seeking to offset=%" PRIi64
ssh_auth_methods(int methods) "auth methods=0x%x"
ssh_server_status(int status) "server status=%d"
# curl.c
curl_timer_cb(long timeout_ms) "timer callback timeout_ms %ld"
@ -216,4 +218,4 @@ sheepdog_snapshot_create(const char *sn_name, const char *id) "%s %s"
sheepdog_snapshot_create_inode(const char *name, uint32_t snap, uint32_t vdi) "s->inode: name %s snap_id 0x%" PRIx32 " vdi 0x%" PRIx32
# ssh.c
sftp_error(const char *op, const char *ssh_err, int ssh_err_code, unsigned long sftp_err_code) "%s failed: %s (libssh2 error code: %d, sftp error code: %lu)"
sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)"

View File

@ -91,6 +91,44 @@ typedef struct {
uint16_t compressAlgorithm;
} QEMU_PACKED VMDK4Header;
typedef struct VMDKSESparseConstHeader {
uint64_t magic;
uint64_t version;
uint64_t capacity;
uint64_t grain_size;
uint64_t grain_table_size;
uint64_t flags;
uint64_t reserved1;
uint64_t reserved2;
uint64_t reserved3;
uint64_t reserved4;
uint64_t volatile_header_offset;
uint64_t volatile_header_size;
uint64_t journal_header_offset;
uint64_t journal_header_size;
uint64_t journal_offset;
uint64_t journal_size;
uint64_t grain_dir_offset;
uint64_t grain_dir_size;
uint64_t grain_tables_offset;
uint64_t grain_tables_size;
uint64_t free_bitmap_offset;
uint64_t free_bitmap_size;
uint64_t backmap_offset;
uint64_t backmap_size;
uint64_t grains_offset;
uint64_t grains_size;
uint8_t pad[304];
} QEMU_PACKED VMDKSESparseConstHeader;
typedef struct VMDKSESparseVolatileHeader {
uint64_t magic;
uint64_t free_gt_number;
uint64_t next_txn_seq_number;
uint64_t replay_journal;
uint8_t pad[480];
} QEMU_PACKED VMDKSESparseVolatileHeader;
#define L2_CACHE_SIZE 16
typedef struct VmdkExtent {
@ -99,19 +137,23 @@ typedef struct VmdkExtent {
bool compressed;
bool has_marker;
bool has_zero_grain;
bool sesparse;
uint64_t sesparse_l2_tables_offset;
uint64_t sesparse_clusters_offset;
int32_t entry_size;
int version;
int64_t sectors;
int64_t end_sector;
int64_t flat_start_offset;
int64_t l1_table_offset;
int64_t l1_backup_table_offset;
uint32_t *l1_table;
void *l1_table;
uint32_t *l1_backup_table;
unsigned int l1_size;
uint32_t l1_entry_sectors;
unsigned int l2_size;
uint32_t *l2_cache;
void *l2_cache;
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
@ -425,11 +467,22 @@ static int vmdk_add_extent(BlockDriverState *bs,
error_setg(errp, "Invalid granularity, image may be corrupt");
return -EFBIG;
}
if (l1_size > 512 * 1024 * 1024) {
/* Although with big capacity and small l1_entry_sectors, we can get a
if (l1_size > 32 * 1024 * 1024) {
/*
* Although with big capacity and small l1_entry_sectors, we can get a
* big l1_size, we don't want unbounded value to allocate the table.
* Limit it to 512M, which is 16PB for default cluster and L2 table
* size */
* Limit it to 32M, which is enough to store:
* 8TB - for both VMDK3 & VMDK4 with
* minimal cluster size: 512B
* minimal L2 table size: 512 entries
* 8 TB is still more than the maximal value supported for
* VMDK3 & VMDK4 which is 2TB.
* 64TB - for "ESXi seSparse Extent"
* minimal cluster size: 512B (default is 4KB)
* L2 table size: 4096 entries (const).
* 64TB is more than the maximal value supported for
* seSparse VMDKs (which is slightly less than 64TB)
*/
error_setg(errp, "L1 size too big");
return -EFBIG;
}
@ -454,6 +507,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
extent->l2_size = l2_size;
extent->cluster_sectors = flat ? sectors : cluster_sectors;
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
extent->entry_size = sizeof(uint32_t);
if (s->num_extents > 1) {
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
@ -475,7 +529,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
int i;
/* read the L1 table */
l1_size = extent->l1_size * sizeof(uint32_t);
l1_size = extent->l1_size * extent->entry_size;
extent->l1_table = g_try_malloc(l1_size);
if (l1_size && extent->l1_table == NULL) {
return -ENOMEM;
@ -493,10 +547,16 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
goto fail_l1;
}
for (i = 0; i < extent->l1_size; i++) {
le32_to_cpus(&extent->l1_table[i]);
if (extent->entry_size == sizeof(uint64_t)) {
le64_to_cpus((uint64_t *)extent->l1_table + i);
} else {
assert(extent->entry_size == sizeof(uint32_t));
le32_to_cpus((uint32_t *)extent->l1_table + i);
}
}
if (extent->l1_backup_table_offset) {
assert(!extent->sesparse);
extent->l1_backup_table = g_try_malloc(l1_size);
if (l1_size && extent->l1_backup_table == NULL) {
ret = -ENOMEM;
@ -519,7 +579,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
}
extent->l2_cache =
g_new(uint32_t, extent->l2_size * L2_CACHE_SIZE);
g_malloc(extent->entry_size * extent->l2_size * L2_CACHE_SIZE);
return 0;
fail_l1b:
g_free(extent->l1_backup_table);
@ -565,6 +625,205 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
return ret;
}
#define SESPARSE_CONST_HEADER_MAGIC UINT64_C(0x00000000cafebabe)
#define SESPARSE_VOLATILE_HEADER_MAGIC UINT64_C(0x00000000cafecafe)
/* Strict checks - format not officially documented */
static int check_se_sparse_const_header(VMDKSESparseConstHeader *header,
Error **errp)
{
header->magic = le64_to_cpu(header->magic);
header->version = le64_to_cpu(header->version);
header->grain_size = le64_to_cpu(header->grain_size);
header->grain_table_size = le64_to_cpu(header->grain_table_size);
header->flags = le64_to_cpu(header->flags);
header->reserved1 = le64_to_cpu(header->reserved1);
header->reserved2 = le64_to_cpu(header->reserved2);
header->reserved3 = le64_to_cpu(header->reserved3);
header->reserved4 = le64_to_cpu(header->reserved4);
header->volatile_header_offset =
le64_to_cpu(header->volatile_header_offset);
header->volatile_header_size = le64_to_cpu(header->volatile_header_size);
header->journal_header_offset = le64_to_cpu(header->journal_header_offset);
header->journal_header_size = le64_to_cpu(header->journal_header_size);
header->journal_offset = le64_to_cpu(header->journal_offset);
header->journal_size = le64_to_cpu(header->journal_size);
header->grain_dir_offset = le64_to_cpu(header->grain_dir_offset);
header->grain_dir_size = le64_to_cpu(header->grain_dir_size);
header->grain_tables_offset = le64_to_cpu(header->grain_tables_offset);
header->grain_tables_size = le64_to_cpu(header->grain_tables_size);
header->free_bitmap_offset = le64_to_cpu(header->free_bitmap_offset);
header->free_bitmap_size = le64_to_cpu(header->free_bitmap_size);
header->backmap_offset = le64_to_cpu(header->backmap_offset);
header->backmap_size = le64_to_cpu(header->backmap_size);
header->grains_offset = le64_to_cpu(header->grains_offset);
header->grains_size = le64_to_cpu(header->grains_size);
if (header->magic != SESPARSE_CONST_HEADER_MAGIC) {
error_setg(errp, "Bad const header magic: 0x%016" PRIx64,
header->magic);
return -EINVAL;
}
if (header->version != 0x0000000200000001) {
error_setg(errp, "Unsupported version: 0x%016" PRIx64,
header->version);
return -ENOTSUP;
}
if (header->grain_size != 8) {
error_setg(errp, "Unsupported grain size: %" PRIu64,
header->grain_size);
return -ENOTSUP;
}
if (header->grain_table_size != 64) {
error_setg(errp, "Unsupported grain table size: %" PRIu64,
header->grain_table_size);
return -ENOTSUP;
}
if (header->flags != 0) {
error_setg(errp, "Unsupported flags: 0x%016" PRIx64,
header->flags);
return -ENOTSUP;
}
if (header->reserved1 != 0 || header->reserved2 != 0 ||
header->reserved3 != 0 || header->reserved4 != 0) {
error_setg(errp, "Unsupported reserved bits:"
" 0x%016" PRIx64 " 0x%016" PRIx64
" 0x%016" PRIx64 " 0x%016" PRIx64,
header->reserved1, header->reserved2,
header->reserved3, header->reserved4);
return -ENOTSUP;
}
/* check that padding is 0 */
if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
error_setg(errp, "Unsupported non-zero const header padding");
return -ENOTSUP;
}
return 0;
}
static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
Error **errp)
{
header->magic = le64_to_cpu(header->magic);
header->free_gt_number = le64_to_cpu(header->free_gt_number);
header->next_txn_seq_number = le64_to_cpu(header->next_txn_seq_number);
header->replay_journal = le64_to_cpu(header->replay_journal);
if (header->magic != SESPARSE_VOLATILE_HEADER_MAGIC) {
error_setg(errp, "Bad volatile header magic: 0x%016" PRIx64,
header->magic);
return -EINVAL;
}
if (header->replay_journal) {
error_setg(errp, "Image is dirty, Replaying journal not supported");
return -ENOTSUP;
}
/* check that padding is 0 */
if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
error_setg(errp, "Unsupported non-zero volatile header padding");
return -ENOTSUP;
}
return 0;
}
static int vmdk_open_se_sparse(BlockDriverState *bs,
BdrvChild *file,
int flags, Error **errp)
{
int ret;
VMDKSESparseConstHeader const_header;
VMDKSESparseVolatileHeader volatile_header;
VmdkExtent *extent;
ret = bdrv_apply_auto_read_only(bs,
"No write support for seSparse images available", errp);
if (ret < 0) {
return ret;
}
assert(sizeof(const_header) == SECTOR_SIZE);
ret = bdrv_pread(file, 0, &const_header, sizeof(const_header));
if (ret < 0) {
bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read const header from file '%s'",
file->bs->filename);
return ret;
}
/* check const header */
ret = check_se_sparse_const_header(&const_header, errp);
if (ret < 0) {
return ret;
}
assert(sizeof(volatile_header) == SECTOR_SIZE);
ret = bdrv_pread(file,
const_header.volatile_header_offset * SECTOR_SIZE,
&volatile_header, sizeof(volatile_header));
if (ret < 0) {
bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read volatile header from file '%s'",
file->bs->filename);
return ret;
}
/* check volatile header */
ret = check_se_sparse_volatile_header(&volatile_header, errp);
if (ret < 0) {
return ret;
}
ret = vmdk_add_extent(bs, file, false,
const_header.capacity,
const_header.grain_dir_offset * SECTOR_SIZE,
0,
const_header.grain_dir_size *
SECTOR_SIZE / sizeof(uint64_t),
const_header.grain_table_size *
SECTOR_SIZE / sizeof(uint64_t),
const_header.grain_size,
&extent,
errp);
if (ret < 0) {
return ret;
}
extent->sesparse = true;
extent->sesparse_l2_tables_offset = const_header.grain_tables_offset;
extent->sesparse_clusters_offset = const_header.grains_offset;
extent->entry_size = sizeof(uint64_t);
ret = vmdk_init_tables(bs, extent, errp);
if (ret) {
/* free extent allocated by vmdk_add_extent */
vmdk_free_last_extent(bs);
}
return ret;
}
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
QDict *options, Error **errp);
@ -842,6 +1101,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
* RW [size in sectors] SPARSE "file-name.vmdk"
* RW [size in sectors] VMFS "file-name.vmdk"
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
* RW [size in sectors] SESPARSE "file-name.vmdk"
*/
flat_offset = -1;
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
@ -864,7 +1124,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
if (sectors <= 0 ||
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE") &&
strcmp(type, "SESPARSE")) ||
(strcmp(access, "RW"))) {
continue;
}
@ -917,6 +1178,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
return ret;
}
extent = &s->extents[s->num_extents - 1];
} else if (!strcmp(type, "SESPARSE")) {
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
if (ret) {
bdrv_unref_child(bs, extent_file);
return ret;
}
extent = &s->extents[s->num_extents - 1];
} else {
error_setg(errp, "Unsupported extent type '%s'", type);
bdrv_unref_child(bs, extent_file);
@ -951,6 +1219,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
if (strcmp(ct, "monolithicFlat") &&
strcmp(ct, "vmfs") &&
strcmp(ct, "vmfsSparse") &&
strcmp(ct, "seSparse") &&
strcmp(ct, "twoGbMaxExtentSparse") &&
strcmp(ct, "twoGbMaxExtentFlat")) {
error_setg(errp, "Unsupported image type '%s'", ct);
@ -1201,10 +1470,12 @@ static int get_cluster_offset(BlockDriverState *bs,
{
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
uint32_t min_count, *l2_table;
uint32_t min_count;
void *l2_table;
bool zeroed = false;
int64_t ret;
int64_t cluster_sector;
unsigned int l2_size_bytes = extent->l2_size * extent->entry_size;
if (m_data) {
m_data->valid = 0;
@ -1219,7 +1490,36 @@ static int get_cluster_offset(BlockDriverState *bs,
if (l1_index >= extent->l1_size) {
return VMDK_ERROR;
}
l2_offset = extent->l1_table[l1_index];
if (extent->sesparse) {
uint64_t l2_offset_u64;
assert(extent->entry_size == sizeof(uint64_t));
l2_offset_u64 = ((uint64_t *)extent->l1_table)[l1_index];
if (l2_offset_u64 == 0) {
l2_offset = 0;
} else if ((l2_offset_u64 & 0xffffffff00000000) != 0x1000000000000000) {
/*
* Top most nibble is 0x1 if grain table is allocated.
* strict check - top most 4 bytes must be 0x10000000 since max
* supported size is 64TB for disk - so no more than 64TB / 16MB
* grain directories which is smaller than uint32,
* where 16MB is the only supported default grain table coverage.
*/
return VMDK_ERROR;
} else {
l2_offset_u64 = l2_offset_u64 & 0x00000000ffffffff;
l2_offset_u64 = extent->sesparse_l2_tables_offset +
l2_offset_u64 * l2_size_bytes / SECTOR_SIZE;
if (l2_offset_u64 > 0x00000000ffffffff) {
return VMDK_ERROR;
}
l2_offset = (unsigned int)(l2_offset_u64);
}
} else {
assert(extent->entry_size == sizeof(uint32_t));
l2_offset = ((uint32_t *)extent->l1_table)[l1_index];
}
if (!l2_offset) {
return VMDK_UNALLOC;
}
@ -1231,7 +1531,7 @@ static int get_cluster_offset(BlockDriverState *bs,
extent->l2_cache_counts[j] >>= 1;
}
}
l2_table = extent->l2_cache + (i * extent->l2_size);
l2_table = (char *)extent->l2_cache + (i * l2_size_bytes);
goto found;
}
}
@ -1244,13 +1544,13 @@ static int get_cluster_offset(BlockDriverState *bs,
min_index = i;
}
}
l2_table = extent->l2_cache + (min_index * extent->l2_size);
l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
if (bdrv_pread(extent->file,
(int64_t)l2_offset * 512,
l2_table,
extent->l2_size * sizeof(uint32_t)
) != extent->l2_size * sizeof(uint32_t)) {
l2_size_bytes
) != l2_size_bytes) {
return VMDK_ERROR;
}
@ -1258,16 +1558,45 @@ static int get_cluster_offset(BlockDriverState *bs,
extent->l2_cache_counts[min_index] = 1;
found:
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
cluster_sector = le32_to_cpu(l2_table[l2_index]);
if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
zeroed = true;
if (extent->sesparse) {
cluster_sector = le64_to_cpu(((uint64_t *)l2_table)[l2_index]);
switch (cluster_sector & 0xf000000000000000) {
case 0x0000000000000000:
/* unallocated grain */
if (cluster_sector != 0) {
return VMDK_ERROR;
}
break;
case 0x1000000000000000:
/* scsi-unmapped grain - fallthrough */
case 0x2000000000000000:
/* zero grain */
zeroed = true;
break;
case 0x3000000000000000:
/* allocated grain */
cluster_sector = (((cluster_sector & 0x0fff000000000000) >> 48) |
((cluster_sector & 0x0000ffffffffffff) << 12));
cluster_sector = extent->sesparse_clusters_offset +
cluster_sector * extent->cluster_sectors;
break;
default:
return VMDK_ERROR;
}
} else {
cluster_sector = le32_to_cpu(((uint32_t *)l2_table)[l2_index]);
if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
zeroed = true;
}
}
if (!cluster_sector || zeroed) {
if (!allocate) {
return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
}
assert(!extent->sesparse);
if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) {
return VMDK_ERROR;
@ -1291,7 +1620,7 @@ static int get_cluster_offset(BlockDriverState *bs,
m_data->l1_index = l1_index;
m_data->l2_index = l2_index;
m_data->l2_offset = l2_offset;
m_data->l2_cache_entry = &l2_table[l2_index];
m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index;
}
}
*cluster_offset = cluster_sector << BDRV_SECTOR_BITS;
@ -1617,6 +1946,9 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
if (!extent) {
return -EIO;
}
if (extent->sesparse) {
return -ENOTSUP;
}
offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE
- offset_in_cluster);

View File

@ -1774,7 +1774,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
backup = common->action->u.drive_backup.data;
bs = qmp_get_root_bs(backup->device, errp);
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
if (!bs) {
return;
}

65
configure vendored
View File

@ -472,7 +472,7 @@ auth_pam=""
vte=""
virglrenderer=""
tpm=""
libssh2=""
libssh=""
live_block_migration="yes"
numa=""
tcmalloc="no"
@ -1439,9 +1439,9 @@ for opt do
;;
--enable-tpm) tpm="yes"
;;
--disable-libssh2) libssh2="no"
--disable-libssh) libssh="no"
;;
--enable-libssh2) libssh2="yes"
--enable-libssh) libssh="yes"
;;
--disable-live-block-migration) live_block_migration="no"
;;
@ -1810,7 +1810,7 @@ disabled with --disable-FEATURE, default is enabled if available:
coroutine-pool coroutine freelist (better performance)
glusterfs GlusterFS backend
tpm TPM support
libssh2 ssh block device support
libssh ssh block device support
numa libnuma support
libxml2 for Parallels image format
tcmalloc tcmalloc support
@ -3914,43 +3914,34 @@ EOF
fi
##########################################
# libssh2 probe
min_libssh2_version=1.2.8
if test "$libssh2" != "no" ; then
if $pkg_config --atleast-version=$min_libssh2_version libssh2; then
libssh2_cflags=$($pkg_config libssh2 --cflags)
libssh2_libs=$($pkg_config libssh2 --libs)
libssh2=yes
# libssh probe
if test "$libssh" != "no" ; then
if $pkg_config --exists libssh; then
libssh_cflags=$($pkg_config libssh --cflags)
libssh_libs=$($pkg_config libssh --libs)
libssh=yes
else
if test "$libssh2" = "yes" ; then
error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2"
if test "$libssh" = "yes" ; then
error_exit "libssh required for --enable-libssh"
fi
libssh2=no
libssh=no
fi
fi
##########################################
# libssh2_sftp_fsync probe
# Check for libssh 0.8
# This is done like this instead of using the LIBSSH_VERSION_* and
# SSH_VERSION_* macros because some distributions in the past shipped
# snapshots of the future 0.8 from Git, and those snapshots did not
# have updated version numbers (still referring to 0.7.0).
if test "$libssh2" = "yes"; then
if test "$libssh" = "yes"; then
cat > $TMPC <<EOF
#include <stdio.h>
#include <libssh2.h>
#include <libssh2_sftp.h>
int main(void) {
LIBSSH2_SESSION *session;
LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *sftp_handle;
session = libssh2_session_init ();
sftp = libssh2_sftp_init (session);
sftp_handle = libssh2_sftp_open (sftp, "/", 0, 0);
libssh2_sftp_fsync (sftp_handle);
return 0;
}
#include <libssh/libssh.h>
int main(void) { return ssh_get_server_publickey(NULL, NULL); }
EOF
# libssh2_cflags/libssh2_libs defined in previous test.
if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then
QEMU_CFLAGS="-DHAS_LIBSSH2_SFTP_FSYNC $QEMU_CFLAGS"
if compile_prog "$libssh_cflags" "$libssh_libs"; then
libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags"
fi
fi
@ -6451,7 +6442,7 @@ echo "GlusterFS support $glusterfs"
echo "gcov $gcov_tool"
echo "gcov enabled $gcov"
echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "libssh support $libssh"
echo "QOM debugging $qom_cast_debug"
echo "Live block migration $live_block_migration"
echo "lzo support $lzo"
@ -7144,10 +7135,10 @@ if test "$glusterfs_iocb_has_stat" = "yes" ; then
echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak
fi
if test "$libssh2" = "yes" ; then
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
if test "$libssh" = "yes" ; then
echo "CONFIG_LIBSSH=m" >> $config_host_mak
echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak
echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak
fi
if test "$live_block_migration" = "yes" ; then

View File

@ -782,7 +782,7 @@ print a warning when @code{fsync} is not supported:
warning: ssh server @code{ssh.example.com:22} does not support fsync
With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is
With sufficiently new versions of libssh and OpenSSH, @code{fsync} is
supported.
@node disk_images_nvme

View File

@ -1384,7 +1384,6 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
n->bar.cap = 0;
NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
NVME_CAP_SET_CQR(n->bar.cap, 1);
NVME_CAP_SET_AMS(n->bar.cap, 1);
NVME_CAP_SET_TO(n->bar.cap, 0xf);
NVME_CAP_SET_CSS(n->bar.cap, 1);
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);

View File

@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
mxe-$TARGET-w64-mingw32.shared-curl \
mxe-$TARGET-w64-mingw32.shared-glib \
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
mxe-$TARGET-w64-mingw32.shared-libssh2 \
mxe-$TARGET-w64-mingw32.shared-libusb1 \
mxe-$TARGET-w64-mingw32.shared-lzo \
mxe-$TARGET-w64-mingw32.shared-nettle \

View File

@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
mxe-$TARGET-w64-mingw32.shared-curl \
mxe-$TARGET-w64-mingw32.shared-glib \
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
mxe-$TARGET-w64-mingw32.shared-libssh2 \
mxe-$TARGET-w64-mingw32.shared-libusb1 \
mxe-$TARGET-w64-mingw32.shared-lzo \
mxe-$TARGET-w64-mingw32.shared-nettle \

View File

@ -35,7 +35,7 @@ ENV PACKAGES \
libpng-devel \
librbd-devel \
libseccomp-devel \
libssh2-devel \
libssh-devel \
libubsan \
libusbx-devel \
libxml2-devel \
@ -50,7 +50,6 @@ ENV PACKAGES \
mingw32-gtk3 \
mingw32-libjpeg-turbo \
mingw32-libpng \
mingw32-libssh2 \
mingw32-libtasn1 \
mingw32-nettle \
mingw32-pixman \
@ -64,7 +63,6 @@ ENV PACKAGES \
mingw64-gtk3 \
mingw64-libjpeg-turbo \
mingw64-libpng \
mingw64-libssh2 \
mingw64-libtasn1 \
mingw64-nettle \
mingw64-pixman \

View File

@ -53,7 +53,7 @@ ENV PACKAGES flex bison \
libsnappy-dev \
libspice-protocol-dev \
libspice-server-dev \
libssh2-1-dev \
libssh-dev \
libusb-1.0-0-dev \
libusbredirhost-dev \
libvdeplug-dev \

View File

@ -40,7 +40,7 @@ ENV PACKAGES flex bison \
libsnappy-dev \
libspice-protocol-dev \
libspice-server-dev \
libssh2-1-dev \
libssh-dev \
libusb-1.0-0-dev \
libusbredirhost-dev \
libvdeplug-dev \

View File

@ -2358,5 +2358,5 @@ Offset Length Mapped to File
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
=== Testing afl image with a very large capacity ===
qemu-img: Can't get image size 'TEST_DIR/afl9.IMGFMT': File too large
qemu-img: Could not open 'TEST_DIR/afl9.IMGFMT': L1 size too big
*** done

View File

@ -56,6 +56,15 @@ echo
echo "== reading whole image =="
$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
echo
echo "== rewriting cluster part =="
$QEMU_IO --object $SECRET -c "write -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
echo
echo "== verify pattern =="
$QEMU_IO --object $SECRET -c "read -P 0 0 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
$QEMU_IO --object $SECRET -c "read -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
echo
echo "== rewriting whole image =="
$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir

View File

@ -5,6 +5,16 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.
read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== rewriting cluster part ==
wrote 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verify pattern ==
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== rewriting whole image ==
wrote 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)

View File

@ -24,7 +24,7 @@ import iotests
import time
from iotests import qemu_img_create, qemu_io, filter_qemu_io, QemuIoInteractive
nbd_sock = 'nbd_sock'
nbd_sock = os.path.join(iotests.test_dir, 'nbd_sock')
nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock
disk = os.path.join(iotests.test_dir, 'disk')

View File

@ -110,12 +110,49 @@ with iotests.FilePath('t.img') as disk_path, \
iotests.img_info_log(remote_path)
md5_key = subprocess.check_output(
'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1',
shell=True).rstrip().decode('ascii')
keys = subprocess.check_output(
'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
'cut -d" " -f3',
shell=True).rstrip().decode('ascii').split('\n')
# Mappings of base64 representations to digests
md5_keys = {}
sha1_keys = {}
for key in keys:
md5_keys[key] = subprocess.check_output(
'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key,
shell=True).rstrip().decode('ascii')
sha1_keys[key] = subprocess.check_output(
'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key,
shell=True).rstrip().decode('ascii')
vm.launch()
# Find correct key first
matching_key = None
for key in keys:
result = vm.qmp('blockdev-add',
driver='ssh', node_name='node0', path=disk_path,
server={
'host': '127.0.0.1',
'port': '22',
}, host_key_check={
'mode': 'hash',
'type': 'md5',
'hash': md5_keys[key],
})
if 'error' not in result:
vm.qmp('blockdev-del', node_name='node0')
matching_key = key
break
if matching_key is None:
vm.shutdown()
iotests.notrun('Did not find a key that fits 127.0.0.1')
blockdev_create(vm, { 'driver': 'ssh',
'location': {
'path': disk_path,
@ -140,7 +177,7 @@ with iotests.FilePath('t.img') as disk_path, \
'host-key-check': {
'mode': 'hash',
'type': 'md5',
'hash': md5_key,
'hash': md5_keys[matching_key],
}
},
'size': 8388608 })
@ -148,11 +185,6 @@ with iotests.FilePath('t.img') as disk_path, \
iotests.img_info_log(remote_path)
sha1_key = subprocess.check_output(
'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1',
shell=True).rstrip().decode('ascii')
vm.launch()
blockdev_create(vm, { 'driver': 'ssh',
'location': {
@ -178,7 +210,7 @@ with iotests.FilePath('t.img') as disk_path, \
'host-key-check': {
'mode': 'hash',
'type': 'sha1',
'hash': sha1_key,
'hash': sha1_keys[matching_key],
}
},
'size': 4194304 })

View File

@ -68,7 +68,7 @@ virtual size: 4 MiB (4194304 bytes)
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
Job failed: failed to open remote file '/this/is/not/an/existing/path': SFTP server: No such file (libssh error code: 1, sftp error code: 2)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}