mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Tue 23 Jan 2018 12:38:36 GMT # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (29 commits) iotests: Disable some tests for compat=0.10 iotests: Split 177 into two parts for compat=0.10 iotests: Make 059 pass on machines with little RAM iotests: Filter compat-dependent info in 198 iotests: Make 191 work with qcow2 options iotests: Make 184 image-less iotests: Make 089 compatible with compat=0.10 iotests: Fix 067 for compat=0.10 iotests: Fix 059's reference output iotests: Fix 051 for compat=0.10 iotests: Fix 020 for vmdk iotests: Skip 103 for refcount_bits=1 iotests: Forbid 020 for non-file protocols iotests: Drop format-specific in _filter_img_info iotests: Fix _img_info for backslashes block/vmdk: Add blkdebug events block/qcow: Add blkdebug events qcow2: No persistent dirty bitmaps for compat=0.10 block/vmdk: Fix , instead of ; at end of line qemu-iotests: Fix locking issue in 102 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -379,6 +379,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
/* update the L1 entry */
|
||||
s->l1_table[l1_index] = l2_offset;
|
||||
tmp = cpu_to_be64(l2_offset);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
|
||||
ret = bdrv_pwrite_sync(bs->file,
|
||||
s->l1_table_offset + l1_index * sizeof(tmp),
|
||||
&tmp, sizeof(tmp));
|
||||
@@ -409,6 +410,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
l2_table = s->l2_cache + (min_index << s->l2_bits);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
|
||||
if (new_l2_table) {
|
||||
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
|
||||
ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
|
||||
@@ -432,6 +434,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
|
||||
if (!allocate)
|
||||
return 0;
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
|
||||
/* allocate a new cluster */
|
||||
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
|
||||
(n_end - n_start) < s->cluster_sectors) {
|
||||
@@ -447,6 +450,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
}
|
||||
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
|
||||
/* write the cluster content */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
|
||||
s->cluster_size);
|
||||
if (ret < 0) {
|
||||
@@ -486,6 +490,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
NULL) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
ret = bdrv_pwrite(bs->file,
|
||||
cluster_offset + i * 512,
|
||||
s->cluster_data, 512);
|
||||
@@ -503,6 +508,11 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
/* update L2 table */
|
||||
tmp = cpu_to_be64(cluster_offset);
|
||||
l2_table[l2_index] = tmp;
|
||||
if (allocate == 2) {
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
|
||||
} else {
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
|
||||
}
|
||||
ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
|
||||
&tmp, sizeof(tmp));
|
||||
if (ret < 0) {
|
||||
@@ -579,6 +589,7 @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
|
||||
if (s->cluster_cache_offset != coffset) {
|
||||
csize = cluster_offset >> (63 - s->cluster_bits);
|
||||
csize &= (s->cluster_size - 1);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
|
||||
ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
|
||||
if (ret != csize)
|
||||
return -1;
|
||||
@@ -635,6 +646,8 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
/* qcow2 emits this on bs->file instead of bs->backing */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
if (ret < 0) {
|
||||
@@ -661,6 +674,7 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||
ret = bdrv_co_readv(bs->file,
|
||||
(cluster_offset >> 9) + index_in_cluster,
|
||||
n, &hd_qiov);
|
||||
@@ -754,6 +768,7 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
ret = bdrv_co_writev(bs->file,
|
||||
(cluster_offset >> 9) + index_in_cluster,
|
||||
n, &hd_qiov);
|
||||
@@ -1048,6 +1063,7 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
.iov_len = out_len,
|
||||
};
|
||||
qemu_iovec_init_external(&hd_qiov, &iov, 1);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
|
||||
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
|
||||
@@ -1449,6 +1449,16 @@ bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
|
||||
bool found;
|
||||
Qcow2BitmapList *bm_list;
|
||||
|
||||
if (s->qcow_version < 3) {
|
||||
/* Without autoclear_features, we would always have to assume
|
||||
* that a program without persistent dirty bitmap support has
|
||||
* accessed this qcow2 file when opening it, and would thus
|
||||
* have to drop all dirty bitmaps (defeating their purpose).
|
||||
*/
|
||||
error_setg(errp, "Cannot store dirty bitmaps in qcow2 v2 files");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (check_constraints_on_bitmap(bs, name, granularity, errp) != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+58
-12
@@ -1508,7 +1508,7 @@ enum {
|
||||
static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
void **refcount_table,
|
||||
int64_t *refcount_table_size, int64_t l2_offset,
|
||||
int flags)
|
||||
int flags, BdrvCheckMode fix)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t *l2_table, l2_entry;
|
||||
@@ -1579,6 +1579,57 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
next_contiguous_offset = offset + s->cluster_size;
|
||||
}
|
||||
|
||||
/* Correct offsets are cluster aligned */
|
||||
if (offset_into_cluster(s, offset)) {
|
||||
if (qcow2_get_cluster_type(l2_entry) ==
|
||||
QCOW2_CLUSTER_ZERO_ALLOC)
|
||||
{
|
||||
fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero "
|
||||
"cluster is not properly aligned; L2 entry "
|
||||
"corrupted.\n",
|
||||
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
|
||||
offset);
|
||||
if (fix & BDRV_FIX_ERRORS) {
|
||||
uint64_t l2e_offset =
|
||||
l2_offset + (uint64_t)i * sizeof(uint64_t);
|
||||
|
||||
l2_entry = QCOW_OFLAG_ZERO;
|
||||
l2_table[i] = cpu_to_be64(l2_entry);
|
||||
ret = qcow2_pre_write_overlap_check(bs,
|
||||
QCOW2_OL_ACTIVE_L2 | QCOW2_OL_INACTIVE_L2,
|
||||
l2e_offset, sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: Overlap check failed\n");
|
||||
res->check_errors++;
|
||||
/* Something is seriously wrong, so abort checking
|
||||
* this L2 table */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file, l2e_offset,
|
||||
&l2_table[i], sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: Failed to overwrite L2 "
|
||||
"table entry: %s\n", strerror(-ret));
|
||||
res->check_errors++;
|
||||
/* Do not abort, continue checking the rest of this
|
||||
* L2 table's entries */
|
||||
} else {
|
||||
res->corruptions_fixed++;
|
||||
/* Skip marking the cluster as used
|
||||
* (it is unused now) */
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
res->corruptions++;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR offset=%" PRIx64 ": Data cluster is "
|
||||
"not properly aligned; L2 entry corrupted.\n", offset);
|
||||
res->corruptions++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark cluster as used */
|
||||
ret = qcow2_inc_refcounts_imrt(bs, res,
|
||||
refcount_table, refcount_table_size,
|
||||
@@ -1586,13 +1637,6 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Correct offsets are cluster aligned */
|
||||
if (offset_into_cluster(s, offset)) {
|
||||
fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
|
||||
"properly aligned; L2 entry corrupted.\n", offset);
|
||||
res->corruptions++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1626,7 +1670,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
|
||||
void **refcount_table,
|
||||
int64_t *refcount_table_size,
|
||||
int64_t l1_table_offset, int l1_size,
|
||||
int flags)
|
||||
int flags, BdrvCheckMode fix)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t *l1_table = NULL, l2_offset, l1_size2;
|
||||
@@ -1681,7 +1725,8 @@ static int check_refcounts_l1(BlockDriverState *bs,
|
||||
|
||||
/* Process and check L2 entries */
|
||||
ret = check_refcounts_l2(bs, res, refcount_table,
|
||||
refcount_table_size, l2_offset, flags);
|
||||
refcount_table_size, l2_offset, flags,
|
||||
fix);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1957,7 +2002,8 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
|
||||
/* current L1 table */
|
||||
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
|
||||
s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO);
|
||||
s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO,
|
||||
fix);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -1966,7 +2012,7 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
for (i = 0; i < s->nb_snapshots; i++) {
|
||||
sn = s->snapshots + i;
|
||||
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
|
||||
sn->l1_table_offset, sn->l1_size, 0);
|
||||
sn->l1_table_offset, sn->l1_size, 0, fix);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+11
-3
@@ -302,9 +302,17 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
}
|
||||
|
||||
if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) {
|
||||
warn_report("a program lacking bitmap support "
|
||||
"modified this file, so all bitmaps are now "
|
||||
"considered inconsistent");
|
||||
if (s->qcow_version < 3) {
|
||||
/* Let's be a bit more specific */
|
||||
warn_report("This qcow2 v2 image contains bitmaps, but "
|
||||
"they may have been modified by a program "
|
||||
"without persistent bitmap support; so now "
|
||||
"they must all be considered inconsistent");
|
||||
} else {
|
||||
warn_report("a program lacking bitmap support "
|
||||
"modified this file, so all bitmaps are now "
|
||||
"considered inconsistent");
|
||||
}
|
||||
error_printf("Some clusters may be leaked, "
|
||||
"run 'qemu-img check -r' on the image "
|
||||
"file to fix.");
|
||||
|
||||
+17
-1
@@ -1075,6 +1075,8 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
/* Read backing data before skip range */
|
||||
if (skip_start_bytes > 0) {
|
||||
if (bs->backing) {
|
||||
/* qcow2 emits this on bs->file instead of bs->backing */
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
|
||||
ret = bdrv_pread(bs->backing, offset, whole_grain,
|
||||
skip_start_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1082,6 +1084,7 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
|
||||
ret = bdrv_pwrite(extent->file, cluster_offset, whole_grain,
|
||||
skip_start_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1092,6 +1095,8 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
/* Read backing data after skip range */
|
||||
if (skip_end_bytes < cluster_bytes) {
|
||||
if (bs->backing) {
|
||||
/* qcow2 emits this on bs->file instead of bs->backing */
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
|
||||
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
|
||||
whole_grain + skip_end_bytes,
|
||||
cluster_bytes - skip_end_bytes);
|
||||
@@ -1100,6 +1105,7 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
|
||||
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
|
||||
whole_grain + skip_end_bytes,
|
||||
cluster_bytes - skip_end_bytes);
|
||||
@@ -1120,6 +1126,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
|
||||
{
|
||||
offset = cpu_to_le32(offset);
|
||||
/* update L2 table */
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
|
||||
if (bdrv_pwrite_sync(extent->file,
|
||||
((int64_t)m_data->l2_offset * 512)
|
||||
+ (m_data->l2_index * sizeof(offset)),
|
||||
@@ -1218,6 +1225,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
l2_table = extent->l2_cache + (min_index * extent->l2_size);
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
|
||||
if (bdrv_pread(extent->file,
|
||||
(int64_t)l2_offset * 512,
|
||||
l2_table,
|
||||
@@ -1393,12 +1401,16 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
.iov_len = n_bytes,
|
||||
};
|
||||
qemu_iovec_init_external(&local_qiov, &iov, 1);
|
||||
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED);
|
||||
} else {
|
||||
qemu_iovec_init(&local_qiov, qiov->niov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, qiov_offset, n_bytes);
|
||||
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_WRITE_AIO);
|
||||
}
|
||||
|
||||
write_offset = cluster_offset + offset_in_cluster,
|
||||
write_offset = cluster_offset + offset_in_cluster;
|
||||
ret = bdrv_co_pwritev(extent->file, write_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
|
||||
@@ -1437,6 +1449,7 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
|
||||
|
||||
if (!extent->compressed) {
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_READ_AIO);
|
||||
ret = bdrv_co_preadv(extent->file,
|
||||
cluster_offset + offset_in_cluster, bytes,
|
||||
qiov, 0);
|
||||
@@ -1450,6 +1463,7 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
buf_bytes = cluster_bytes * 2;
|
||||
cluster_buf = g_malloc(buf_bytes);
|
||||
uncomp_buf = g_malloc(cluster_bytes);
|
||||
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
|
||||
ret = bdrv_pread(extent->file,
|
||||
cluster_offset,
|
||||
cluster_buf, buf_bytes);
|
||||
@@ -1527,6 +1541,8 @@ vmdk_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
/* qcow2 emits this on bs->file instead of bs->backing */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
ret = bdrv_co_preadv(bs->backing, offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
if (ret < 0) {
|
||||
|
||||
+23
-7
@@ -60,6 +60,11 @@ static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
|
||||
|
||||
static int do_open_tray(const char *blk_name, const char *qdev_id,
|
||||
bool force, Error **errp);
|
||||
static void blockdev_remove_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id, Error **errp);
|
||||
static void blockdev_insert_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id,
|
||||
const char *node_name, Error **errp);
|
||||
|
||||
static const char *const if_name[IF_COUNT] = {
|
||||
[IF_NONE] = "none",
|
||||
@@ -2323,7 +2328,7 @@ void qmp_eject(bool has_device, const char *device,
|
||||
}
|
||||
error_free(local_err);
|
||||
|
||||
qmp_x_blockdev_remove_medium(has_device, device, has_id, id, errp);
|
||||
blockdev_remove_medium(has_device, device, has_id, id, errp);
|
||||
}
|
||||
|
||||
void qmp_block_passwd(bool has_device, const char *device,
|
||||
@@ -2446,8 +2451,8 @@ void qmp_blockdev_close_tray(bool has_device, const char *device,
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_remove_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id, Error **errp)
|
||||
static void blockdev_remove_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id, Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
@@ -2503,6 +2508,11 @@ out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
void qmp_blockdev_remove_medium(const char *id, Error **errp)
|
||||
{
|
||||
blockdev_remove_medium(false, NULL, true, id, errp);
|
||||
}
|
||||
|
||||
static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||
BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
@@ -2548,9 +2558,9 @@ static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_insert_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id,
|
||||
const char *node_name, Error **errp)
|
||||
static void blockdev_insert_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id,
|
||||
const char *node_name, Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
@@ -2576,6 +2586,12 @@ void qmp_x_blockdev_insert_medium(bool has_device, const char *device,
|
||||
qmp_blockdev_insert_anon_medium(blk, bs, errp);
|
||||
}
|
||||
|
||||
void qmp_blockdev_insert_medium(const char *id, const char *node_name,
|
||||
Error **errp)
|
||||
{
|
||||
blockdev_insert_medium(false, NULL, true, id, node_name, errp);
|
||||
}
|
||||
|
||||
void qmp_blockdev_change_medium(bool has_device, const char *device,
|
||||
bool has_id, const char *id,
|
||||
const char *filename,
|
||||
@@ -2650,7 +2666,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
|
||||
qmp_x_blockdev_remove_medium(has_device, device, has_id, id, &err);
|
||||
blockdev_remove_medium(has_device, device, has_id, id, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
goto fail;
|
||||
|
||||
+34
-5
@@ -91,7 +91,19 @@ static uint8_t nvme_sq_empty(NvmeSQueue *sq)
|
||||
return sq->head == sq->tail;
|
||||
}
|
||||
|
||||
static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
|
||||
static void nvme_irq_check(NvmeCtrl *n)
|
||||
{
|
||||
if (msix_enabled(&(n->parent_obj))) {
|
||||
return;
|
||||
}
|
||||
if (~n->bar.intms & n->irq_status) {
|
||||
pci_irq_assert(&n->parent_obj);
|
||||
} else {
|
||||
pci_irq_deassert(&n->parent_obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq)
|
||||
{
|
||||
if (cq->irq_enabled) {
|
||||
if (msix_enabled(&(n->parent_obj))) {
|
||||
@@ -99,13 +111,28 @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
|
||||
msix_notify(&(n->parent_obj), cq->vector);
|
||||
} else {
|
||||
trace_nvme_irq_pin();
|
||||
pci_irq_pulse(&n->parent_obj);
|
||||
assert(cq->cqid < 64);
|
||||
n->irq_status |= 1 << cq->cqid;
|
||||
nvme_irq_check(n);
|
||||
}
|
||||
} else {
|
||||
trace_nvme_irq_masked();
|
||||
}
|
||||
}
|
||||
|
||||
static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq)
|
||||
{
|
||||
if (cq->irq_enabled) {
|
||||
if (msix_enabled(&(n->parent_obj))) {
|
||||
return;
|
||||
} else {
|
||||
assert(cq->cqid < 64);
|
||||
n->irq_status &= ~(1 << cq->cqid);
|
||||
nvme_irq_check(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
|
||||
uint64_t prp2, uint32_t len, NvmeCtrl *n)
|
||||
{
|
||||
@@ -242,7 +269,7 @@ static void nvme_post_cqes(void *opaque)
|
||||
sizeof(req->cqe));
|
||||
QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
|
||||
}
|
||||
nvme_isr_notify(n, cq);
|
||||
nvme_irq_assert(n, cq);
|
||||
}
|
||||
|
||||
static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
|
||||
@@ -905,6 +932,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||
n->bar.intmc = n->bar.intms;
|
||||
trace_nvme_mmio_intm_set(data & 0xffffffff,
|
||||
n->bar.intmc);
|
||||
nvme_irq_check(n);
|
||||
break;
|
||||
case 0x10: /* INTMC */
|
||||
if (unlikely(msix_enabled(&(n->parent_obj)))) {
|
||||
@@ -917,6 +945,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||
n->bar.intmc = n->bar.intms;
|
||||
trace_nvme_mmio_intm_clr(data & 0xffffffff,
|
||||
n->bar.intmc);
|
||||
nvme_irq_check(n);
|
||||
break;
|
||||
case 0x14: /* CC */
|
||||
trace_nvme_mmio_cfg(data & 0xffffffff);
|
||||
@@ -1085,8 +1114,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
|
||||
timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
|
||||
}
|
||||
|
||||
if (cq->tail != cq->head) {
|
||||
nvme_isr_notify(n, cq);
|
||||
if (cq->tail == cq->head) {
|
||||
nvme_irq_deassert(n, cq);
|
||||
}
|
||||
} else {
|
||||
/* Submission queue doorbell write */
|
||||
|
||||
@@ -775,6 +775,7 @@ typedef struct NvmeCtrl {
|
||||
uint32_t cmbsz;
|
||||
uint32_t cmbloc;
|
||||
uint8_t *cmbuf;
|
||||
uint64_t irq_status;
|
||||
|
||||
char *serial;
|
||||
NvmeNamespace *namespaces;
|
||||
|
||||
+15
-27
@@ -3421,7 +3421,7 @@
|
||||
'*id': 'str' } }
|
||||
|
||||
##
|
||||
# @x-blockdev-remove-medium:
|
||||
# @blockdev-remove-medium:
|
||||
#
|
||||
# Removes a medium (a block driver state tree) from a block device. That block
|
||||
# device's tray must currently be open (unless there is no attached guest
|
||||
@@ -3429,18 +3429,13 @@
|
||||
#
|
||||
# If the tray is open and there is no medium inserted, this will be a no-op.
|
||||
#
|
||||
# @device: Block device name (deprecated, use @id instead)
|
||||
# @id: The name or QOM path of the guest device
|
||||
#
|
||||
# @id: The name or QOM path of the guest device (since: 2.8)
|
||||
#
|
||||
# Note: This command is still a work in progress and is considered experimental.
|
||||
# Stay away from it unless you want to help with its development.
|
||||
#
|
||||
# Since: 2.5
|
||||
# Since: 2.12
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "x-blockdev-remove-medium",
|
||||
# -> { "execute": "blockdev-remove-medium",
|
||||
# "arguments": { "id": "ide0-1-0" } }
|
||||
#
|
||||
# <- { "error": { "class": "GenericError",
|
||||
@@ -3458,33 +3453,27 @@
|
||||
#
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# -> { "execute": "x-blockdev-remove-medium",
|
||||
# -> { "execute": "blockdev-remove-medium",
|
||||
# "arguments": { "id": "ide0-1-0" } }
|
||||
#
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'x-blockdev-remove-medium',
|
||||
'data': { '*device': 'str',
|
||||
'*id': 'str' } }
|
||||
{ 'command': 'blockdev-remove-medium',
|
||||
'data': { 'id': 'str' } }
|
||||
|
||||
##
|
||||
# @x-blockdev-insert-medium:
|
||||
# @blockdev-insert-medium:
|
||||
#
|
||||
# Inserts a medium (a block driver state tree) into a block device. That block
|
||||
# device's tray must currently be open (unless there is no attached guest
|
||||
# device) and there must be no medium inserted already.
|
||||
#
|
||||
# @device: Block device name (deprecated, use @id instead)
|
||||
#
|
||||
# @id: The name or QOM path of the guest device (since: 2.8)
|
||||
# @id: The name or QOM path of the guest device
|
||||
#
|
||||
# @node-name: name of a node in the block driver state graph
|
||||
#
|
||||
# Note: This command is still a work in progress and is considered experimental.
|
||||
# Stay away from it unless you want to help with its development.
|
||||
#
|
||||
# Since: 2.5
|
||||
# Since: 2.12
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
@@ -3496,16 +3485,15 @@
|
||||
# "filename": "fedora.iso" } } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# -> { "execute": "x-blockdev-insert-medium",
|
||||
# -> { "execute": "blockdev-insert-medium",
|
||||
# "arguments": { "id": "ide0-1-0",
|
||||
# "node-name": "node0" } }
|
||||
#
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'x-blockdev-insert-medium',
|
||||
'data': { '*device': 'str',
|
||||
'*id': 'str',
|
||||
{ 'command': 'blockdev-insert-medium',
|
||||
'data': { 'id': 'str',
|
||||
'node-name': 'str'} }
|
||||
|
||||
|
||||
@@ -3533,8 +3521,8 @@
|
||||
#
|
||||
# Changes the medium inserted into a block device by ejecting the current medium
|
||||
# and loading a new image file which is inserted as the new medium (this command
|
||||
# combines blockdev-open-tray, x-blockdev-remove-medium,
|
||||
# x-blockdev-insert-medium and blockdev-close-tray).
|
||||
# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
|
||||
# and blockdev-close-tray).
|
||||
#
|
||||
# @device: Block device name (deprecated, use @id instead)
|
||||
#
|
||||
|
||||
@@ -18,6 +18,7 @@ test-aio
|
||||
test-aio-multithread
|
||||
test-arm-mptimer
|
||||
test-base64
|
||||
test-bdrv-drain
|
||||
test-bitops
|
||||
test-bitcnt
|
||||
test-blockjob
|
||||
|
||||
+8
-8
@@ -1578,9 +1578,9 @@ static void test_atapi_tray(void)
|
||||
QDict *rsp;
|
||||
|
||||
fd = prepare_iso(iso_size, &tx, &iso);
|
||||
ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,format=raw "
|
||||
ahci = ahci_boot_and_enable("-blockdev node-name=drive0,driver=file,filename=%s "
|
||||
"-M q35 "
|
||||
"-device ide-cd,drive=drive0 ", iso);
|
||||
"-device ide-cd,id=cd0,drive=drive0 ", iso);
|
||||
port = ahci_port_select(ahci);
|
||||
|
||||
ahci_atapi_eject(ahci, port);
|
||||
@@ -1591,13 +1591,13 @@ static void test_atapi_tray(void)
|
||||
|
||||
/* Remove media */
|
||||
qmp_async("{'execute': 'blockdev-open-tray', "
|
||||
"'arguments': {'device': 'drive0'}}");
|
||||
"'arguments': {'id': 'cd0'}}");
|
||||
atapi_wait_tray(true);
|
||||
rsp = qmp_receive();
|
||||
QDECREF(rsp);
|
||||
|
||||
qmp_discard_response("{'execute': 'x-blockdev-remove-medium', "
|
||||
"'arguments': {'device': 'drive0'}}");
|
||||
qmp_discard_response("{'execute': 'blockdev-remove-medium', "
|
||||
"'arguments': {'id': 'cd0'}}");
|
||||
|
||||
/* Test the tray without a medium */
|
||||
ahci_atapi_load(ahci, port);
|
||||
@@ -1612,13 +1612,13 @@ static void test_atapi_tray(void)
|
||||
"'driver': 'raw', "
|
||||
"'file': { 'driver': 'file', "
|
||||
"'filename': %s }}}", iso);
|
||||
qmp_discard_response("{'execute': 'x-blockdev-insert-medium',"
|
||||
"'arguments': { 'device': 'drive0', "
|
||||
qmp_discard_response("{'execute': 'blockdev-insert-medium',"
|
||||
"'arguments': { 'id': 'cd0', "
|
||||
"'node-name': 'node0' }}");
|
||||
|
||||
/* Again, the event shows up first */
|
||||
qmp_async("{'execute': 'blockdev-close-tray', "
|
||||
"'arguments': {'device': 'drive0'}}");
|
||||
"'arguments': {'id': 'cd0'}}");
|
||||
atapi_wait_tray(false);
|
||||
rsp = qmp_receive();
|
||||
QDECREF(rsp);
|
||||
|
||||
+7
-10
@@ -42,18 +42,12 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# Any format supporting backing files
|
||||
_supported_fmt qcow qcow2 vmdk qed
|
||||
_supported_proto generic
|
||||
_unsupported_proto vxhs
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||
"subformat=twoGbMaxExtentFlat" \
|
||||
"subformat=twoGbMaxExtentSparse"
|
||||
|
||||
# NFS does not support bdrv_reopen_prepare thus qemu-img commit fails.
|
||||
if [ "$IMGPROTO" = "nfs" ]; then
|
||||
_notrun "image protocol $IMGPROTO does not support bdrv_commit"
|
||||
fi
|
||||
|
||||
TEST_OFFSETS="0 4294967296"
|
||||
|
||||
TEST_IMG_SAVE="$TEST_IMG"
|
||||
@@ -117,10 +111,12 @@ echo
|
||||
echo 'Testing failing commit'
|
||||
echo
|
||||
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img 1M
|
||||
|
||||
# Create an image with a null backing file to which committing will fail (with
|
||||
# ENOSPC so we can distinguish the result from some generic EIO which may be
|
||||
# generated anywhere in the block layer)
|
||||
_make_test_img -b "json:{'driver': 'raw',
|
||||
_make_test_img -b "json:{'driver': '$IMGFMT',
|
||||
'file': {
|
||||
'driver': 'blkdebug',
|
||||
'inject-error': [{
|
||||
@@ -129,14 +125,15 @@ _make_test_img -b "json:{'driver': 'raw',
|
||||
'once': true
|
||||
}],
|
||||
'image': {
|
||||
'driver': 'null-co'
|
||||
'driver': 'file',
|
||||
'filename': '$TEST_IMG.base'
|
||||
}}}"
|
||||
|
||||
# Just write anything so committing will not be a no-op
|
||||
$QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
$QEMU_IMG commit "$TEST_IMG"
|
||||
_cleanup_test_img
|
||||
_cleanup
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
|
||||
@@ -1078,7 +1078,8 @@ No errors were found on the image.
|
||||
|
||||
Testing failing commit
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=json:{'driver': 'raw',,
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driver': 'IMGFMT',,
|
||||
'file': {
|
||||
'driver': 'blkdebug',,
|
||||
'inject-error': [{
|
||||
@@ -1087,7 +1088,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=json:{'d
|
||||
'once': true
|
||||
}],,
|
||||
'image': {
|
||||
'driver': 'null-co'
|
||||
'driver': 'file',,
|
||||
'filename': 'TEST_DIR/t.IMGFMT.base'
|
||||
}}}
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
@@ -131,6 +131,8 @@ echo
|
||||
echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
|
||||
echo
|
||||
|
||||
_make_test_img -o compat=1.1 "$size"
|
||||
|
||||
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
|
||||
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
|
||||
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=
|
||||
|
||||
@@ -77,6 +77,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
|
||||
|
||||
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) quit
|
||||
|
||||
@@ -77,6 +77,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
|
||||
|
||||
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) quit
|
||||
|
||||
@@ -152,7 +152,9 @@ done
|
||||
echo
|
||||
echo "=== Testing afl image with a very large capacity ==="
|
||||
_use_sample_img afl9.vmdk.bz2
|
||||
_img_info
|
||||
# The sed makes this test pass on machines with little RAM
|
||||
# (and also with 32 bit builds)
|
||||
_img_info | sed -e 's/Cannot allocate memory/Invalid argument/'
|
||||
_cleanup_test_img
|
||||
|
||||
# success, all done
|
||||
|
||||
@@ -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': Could not open 'TEST_DIR/afl9.IMGFMT': Invalid argument
|
||||
*** done
|
||||
|
||||
@@ -335,7 +335,8 @@ poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x00\x2a\x01"
|
||||
# Let's write to it!
|
||||
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# Can't repair this yet (TODO: We can just deallocate the cluster)
|
||||
echo '--- Repairing ---'
|
||||
_check_test_img -r all
|
||||
|
||||
echo
|
||||
echo '=== Discarding with an unaligned refblock ==='
|
||||
|
||||
@@ -317,6 +317,15 @@ discard 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
|
||||
write failed: Input/output error
|
||||
--- Repairing ---
|
||||
Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted.
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
|
||||
=== Discarding with an unaligned refblock ===
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user