mirror of https://github.com/xemu-project/xemu.git
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:
commit
7fec76a022
|
@ -31,7 +31,7 @@ addons:
|
||||||
- libseccomp-dev
|
- libseccomp-dev
|
||||||
- libspice-protocol-dev
|
- libspice-protocol-dev
|
||||||
- libspice-server-dev
|
- libspice-server-dev
|
||||||
- libssh2-1-dev
|
- libssh-dev
|
||||||
- liburcu-dev
|
- liburcu-dev
|
||||||
- libusb-1.0-0-dev
|
- libusb-1.0-0-dev
|
||||||
- libvte-2.91-dev
|
- libvte-2.91-dev
|
||||||
|
@ -270,7 +270,7 @@ matrix:
|
||||||
- libseccomp-dev
|
- libseccomp-dev
|
||||||
- libspice-protocol-dev
|
- libspice-protocol-dev
|
||||||
- libspice-server-dev
|
- libspice-server-dev
|
||||||
- libssh2-1-dev
|
- libssh-dev
|
||||||
- liburcu-dev
|
- liburcu-dev
|
||||||
- libusb-1.0-0-dev
|
- libusb-1.0-0-dev
|
||||||
- libvte-2.91-dev
|
- libvte-2.91-dev
|
||||||
|
|
|
@ -31,7 +31,7 @@ block-obj-$(CONFIG_CURL) += curl.o
|
||||||
block-obj-$(CONFIG_RBD) += rbd.o
|
block-obj-$(CONFIG_RBD) += rbd.o
|
||||||
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
||||||
block-obj-$(CONFIG_VXHS) += vxhs.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 += accounting.o dirty-bitmap.o
|
||||||
block-obj-y += write-threshold.o
|
block-obj-y += write-threshold.o
|
||||||
block-obj-y += backup.o
|
block-obj-y += backup.o
|
||||||
|
@ -52,8 +52,8 @@ rbd.o-libs := $(RBD_LIBS)
|
||||||
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
|
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
|
||||||
gluster.o-libs := $(GLUSTERFS_LIBS)
|
gluster.o-libs := $(GLUSTERFS_LIBS)
|
||||||
vxhs.o-libs := $(VXHS_LIBS)
|
vxhs.o-libs := $(VXHS_LIBS)
|
||||||
ssh.o-cflags := $(LIBSSH2_CFLAGS)
|
ssh.o-cflags := $(LIBSSH_CFLAGS)
|
||||||
ssh.o-libs := $(LIBSSH2_LIBS)
|
ssh.o-libs := $(LIBSSH_LIBS)
|
||||||
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
|
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
|
||||||
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
|
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
|
||||||
dmg-bz2.o-libs := $(BZIP2_LIBS)
|
dmg-bz2.o-libs := $(BZIP2_LIBS)
|
||||||
|
|
662
block/ssh.c
662
block/ssh.c
File diff suppressed because it is too large
Load Diff
|
@ -171,19 +171,21 @@ nbd_client_connect_success(const char *export_name) "export '%s'"
|
||||||
# ssh.c
|
# ssh.c
|
||||||
ssh_restart_coroutine(void *co) "co=%p"
|
ssh_restart_coroutine(void *co) "co=%p"
|
||||||
ssh_flush(void) "fsync"
|
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_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(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_co_yield_back(int sock) "s->sock=%d - back"
|
||||||
ssh_getlength(int64_t length) "length=%" PRIi64
|
ssh_getlength(int64_t length) "length=%" PRIi64
|
||||||
ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64
|
ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64
|
||||||
ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
|
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_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) "sftp_read returned %zd"
|
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(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_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) "sftp_write returned %zd"
|
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_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.c
|
||||||
curl_timer_cb(long timeout_ms) "timer callback timeout_ms %ld"
|
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
|
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
|
# 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)"
|
||||||
|
|
372
block/vmdk.c
372
block/vmdk.c
|
@ -91,6 +91,44 @@ typedef struct {
|
||||||
uint16_t compressAlgorithm;
|
uint16_t compressAlgorithm;
|
||||||
} QEMU_PACKED VMDK4Header;
|
} 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
|
#define L2_CACHE_SIZE 16
|
||||||
|
|
||||||
typedef struct VmdkExtent {
|
typedef struct VmdkExtent {
|
||||||
|
@ -99,19 +137,23 @@ typedef struct VmdkExtent {
|
||||||
bool compressed;
|
bool compressed;
|
||||||
bool has_marker;
|
bool has_marker;
|
||||||
bool has_zero_grain;
|
bool has_zero_grain;
|
||||||
|
bool sesparse;
|
||||||
|
uint64_t sesparse_l2_tables_offset;
|
||||||
|
uint64_t sesparse_clusters_offset;
|
||||||
|
int32_t entry_size;
|
||||||
int version;
|
int version;
|
||||||
int64_t sectors;
|
int64_t sectors;
|
||||||
int64_t end_sector;
|
int64_t end_sector;
|
||||||
int64_t flat_start_offset;
|
int64_t flat_start_offset;
|
||||||
int64_t l1_table_offset;
|
int64_t l1_table_offset;
|
||||||
int64_t l1_backup_table_offset;
|
int64_t l1_backup_table_offset;
|
||||||
uint32_t *l1_table;
|
void *l1_table;
|
||||||
uint32_t *l1_backup_table;
|
uint32_t *l1_backup_table;
|
||||||
unsigned int l1_size;
|
unsigned int l1_size;
|
||||||
uint32_t l1_entry_sectors;
|
uint32_t l1_entry_sectors;
|
||||||
|
|
||||||
unsigned int l2_size;
|
unsigned int l2_size;
|
||||||
uint32_t *l2_cache;
|
void *l2_cache;
|
||||||
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
|
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
|
||||||
uint32_t l2_cache_counts[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");
|
error_setg(errp, "Invalid granularity, image may be corrupt");
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
if (l1_size > 512 * 1024 * 1024) {
|
if (l1_size > 32 * 1024 * 1024) {
|
||||||
/* Although with big capacity and small l1_entry_sectors, we can get a
|
/*
|
||||||
|
* 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.
|
* 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
|
* Limit it to 32M, which is enough to store:
|
||||||
* size */
|
* 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");
|
error_setg(errp, "L1 size too big");
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
|
@ -454,6 +507,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
|
||||||
extent->l2_size = l2_size;
|
extent->l2_size = l2_size;
|
||||||
extent->cluster_sectors = flat ? sectors : cluster_sectors;
|
extent->cluster_sectors = flat ? sectors : cluster_sectors;
|
||||||
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
|
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
|
||||||
|
extent->entry_size = sizeof(uint32_t);
|
||||||
|
|
||||||
if (s->num_extents > 1) {
|
if (s->num_extents > 1) {
|
||||||
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
|
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
|
||||||
|
@ -475,7 +529,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* read the L1 table */
|
/* 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);
|
extent->l1_table = g_try_malloc(l1_size);
|
||||||
if (l1_size && extent->l1_table == NULL) {
|
if (l1_size && extent->l1_table == NULL) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -493,10 +547,16 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||||
goto fail_l1;
|
goto fail_l1;
|
||||||
}
|
}
|
||||||
for (i = 0; i < extent->l1_size; i++) {
|
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) {
|
if (extent->l1_backup_table_offset) {
|
||||||
|
assert(!extent->sesparse);
|
||||||
extent->l1_backup_table = g_try_malloc(l1_size);
|
extent->l1_backup_table = g_try_malloc(l1_size);
|
||||||
if (l1_size && extent->l1_backup_table == NULL) {
|
if (l1_size && extent->l1_backup_table == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -519,7 +579,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||||
}
|
}
|
||||||
|
|
||||||
extent->l2_cache =
|
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;
|
return 0;
|
||||||
fail_l1b:
|
fail_l1b:
|
||||||
g_free(extent->l1_backup_table);
|
g_free(extent->l1_backup_table);
|
||||||
|
@ -565,6 +625,205 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
|
||||||
return ret;
|
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,
|
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
|
||||||
QDict *options, Error **errp);
|
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] SPARSE "file-name.vmdk"
|
||||||
* RW [size in sectors] VMFS "file-name.vmdk"
|
* RW [size in sectors] VMFS "file-name.vmdk"
|
||||||
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
|
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
|
||||||
|
* RW [size in sectors] SESPARSE "file-name.vmdk"
|
||||||
*/
|
*/
|
||||||
flat_offset = -1;
|
flat_offset = -1;
|
||||||
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
|
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 ||
|
if (sectors <= 0 ||
|
||||||
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
|
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
|
||||||
strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
|
strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE") &&
|
||||||
|
strcmp(type, "SESPARSE")) ||
|
||||||
(strcmp(access, "RW"))) {
|
(strcmp(access, "RW"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -917,6 +1178,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
extent = &s->extents[s->num_extents - 1];
|
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 {
|
} else {
|
||||||
error_setg(errp, "Unsupported extent type '%s'", type);
|
error_setg(errp, "Unsupported extent type '%s'", type);
|
||||||
bdrv_unref_child(bs, extent_file);
|
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") &&
|
if (strcmp(ct, "monolithicFlat") &&
|
||||||
strcmp(ct, "vmfs") &&
|
strcmp(ct, "vmfs") &&
|
||||||
strcmp(ct, "vmfsSparse") &&
|
strcmp(ct, "vmfsSparse") &&
|
||||||
|
strcmp(ct, "seSparse") &&
|
||||||
strcmp(ct, "twoGbMaxExtentSparse") &&
|
strcmp(ct, "twoGbMaxExtentSparse") &&
|
||||||
strcmp(ct, "twoGbMaxExtentFlat")) {
|
strcmp(ct, "twoGbMaxExtentFlat")) {
|
||||||
error_setg(errp, "Unsupported image type '%s'", ct);
|
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;
|
unsigned int l1_index, l2_offset, l2_index;
|
||||||
int min_index, i, j;
|
int min_index, i, j;
|
||||||
uint32_t min_count, *l2_table;
|
uint32_t min_count;
|
||||||
|
void *l2_table;
|
||||||
bool zeroed = false;
|
bool zeroed = false;
|
||||||
int64_t ret;
|
int64_t ret;
|
||||||
int64_t cluster_sector;
|
int64_t cluster_sector;
|
||||||
|
unsigned int l2_size_bytes = extent->l2_size * extent->entry_size;
|
||||||
|
|
||||||
if (m_data) {
|
if (m_data) {
|
||||||
m_data->valid = 0;
|
m_data->valid = 0;
|
||||||
|
@ -1219,7 +1490,36 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||||
if (l1_index >= extent->l1_size) {
|
if (l1_index >= extent->l1_size) {
|
||||||
return VMDK_ERROR;
|
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) {
|
if (!l2_offset) {
|
||||||
return VMDK_UNALLOC;
|
return VMDK_UNALLOC;
|
||||||
}
|
}
|
||||||
|
@ -1231,7 +1531,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||||
extent->l2_cache_counts[j] >>= 1;
|
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;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1244,13 +1544,13 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||||
min_index = i;
|
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);
|
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
|
||||||
if (bdrv_pread(extent->file,
|
if (bdrv_pread(extent->file,
|
||||||
(int64_t)l2_offset * 512,
|
(int64_t)l2_offset * 512,
|
||||||
l2_table,
|
l2_table,
|
||||||
extent->l2_size * sizeof(uint32_t)
|
l2_size_bytes
|
||||||
) != extent->l2_size * sizeof(uint32_t)) {
|
) != l2_size_bytes) {
|
||||||
return VMDK_ERROR;
|
return VMDK_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,16 +1558,45 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||||
extent->l2_cache_counts[min_index] = 1;
|
extent->l2_cache_counts[min_index] = 1;
|
||||||
found:
|
found:
|
||||||
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
|
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) {
|
if (extent->sesparse) {
|
||||||
zeroed = true;
|
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 (!cluster_sector || zeroed) {
|
||||||
if (!allocate) {
|
if (!allocate) {
|
||||||
return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
|
return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
|
||||||
}
|
}
|
||||||
|
assert(!extent->sesparse);
|
||||||
|
|
||||||
if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) {
|
if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) {
|
||||||
return VMDK_ERROR;
|
return VMDK_ERROR;
|
||||||
|
@ -1291,7 +1620,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||||
m_data->l1_index = l1_index;
|
m_data->l1_index = l1_index;
|
||||||
m_data->l2_index = l2_index;
|
m_data->l2_index = l2_index;
|
||||||
m_data->l2_offset = l2_offset;
|
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;
|
*cluster_offset = cluster_sector << BDRV_SECTOR_BITS;
|
||||||
|
@ -1617,6 +1946,9 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||||
if (!extent) {
|
if (!extent) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
if (extent->sesparse) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
|
offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
|
||||||
n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE
|
n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE
|
||||||
- offset_in_cluster);
|
- offset_in_cluster);
|
||||||
|
|
|
@ -1774,7 +1774,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
||||||
backup = common->action->u.drive_backup.data;
|
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) {
|
if (!bs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,7 +472,7 @@ auth_pam=""
|
||||||
vte=""
|
vte=""
|
||||||
virglrenderer=""
|
virglrenderer=""
|
||||||
tpm=""
|
tpm=""
|
||||||
libssh2=""
|
libssh=""
|
||||||
live_block_migration="yes"
|
live_block_migration="yes"
|
||||||
numa=""
|
numa=""
|
||||||
tcmalloc="no"
|
tcmalloc="no"
|
||||||
|
@ -1439,9 +1439,9 @@ for opt do
|
||||||
;;
|
;;
|
||||||
--enable-tpm) tpm="yes"
|
--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"
|
--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)
|
coroutine-pool coroutine freelist (better performance)
|
||||||
glusterfs GlusterFS backend
|
glusterfs GlusterFS backend
|
||||||
tpm TPM support
|
tpm TPM support
|
||||||
libssh2 ssh block device support
|
libssh ssh block device support
|
||||||
numa libnuma support
|
numa libnuma support
|
||||||
libxml2 for Parallels image format
|
libxml2 for Parallels image format
|
||||||
tcmalloc tcmalloc support
|
tcmalloc tcmalloc support
|
||||||
|
@ -3914,43 +3914,34 @@ EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# libssh2 probe
|
# libssh probe
|
||||||
min_libssh2_version=1.2.8
|
if test "$libssh" != "no" ; then
|
||||||
if test "$libssh2" != "no" ; then
|
if $pkg_config --exists libssh; then
|
||||||
if $pkg_config --atleast-version=$min_libssh2_version libssh2; then
|
libssh_cflags=$($pkg_config libssh --cflags)
|
||||||
libssh2_cflags=$($pkg_config libssh2 --cflags)
|
libssh_libs=$($pkg_config libssh --libs)
|
||||||
libssh2_libs=$($pkg_config libssh2 --libs)
|
libssh=yes
|
||||||
libssh2=yes
|
|
||||||
else
|
else
|
||||||
if test "$libssh2" = "yes" ; then
|
if test "$libssh" = "yes" ; then
|
||||||
error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2"
|
error_exit "libssh required for --enable-libssh"
|
||||||
fi
|
fi
|
||||||
libssh2=no
|
libssh=no
|
||||||
fi
|
fi
|
||||||
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
|
cat > $TMPC <<EOF
|
||||||
#include <stdio.h>
|
#include <libssh/libssh.h>
|
||||||
#include <libssh2.h>
|
int main(void) { return ssh_get_server_publickey(NULL, NULL); }
|
||||||
#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;
|
|
||||||
}
|
|
||||||
EOF
|
EOF
|
||||||
# libssh2_cflags/libssh2_libs defined in previous test.
|
if compile_prog "$libssh_cflags" "$libssh_libs"; then
|
||||||
if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then
|
libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags"
|
||||||
QEMU_CFLAGS="-DHAS_LIBSSH2_SFTP_FSYNC $QEMU_CFLAGS"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -6451,7 +6442,7 @@ echo "GlusterFS support $glusterfs"
|
||||||
echo "gcov $gcov_tool"
|
echo "gcov $gcov_tool"
|
||||||
echo "gcov enabled $gcov"
|
echo "gcov enabled $gcov"
|
||||||
echo "TPM support $tpm"
|
echo "TPM support $tpm"
|
||||||
echo "libssh2 support $libssh2"
|
echo "libssh support $libssh"
|
||||||
echo "QOM debugging $qom_cast_debug"
|
echo "QOM debugging $qom_cast_debug"
|
||||||
echo "Live block migration $live_block_migration"
|
echo "Live block migration $live_block_migration"
|
||||||
echo "lzo support $lzo"
|
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
|
echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$libssh2" = "yes" ; then
|
if test "$libssh" = "yes" ; then
|
||||||
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
|
echo "CONFIG_LIBSSH=m" >> $config_host_mak
|
||||||
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
|
echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak
|
||||||
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
|
echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$live_block_migration" = "yes" ; then
|
if test "$live_block_migration" = "yes" ; then
|
||||||
|
|
|
@ -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
|
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.
|
supported.
|
||||||
|
|
||||||
@node disk_images_nvme
|
@node disk_images_nvme
|
||||||
|
|
|
@ -1384,7 +1384,6 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
|
||||||
n->bar.cap = 0;
|
n->bar.cap = 0;
|
||||||
NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
|
NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
|
||||||
NVME_CAP_SET_CQR(n->bar.cap, 1);
|
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_TO(n->bar.cap, 0xf);
|
||||||
NVME_CAP_SET_CSS(n->bar.cap, 1);
|
NVME_CAP_SET_CSS(n->bar.cap, 1);
|
||||||
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
|
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
|
||||||
|
|
|
@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
|
||||||
mxe-$TARGET-w64-mingw32.shared-curl \
|
mxe-$TARGET-w64-mingw32.shared-curl \
|
||||||
mxe-$TARGET-w64-mingw32.shared-glib \
|
mxe-$TARGET-w64-mingw32.shared-glib \
|
||||||
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
|
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
|
||||||
mxe-$TARGET-w64-mingw32.shared-libssh2 \
|
|
||||||
mxe-$TARGET-w64-mingw32.shared-libusb1 \
|
mxe-$TARGET-w64-mingw32.shared-libusb1 \
|
||||||
mxe-$TARGET-w64-mingw32.shared-lzo \
|
mxe-$TARGET-w64-mingw32.shared-lzo \
|
||||||
mxe-$TARGET-w64-mingw32.shared-nettle \
|
mxe-$TARGET-w64-mingw32.shared-nettle \
|
||||||
|
|
|
@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
|
||||||
mxe-$TARGET-w64-mingw32.shared-curl \
|
mxe-$TARGET-w64-mingw32.shared-curl \
|
||||||
mxe-$TARGET-w64-mingw32.shared-glib \
|
mxe-$TARGET-w64-mingw32.shared-glib \
|
||||||
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
|
mxe-$TARGET-w64-mingw32.shared-libgcrypt \
|
||||||
mxe-$TARGET-w64-mingw32.shared-libssh2 \
|
|
||||||
mxe-$TARGET-w64-mingw32.shared-libusb1 \
|
mxe-$TARGET-w64-mingw32.shared-libusb1 \
|
||||||
mxe-$TARGET-w64-mingw32.shared-lzo \
|
mxe-$TARGET-w64-mingw32.shared-lzo \
|
||||||
mxe-$TARGET-w64-mingw32.shared-nettle \
|
mxe-$TARGET-w64-mingw32.shared-nettle \
|
||||||
|
|
|
@ -35,7 +35,7 @@ ENV PACKAGES \
|
||||||
libpng-devel \
|
libpng-devel \
|
||||||
librbd-devel \
|
librbd-devel \
|
||||||
libseccomp-devel \
|
libseccomp-devel \
|
||||||
libssh2-devel \
|
libssh-devel \
|
||||||
libubsan \
|
libubsan \
|
||||||
libusbx-devel \
|
libusbx-devel \
|
||||||
libxml2-devel \
|
libxml2-devel \
|
||||||
|
@ -50,7 +50,6 @@ ENV PACKAGES \
|
||||||
mingw32-gtk3 \
|
mingw32-gtk3 \
|
||||||
mingw32-libjpeg-turbo \
|
mingw32-libjpeg-turbo \
|
||||||
mingw32-libpng \
|
mingw32-libpng \
|
||||||
mingw32-libssh2 \
|
|
||||||
mingw32-libtasn1 \
|
mingw32-libtasn1 \
|
||||||
mingw32-nettle \
|
mingw32-nettle \
|
||||||
mingw32-pixman \
|
mingw32-pixman \
|
||||||
|
@ -64,7 +63,6 @@ ENV PACKAGES \
|
||||||
mingw64-gtk3 \
|
mingw64-gtk3 \
|
||||||
mingw64-libjpeg-turbo \
|
mingw64-libjpeg-turbo \
|
||||||
mingw64-libpng \
|
mingw64-libpng \
|
||||||
mingw64-libssh2 \
|
|
||||||
mingw64-libtasn1 \
|
mingw64-libtasn1 \
|
||||||
mingw64-nettle \
|
mingw64-nettle \
|
||||||
mingw64-pixman \
|
mingw64-pixman \
|
||||||
|
|
|
@ -53,7 +53,7 @@ ENV PACKAGES flex bison \
|
||||||
libsnappy-dev \
|
libsnappy-dev \
|
||||||
libspice-protocol-dev \
|
libspice-protocol-dev \
|
||||||
libspice-server-dev \
|
libspice-server-dev \
|
||||||
libssh2-1-dev \
|
libssh-dev \
|
||||||
libusb-1.0-0-dev \
|
libusb-1.0-0-dev \
|
||||||
libusbredirhost-dev \
|
libusbredirhost-dev \
|
||||||
libvdeplug-dev \
|
libvdeplug-dev \
|
||||||
|
|
|
@ -40,7 +40,7 @@ ENV PACKAGES flex bison \
|
||||||
libsnappy-dev \
|
libsnappy-dev \
|
||||||
libspice-protocol-dev \
|
libspice-protocol-dev \
|
||||||
libspice-server-dev \
|
libspice-server-dev \
|
||||||
libssh2-1-dev \
|
libssh-dev \
|
||||||
libusb-1.0-0-dev \
|
libusb-1.0-0-dev \
|
||||||
libusbredirhost-dev \
|
libusbredirhost-dev \
|
||||||
libvdeplug-dev \
|
libvdeplug-dev \
|
||||||
|
|
|
@ -2358,5 +2358,5 @@ Offset Length Mapped to File
|
||||||
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
|
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
|
||||||
|
|
||||||
=== Testing afl image with a very large capacity ===
|
=== 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
|
*** done
|
||||||
|
|
|
@ -56,6 +56,15 @@ echo
|
||||||
echo "== reading whole image =="
|
echo "== reading whole image =="
|
||||||
$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
$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
|
||||||
echo "== rewriting whole image =="
|
echo "== rewriting whole image =="
|
||||||
$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
||||||
|
|
|
@ -5,6 +5,16 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.
|
||||||
read 134217728/134217728 bytes at offset 0
|
read 134217728/134217728 bytes at offset 0
|
||||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
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 ==
|
== rewriting whole image ==
|
||||||
wrote 134217728/134217728 bytes at offset 0
|
wrote 134217728/134217728 bytes at offset 0
|
||||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
|
@ -24,7 +24,7 @@ import iotests
|
||||||
import time
|
import time
|
||||||
from iotests import qemu_img_create, qemu_io, filter_qemu_io, QemuIoInteractive
|
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
|
nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock
|
||||||
disk = os.path.join(iotests.test_dir, 'disk')
|
disk = os.path.join(iotests.test_dir, 'disk')
|
||||||
|
|
||||||
|
|
|
@ -110,12 +110,49 @@ with iotests.FilePath('t.img') as disk_path, \
|
||||||
|
|
||||||
iotests.img_info_log(remote_path)
|
iotests.img_info_log(remote_path)
|
||||||
|
|
||||||
md5_key = subprocess.check_output(
|
keys = subprocess.check_output(
|
||||||
'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
|
'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
|
||||||
'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1',
|
'cut -d" " -f3',
|
||||||
shell=True).rstrip().decode('ascii')
|
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()
|
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',
|
blockdev_create(vm, { 'driver': 'ssh',
|
||||||
'location': {
|
'location': {
|
||||||
'path': disk_path,
|
'path': disk_path,
|
||||||
|
@ -140,7 +177,7 @@ with iotests.FilePath('t.img') as disk_path, \
|
||||||
'host-key-check': {
|
'host-key-check': {
|
||||||
'mode': 'hash',
|
'mode': 'hash',
|
||||||
'type': 'md5',
|
'type': 'md5',
|
||||||
'hash': md5_key,
|
'hash': md5_keys[matching_key],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'size': 8388608 })
|
'size': 8388608 })
|
||||||
|
@ -148,11 +185,6 @@ with iotests.FilePath('t.img') as disk_path, \
|
||||||
|
|
||||||
iotests.img_info_log(remote_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()
|
vm.launch()
|
||||||
blockdev_create(vm, { 'driver': 'ssh',
|
blockdev_create(vm, { 'driver': 'ssh',
|
||||||
'location': {
|
'location': {
|
||||||
|
@ -178,7 +210,7 @@ with iotests.FilePath('t.img') as disk_path, \
|
||||||
'host-key-check': {
|
'host-key-check': {
|
||||||
'mode': 'hash',
|
'mode': 'hash',
|
||||||
'type': 'sha1',
|
'type': 'sha1',
|
||||||
'hash': sha1_key,
|
'hash': sha1_keys[matching_key],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'size': 4194304 })
|
'size': 4194304 })
|
||||||
|
|
|
@ -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}}}
|
{"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": {}}
|
{"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"}}
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue