mirror of https://github.com/xemu-project/xemu.git
Block layer patches
- Event throttling for BLOCK_IO_ERROR - iotests: Fix backup-discard-source test for XFS - Coverity fixes - raw-format: Fix error message for invalid offset/size -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmcX1wQRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9aWKA//cyG+Q3EXLouSu2Ob04RArX8HgAzLmHL3 Fx9x6BbDtusPfzxKVLqhJhJ5/oRyk0QWkdZKGNSxinLD3DBJ6q6FMNaWhuvzOBcy iHnWlMfwEIBl5vFJwM5Q/d7F2afOUiVSeR7E4TQn063cBo96qIrAD7DRLM01jBEN d9+9nkBruwgmxZJIr3WTsqjDoTqflcjxA6Adp/WkzVXBMMYqcsuReXQtrgfFooKw yhjkHq5nFKzebvK+BLjA0ytuvUlsRqLYDXN+bAk/rC6oCgbzygAjNwL5kUEYnV1r lVRSOxRUlet4v2GFCvplxw5tX3aJzlWB50v7d+oaBYR72htTtPeIZzadBJySdtSk DxEUR5kTcGK/vSI+WOapTVK+qU+Wr+6lFwGOL0zEYZyfvpyoFwfAlkjAUbf27FzX BDIL+hi9aVr+ZDooqcs0XUjGe1/1B+8SaNqMexqDUjxGDN4OfZhdQKD6uTjabc07 aiZqKH1ZWViQlNgMcqpXecXS+r+Qc+R6Qga/iwJuhhPKp3VhUEtuDaHajPiTx17q 157CedcXxXKPRnNC/IneU0lOageknCLpRpIHZi3pYgcyfX1evE8CgF0aLZsN8tTv cdFJh7S89CknvK1sL18pcbV5/mtpDH/0DIWGg4d98O9X8Y/vluYEqSf6kPrjg6lR aVHU4/E8p8Y= =c+28 -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging Block layer patches - Event throttling for BLOCK_IO_ERROR - iotests: Fix backup-discard-source test for XFS - Coverity fixes - raw-format: Fix error message for invalid offset/size # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmcX1wQRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9aWKA//cyG+Q3EXLouSu2Ob04RArX8HgAzLmHL3 # Fx9x6BbDtusPfzxKVLqhJhJ5/oRyk0QWkdZKGNSxinLD3DBJ6q6FMNaWhuvzOBcy # iHnWlMfwEIBl5vFJwM5Q/d7F2afOUiVSeR7E4TQn063cBo96qIrAD7DRLM01jBEN # d9+9nkBruwgmxZJIr3WTsqjDoTqflcjxA6Adp/WkzVXBMMYqcsuReXQtrgfFooKw # yhjkHq5nFKzebvK+BLjA0ytuvUlsRqLYDXN+bAk/rC6oCgbzygAjNwL5kUEYnV1r # lVRSOxRUlet4v2GFCvplxw5tX3aJzlWB50v7d+oaBYR72htTtPeIZzadBJySdtSk # DxEUR5kTcGK/vSI+WOapTVK+qU+Wr+6lFwGOL0zEYZyfvpyoFwfAlkjAUbf27FzX # BDIL+hi9aVr+ZDooqcs0XUjGe1/1B+8SaNqMexqDUjxGDN4OfZhdQKD6uTjabc07 # aiZqKH1ZWViQlNgMcqpXecXS+r+Qc+R6Qga/iwJuhhPKp3VhUEtuDaHajPiTx17q # 157CedcXxXKPRnNC/IneU0lOageknCLpRpIHZi3pYgcyfX1evE8CgF0aLZsN8tTv # cdFJh7S89CknvK1sL18pcbV5/mtpDH/0DIWGg4d98O9X8Y/vluYEqSf6kPrjg6lR # aVHU4/E8p8Y= # =c+28 # -----END PGP SIGNATURE----- # gpg: Signature made Tue 22 Oct 2024 17:47:00 BST # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: raw-format: Fix error message for invalid offset/size block-backend: per-device throttling of BLOCK_IO_ERROR reports qapi: add qom-path to BLOCK_IO_ERROR event iotests/backup-discard-source: don't use actual-size iotests/backup-discard-source: convert size variable to be int block/vdi.c: Make SECTOR_SIZE constant 64-bits tests/qemu-iotests/211.out: Update to expect MapEntry 'compressed' field block/ssh.c: Don't double-check that characters are hex digits block/gluster: Use g_autofree for string in qemu_gluster_parse_json() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e67b7aef7c
|
@ -1019,22 +1019,34 @@ DeviceState *blk_get_attached_dev(BlockBackend *blk)
|
|||
return blk->dev;
|
||||
}
|
||||
|
||||
/* Return the qdev ID, or if no ID is assigned the QOM path, of the block
|
||||
* device attached to the BlockBackend. */
|
||||
char *blk_get_attached_dev_id(BlockBackend *blk)
|
||||
static char *blk_get_attached_dev_id_or_path(BlockBackend *blk, bool want_id)
|
||||
{
|
||||
DeviceState *dev = blk->dev;
|
||||
IO_CODE();
|
||||
|
||||
if (!dev) {
|
||||
return g_strdup("");
|
||||
} else if (dev->id) {
|
||||
} else if (want_id && dev->id) {
|
||||
return g_strdup(dev->id);
|
||||
}
|
||||
|
||||
return object_get_canonical_path(OBJECT(dev)) ?: g_strdup("");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the qdev ID, or if no ID is assigned the QOM path, of the block
|
||||
* device attached to the BlockBackend.
|
||||
*/
|
||||
char *blk_get_attached_dev_id(BlockBackend *blk)
|
||||
{
|
||||
return blk_get_attached_dev_id_or_path(blk, true);
|
||||
}
|
||||
|
||||
static char *blk_get_attached_dev_path(BlockBackend *blk)
|
||||
{
|
||||
return blk_get_attached_dev_id_or_path(blk, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the BlockBackend which has the device model @dev attached if it
|
||||
* exists, else null.
|
||||
|
@ -2125,6 +2137,7 @@ static void send_qmp_error_event(BlockBackend *blk,
|
|||
|
||||
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
||||
qapi_event_send_block_io_error(blk_name(blk),
|
||||
blk_get_attached_dev_path(blk),
|
||||
bs ? bdrv_get_node_name(bs) : NULL, optype,
|
||||
action, blk_iostatus_is_enabled(blk),
|
||||
error == ENOSPC, strerror(error));
|
||||
|
|
|
@ -514,7 +514,6 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
|||
SocketAddressList **tail;
|
||||
QDict *backing_options = NULL;
|
||||
Error *local_err = NULL;
|
||||
char *str = NULL;
|
||||
const char *ptr;
|
||||
int i, type, num_servers;
|
||||
|
||||
|
@ -547,7 +546,8 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
|||
tail = &gconf->server;
|
||||
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
str = g_strdup_printf(GLUSTER_OPT_SERVER_PATTERN"%d.", i);
|
||||
g_autofree char *str = g_strdup_printf(GLUSTER_OPT_SERVER_PATTERN"%d.",
|
||||
i);
|
||||
qdict_extract_subqdict(options, &backing_options, str);
|
||||
|
||||
/* create opts info from runtime_type_opts list */
|
||||
|
@ -658,8 +658,6 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
|||
|
||||
qobject_unref(backing_options);
|
||||
backing_options = NULL;
|
||||
g_free(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -668,7 +666,6 @@ out:
|
|||
error_propagate(errp, local_err);
|
||||
qapi_free_SocketAddress(gsconf);
|
||||
qemu_opts_del(opts);
|
||||
g_free(str);
|
||||
qobject_unref(backing_options);
|
||||
errno = EINVAL;
|
||||
return -errno;
|
||||
|
|
|
@ -111,7 +111,7 @@ raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
|
|||
if (offset > real_size) {
|
||||
error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
|
||||
"size of the containing file (%" PRId64 ")",
|
||||
s->offset, real_size);
|
||||
offset, real_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
|
|||
error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
|
||||
"(%" PRIu64 ") has to be smaller or equal to the "
|
||||
" actual size of the containing file (%" PRId64 ")",
|
||||
s->offset, s->size, real_size);
|
||||
offset, size, real_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
12
block/ssh.c
12
block/ssh.c
|
@ -364,7 +364,7 @@ static unsigned hex2decimal(char ch)
|
|||
return 10 + (ch - 'A');
|
||||
}
|
||||
|
||||
return -1;
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
/* Compare the binary fingerprint (hash of host key) with the
|
||||
|
@ -376,13 +376,15 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len,
|
|||
unsigned c;
|
||||
|
||||
while (len > 0) {
|
||||
unsigned c0, c1;
|
||||
while (*host_key_check == ':')
|
||||
host_key_check++;
|
||||
if (!qemu_isxdigit(host_key_check[0]) ||
|
||||
!qemu_isxdigit(host_key_check[1]))
|
||||
c0 = hex2decimal(host_key_check[0]);
|
||||
c1 = hex2decimal(host_key_check[1]);
|
||||
if (c0 > 0xf || c1 > 0xf) {
|
||||
return 1;
|
||||
c = hex2decimal(host_key_check[0]) * 16 +
|
||||
hex2decimal(host_key_check[1]);
|
||||
}
|
||||
c = c0 * 16 + c1;
|
||||
if (c - *fingerprint != 0)
|
||||
return c - *fingerprint;
|
||||
fingerprint++;
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
/* Command line option for static images. */
|
||||
#define BLOCK_OPT_STATIC "static"
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define SECTOR_SIZE 512ULL
|
||||
#define DEFAULT_CLUSTER_SIZE 1048576
|
||||
/* Note: can't use 1 * MiB, because it's passed to stringify() */
|
||||
|
||||
|
@ -442,7 +442,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
goto fail;
|
||||
} else if (header.sector_size != SECTOR_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (sector size %" PRIu32
|
||||
" is not %u)", header.sector_size, SECTOR_SIZE);
|
||||
" is not %llu)", header.sector_size, SECTOR_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
||||
|
|
|
@ -308,6 +308,7 @@ int error_printf_unless_qmp(const char *fmt, ...)
|
|||
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
|
||||
/* Limit guest-triggerable events to 1 per second */
|
||||
[QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_BLOCK_IO_ERROR] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_BALLOON_CHANGE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS },
|
||||
|
@ -493,7 +494,8 @@ static unsigned int qapi_event_throttle_hash(const void *key)
|
|||
hash += g_str_hash(qdict_get_str(evstate->data, "node-name"));
|
||||
}
|
||||
|
||||
if (evstate->event == QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE) {
|
||||
if (evstate->event == QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE ||
|
||||
evstate->event == QAPI_EVENT_BLOCK_IO_ERROR) {
|
||||
hash += g_str_hash(qdict_get_str(evstate->data, "qom-path"));
|
||||
}
|
||||
|
||||
|
@ -519,7 +521,8 @@ static gboolean qapi_event_throttle_equal(const void *a, const void *b)
|
|||
qdict_get_str(evb->data, "node-name"));
|
||||
}
|
||||
|
||||
if (eva->event == QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE) {
|
||||
if (eva->event == QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE ||
|
||||
eva->event == QAPI_EVENT_BLOCK_IO_ERROR) {
|
||||
return !strcmp(qdict_get_str(eva->data, "qom-path"),
|
||||
qdict_get_str(evb->data, "qom-path"));
|
||||
}
|
||||
|
|
|
@ -5584,6 +5584,8 @@
|
|||
#
|
||||
# Emitted when a disk I/O error occurs
|
||||
#
|
||||
# @qom-path: path to the device object in the QOM tree (since 9.2)
|
||||
#
|
||||
# @device: device name. This is always present for compatibility
|
||||
# reasons, but it can be empty ("") if the image does not have a
|
||||
# device name associated.
|
||||
|
@ -5609,12 +5611,15 @@
|
|||
# .. note:: If action is "stop", a STOP event will eventually follow
|
||||
# the BLOCK_IO_ERROR event.
|
||||
#
|
||||
# .. note:: This event is rate-limited.
|
||||
#
|
||||
# Since: 0.13
|
||||
#
|
||||
# .. qmp-example::
|
||||
#
|
||||
# <- { "event": "BLOCK_IO_ERROR",
|
||||
# "data": { "device": "ide0-hd1",
|
||||
# "data": { "qom-path": "/machine/unattached/device[0]",
|
||||
# "device": "ide0-hd1",
|
||||
# "node-name": "#block212",
|
||||
# "operation": "write",
|
||||
# "action": "stop",
|
||||
|
@ -5622,7 +5627,7 @@
|
|||
# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
|
||||
##
|
||||
{ 'event': 'BLOCK_IO_ERROR',
|
||||
'data': { 'device': 'str', '*node-name': 'str',
|
||||
'data': { 'qom-path': 'str', 'device': 'str', '*node-name': 'str',
|
||||
'operation': 'IoOperationType',
|
||||
'action': 'BlockErrorAction', '*nospace': 'bool',
|
||||
'reason': 'str' } }
|
||||
|
|
|
@ -17,7 +17,7 @@ file format: IMGFMT
|
|||
virtual size: 128 MiB (134217728 bytes)
|
||||
cluster_size: 1048576
|
||||
|
||||
[{"data": false, "depth": 0, "length": 134217728, "present": true, "start": 0, "zero": true}]
|
||||
[{"compressed": false, "data": false, "depth": 0, "length": 134217728, "present": true, "start": 0, "zero": true}]
|
||||
=== Successful image creation (explicit defaults) ===
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
|
||||
|
@ -35,7 +35,7 @@ file format: IMGFMT
|
|||
virtual size: 64 MiB (67108864 bytes)
|
||||
cluster_size: 1048576
|
||||
|
||||
[{"data": false, "depth": 0, "length": 67108864, "present": true, "start": 0, "zero": true}]
|
||||
[{"compressed": false, "data": false, "depth": 0, "length": 67108864, "present": true, "start": 0, "zero": true}]
|
||||
=== Successful image creation (with non-default options) ===
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
|
||||
|
@ -53,7 +53,7 @@ file format: IMGFMT
|
|||
virtual size: 32 MiB (33554432 bytes)
|
||||
cluster_size: 1048576
|
||||
|
||||
[{"data": true, "depth": 0, "length": 3072, "offset": 1024, "present": true, "start": 0, "zero": false}, {"data": true, "depth": 0, "length": 33551360, "offset": 4096, "present": true, "start": 3072, "zero": true}]
|
||||
[{"compressed": false, "data": true, "depth": 0, "length": 3072, "offset": 1024, "present": true, "start": 0, "zero": false}, {"compressed": false, "data": true, "depth": 0, "length": 33551360, "offset": 4096, "present": true, "start": 3072, "zero": true}]
|
||||
=== Invalid BlockdevRef ===
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
|
||||
|
|
|
@ -28,20 +28,14 @@ from iotests import qemu_img_create, qemu_img_map, qemu_io
|
|||
temp_img = os.path.join(iotests.test_dir, 'temp')
|
||||
source_img = os.path.join(iotests.test_dir, 'source')
|
||||
target_img = os.path.join(iotests.test_dir, 'target')
|
||||
size = '1M'
|
||||
|
||||
|
||||
def get_actual_size(vm, node_name):
|
||||
nodes = vm.cmd('query-named-block-nodes', flat=True)
|
||||
node = next(n for n in nodes if n['node-name'] == node_name)
|
||||
return node['image']['actual-size']
|
||||
size = 1024 * 1024
|
||||
|
||||
|
||||
class TestBackup(iotests.QMPTestCase):
|
||||
def setUp(self):
|
||||
qemu_img_create('-f', iotests.imgfmt, source_img, size)
|
||||
qemu_img_create('-f', iotests.imgfmt, temp_img, size)
|
||||
qemu_img_create('-f', iotests.imgfmt, target_img, size)
|
||||
qemu_img_create('-f', iotests.imgfmt, source_img, str(size))
|
||||
qemu_img_create('-f', iotests.imgfmt, temp_img, str(size))
|
||||
qemu_img_create('-f', iotests.imgfmt, target_img, str(size))
|
||||
qemu_io('-c', 'write 0 1M', source_img)
|
||||
|
||||
self.vm = iotests.VM()
|
||||
|
@ -84,7 +78,12 @@ class TestBackup(iotests.QMPTestCase):
|
|||
}
|
||||
})
|
||||
|
||||
self.assertLess(get_actual_size(self.vm, 'temp'), 512 * 1024)
|
||||
self.bitmap = {
|
||||
'node': 'temp',
|
||||
'name': 'bitmap0'
|
||||
}
|
||||
|
||||
self.vm.cmd('block-dirty-bitmap-add', self.bitmap)
|
||||
|
||||
def tearDown(self):
|
||||
# That should fail, because region is discarded
|
||||
|
@ -98,7 +97,7 @@ class TestBackup(iotests.QMPTestCase):
|
|||
mapping = qemu_img_map(temp_img)
|
||||
self.assertEqual(len(mapping), 1)
|
||||
self.assertEqual(mapping[0]['start'], 0)
|
||||
self.assertEqual(mapping[0]['length'], 1024 * 1024)
|
||||
self.assertEqual(mapping[0]['length'], size)
|
||||
self.assertEqual(mapping[0]['data'], False)
|
||||
|
||||
os.remove(temp_img)
|
||||
|
@ -113,6 +112,13 @@ class TestBackup(iotests.QMPTestCase):
|
|||
|
||||
self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
|
||||
|
||||
def get_bitmap_count(self):
|
||||
nodes = self.vm.cmd('query-named-block-nodes', flat=True)
|
||||
temp = next(n for n in nodes if n['node-name'] == 'temp')
|
||||
bitmap = temp['dirty-bitmaps'][0]
|
||||
assert bitmap['name'] == self.bitmap['name']
|
||||
return bitmap['count']
|
||||
|
||||
def test_discard_written(self):
|
||||
"""
|
||||
1. Guest writes
|
||||
|
@ -125,7 +131,7 @@ class TestBackup(iotests.QMPTestCase):
|
|||
self.assert_qmp(result, 'return', '')
|
||||
|
||||
# Check that data is written to temporary image
|
||||
self.assertGreater(get_actual_size(self.vm, 'temp'), 1024 * 1024)
|
||||
self.assertEqual(self.get_bitmap_count(), size)
|
||||
|
||||
self.do_backup()
|
||||
|
||||
|
@ -138,13 +144,18 @@ class TestBackup(iotests.QMPTestCase):
|
|||
"""
|
||||
self.do_backup()
|
||||
|
||||
# backup job did discard operation and pollute the bitmap,
|
||||
# we have to clean the bitmap, to check next write
|
||||
self.assertEqual(self.get_bitmap_count(), size)
|
||||
self.vm.cmd('block-dirty-bitmap-clear', self.bitmap)
|
||||
|
||||
# Try trigger copy-before-write operation
|
||||
result = self.vm.hmp_qemu_io('cbw', 'write 0 1M')
|
||||
self.assert_qmp(result, 'return', '')
|
||||
|
||||
# Check that data is not written to temporary image, as region
|
||||
# is discarded from copy-before-write process
|
||||
self.assertLess(get_actual_size(self.vm, 'temp'), 512 * 1024)
|
||||
self.assertEqual(self.get_bitmap_count(), 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue