Block layer patches for 2.10.0-rc0

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJZdgFKAAoJEH8JsnLIjy/WT8wQAIbx1EX+gfSQ5rOE1QXvO1PY
 rQBYjhbzI8VJ/g8l/cII5i3bmd1kgtbY49o4PWOrdZBBDjAofr7Z7gBvKQJscEcX
 +uzhhoCJjypiyLh8+eppaLEdWnriFV2YE4FshGFQMB1Jtc8Wdbg6wNn2am5UEk/i
 DALSGyZiVnxe5CdwZN5PeJEWESr302zvGzN5rzh4EQ1WJ5rMLbsyMIodvPEv2YNR
 rvHwcDyB6oWAbMuxKE6m8blvOOa7JqkKvIlkk1Nuz0Mfk4edWyZgFq8HAEp4y6cA
 UQI9nu7CouOjUyXkB3BaRQk4o0pmu/jidj6i09xiixSKdTLd4jzxhTSKJ2TiWL5l
 tiRLjRCK8a16raTywlM3LZ50ujbbQpHpV88IueKlBHRt/iU0zrYiOrB50XTSNr0j
 He77WAWmXGl2NifeOJ4nk6aucWayp1spJZoAozGtM+OpUfyvb5qr0TRDmovSdKX3
 hKbKYwouOohxA3zZbmOW6IUiGgvrIWMejSJ3WjLGQyaVvwprtRRzhpKHBBGOhbEX
 eej/DssXZCRiYb0L+evXKRSleL+HZqdP35vZhDR7oMwd/4QPZ1URFLvI8Vh0daqb
 cjvMz63V+LDRPn//IAAyUephk51UN6xucz9lbvmq6hXXypKE8tH5+IwoTAWZ0xmo
 cHPZwQseF7TDiNpfndHa
 =OzLv
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging

Block layer patches for 2.10.0-rc0

# gpg: Signature made Mon 24 Jul 2017 15:16:42 BST
# 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:
  qemu-iotests: Avoid unnecessary sleeps
  block: Skip implicit nodes in query-block/blockstats
  qcow2: Fix sector calculation in qcow2_measure()
  dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented
  iotests: Remove a few tests from 'quick' group

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-07-24 16:58:16 +01:00
commit 50104f5ac5
17 changed files with 157 additions and 50 deletions

13
block.c
View File

@ -3973,19 +3973,6 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
return retval; return retval;
} }
int bdrv_get_backing_file_depth(BlockDriverState *bs)
{
if (!bs->drv) {
return 0;
}
if (!bs->backing) {
return 0;
}
return 1 + bdrv_get_backing_file_depth(bs->backing->bs);
}
void bdrv_init(void) void bdrv_init(void)
{ {
module_call_init(MODULE_INIT_BLOCK); module_call_init(MODULE_INIT_BLOCK);

View File

@ -346,6 +346,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
if (commit_top_bs == NULL) { if (commit_top_bs == NULL) {
goto fail; goto fail;
} }
if (!filter_node_name) {
commit_top_bs->implicit = true;
}
commit_top_bs->total_sectors = top->total_sectors; commit_top_bs->total_sectors = top->total_sectors;
bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top)); bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));

View File

@ -461,7 +461,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
info->count = bdrv_get_dirty_count(bm); info->count = bdrv_get_dirty_count(bm) << BDRV_SECTOR_BITS;
info->granularity = bdrv_dirty_bitmap_granularity(bm); info->granularity = bdrv_dirty_bitmap_granularity(bm);
info->has_name = !!bm->name; info->has_name = !!bm->name;
info->name = g_strdup(bm->name); info->name = g_strdup(bm->name);

View File

@ -1168,6 +1168,9 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
if (mirror_top_bs == NULL) { if (mirror_top_bs == NULL) {
return; return;
} }
if (!filter_node_name) {
mirror_top_bs->implicit = true;
}
mirror_top_bs->total_sectors = bs->total_sectors; mirror_top_bs->total_sectors = bs->total_sectors;
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));

View File

@ -64,7 +64,6 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
info->backing_file = g_strdup(bs->backing_file); info->backing_file = g_strdup(bs->backing_file);
} }
info->backing_file_depth = bdrv_get_backing_file_depth(bs);
info->detect_zeroes = bs->detect_zeroes; info->detect_zeroes = bs->detect_zeroes;
if (blk && blk_get_public(blk)->throttle_state) { if (blk && blk_get_public(blk)->throttle_state) {
@ -125,6 +124,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
bs0 = bs; bs0 = bs;
p_image_info = &info->image; p_image_info = &info->image;
info->backing_file_depth = 0;
while (1) { while (1) {
Error *local_err = NULL; Error *local_err = NULL;
bdrv_query_image_info(bs0, p_image_info, &local_err); bdrv_query_image_info(bs0, p_image_info, &local_err);
@ -133,13 +133,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
qapi_free_BlockDeviceInfo(info); qapi_free_BlockDeviceInfo(info);
return NULL; return NULL;
} }
if (bs0->drv && bs0->backing) { if (bs0->drv && bs0->backing) {
info->backing_file_depth++;
bs0 = bs0->backing->bs; bs0 = bs0->backing->bs;
(*p_image_info)->has_backing_image = true; (*p_image_info)->has_backing_image = true;
p_image_info = &((*p_image_info)->backing_image); p_image_info = &((*p_image_info)->backing_image);
} else { } else {
break; break;
} }
/* Skip automatically inserted nodes that the user isn't aware of for
* query-block (blk != NULL), but not for query-named-block-nodes */
while (blk && bs0 && bs0->drv && bs0->implicit) {
bs0 = backing_bs(bs0);
}
} }
return info; return info;
@ -324,6 +332,11 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
char *qdev; char *qdev;
/* Skip automatically inserted nodes that the user isn't aware of */
while (bs && bs->drv && bs->implicit) {
bs = backing_bs(bs);
}
info->device = g_strdup(blk_name(blk)); info->device = g_strdup(blk_name(blk));
info->type = g_strdup("unknown"); info->type = g_strdup("unknown");
info->locked = blk_dev_is_medium_locked(blk); info->locked = blk_dev_is_medium_locked(blk);
@ -434,8 +447,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
} }
} }
static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs, static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
bool query_backing) bool blk_level)
{ {
BlockStats *s = NULL; BlockStats *s = NULL;
@ -446,6 +459,14 @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
return s; return s;
} }
/* Skip automatically inserted nodes that the user isn't aware of in
* a BlockBackend-level command. Stay at the exact node for a node-level
* command. */
while (blk_level && bs->drv && bs->implicit) {
bs = backing_bs(bs);
assert(bs);
}
if (bdrv_get_node_name(bs)[0]) { if (bdrv_get_node_name(bs)[0]) {
s->has_node_name = true; s->has_node_name = true;
s->node_name = g_strdup(bdrv_get_node_name(bs)); s->node_name = g_strdup(bdrv_get_node_name(bs));
@ -455,12 +476,12 @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
if (bs->file) { if (bs->file) {
s->has_parent = true; s->has_parent = true;
s->parent = bdrv_query_bds_stats(bs->file->bs, query_backing); s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level);
} }
if (query_backing && bs->backing) { if (blk_level && bs->backing) {
s->has_backing = true; s->has_backing = true;
s->backing = bdrv_query_bds_stats(bs->backing->bs, query_backing); s->backing = bdrv_query_bds_stats(bs->backing->bs, blk_level);
} }
return s; return s;

View File

@ -3669,8 +3669,8 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
for (sector_num = 0; for (sector_num = 0;
sector_num < ssize / BDRV_SECTOR_SIZE; sector_num < ssize / BDRV_SECTOR_SIZE;
sector_num += pnum) { sector_num += pnum) {
int nb_sectors = MAX(ssize / BDRV_SECTOR_SIZE - sector_num, int nb_sectors = MIN(ssize / BDRV_SECTOR_SIZE - sector_num,
INT_MAX); BDRV_REQUEST_MAX_SECTORS);
BlockDriverState *file; BlockDriverState *file;
int64_t ret; int64_t ret;

View File

@ -300,7 +300,6 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
int bytes, BdrvRequestFlags flags); int bytes, BdrvRequestFlags flags);
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
const char *backing_file); const char *backing_file);
int bdrv_get_backing_file_depth(BlockDriverState *bs);
void bdrv_refresh_filename(BlockDriverState *bs); void bdrv_refresh_filename(BlockDriverState *bs);
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
Error **errp); Error **errp);

View File

@ -549,6 +549,7 @@ struct BlockDriverState {
bool sg; /* if true, the device is a /dev/sg* */ bool sg; /* if true, the device is a /dev/sg* */
bool probed; /* if true, format was probed rather than specified */ bool probed; /* if true, format was probed rather than specified */
bool force_share; /* if true, always allow all shared permissions */ bool force_share; /* if true, always allow all shared permissions */
bool implicit; /* if true, this filter node was automatically inserted */
BlockDriver *drv; /* NULL means no media */ BlockDriver *drv; /* NULL means no media */
void *opaque; void *opaque;

View File

@ -520,7 +520,8 @@
# #
# Get a list of BlockInfo for all virtual block devices. # Get a list of BlockInfo for all virtual block devices.
# #
# Returns: a list of @BlockInfo describing each virtual block device # Returns: a list of @BlockInfo describing each virtual block device. Filter
# nodes that were created implicitly are skipped over.
# #
# Since: 0.14.0 # Since: 0.14.0
# #
@ -780,7 +781,8 @@
# information, but not "backing". # information, but not "backing".
# If false or omitted, the behavior is as before - query all the # If false or omitted, the behavior is as before - query all the
# device backends, recursively including their "parent" and # device backends, recursively including their "parent" and
# "backing". (Since 2.3) # "backing". Filter nodes that were created implicitly are
# skipped over in this mode. (Since 2.3)
# #
# Returns: A list of @BlockStats for each virtual block devices. # Returns: A list of @BlockStats for each virtual block devices.
# #

View File

@ -89,18 +89,19 @@ class TestSingleDrive(iotests.QMPTestCase):
result = self.vm.qmp('block-job-pause', device='drive0') result = self.vm.qmp('block-job-pause', device='drive0')
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
time.sleep(1) self.vm.resume_drive('drive0')
self.pause_job('drive0')
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)
result = self.vm.qmp('block-job-resume', device='drive0') result = self.vm.qmp('block-job-resume', device='drive0')
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
self.vm.resume_drive('drive0')
self.wait_until_completed() self.wait_until_completed()
self.assert_no_active_block_jobs() self.assert_no_active_block_jobs()

View File

@ -81,7 +81,7 @@ class TestSingleDrive(ImageCommitTestCase):
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img) qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
self.vm = iotests.VM().add_drive(test_img, interface="none") self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
self.vm.add_device("virtio-scsi-pci") self.vm.add_device("virtio-scsi-pci")
self.vm.add_device("scsi-hd,id=scsi0,drive=drive0") self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
self.vm.launch() self.vm.launch()
@ -163,6 +163,34 @@ class TestSingleDrive(ImageCommitTestCase):
self.assert_no_active_block_jobs() self.assert_no_active_block_jobs()
# Tests that the insertion of the commit_top filter node doesn't make a
# difference to query-blockstat
def test_implicit_node(self):
if self.image_len == 0:
return
self.assert_no_active_block_jobs()
result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
base=backing_img, speed=(self.image_len / 4))
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', test_img)
self.assert_qmp(result, 'return[0]/inserted/drv', iotests.imgfmt)
self.assert_qmp(result, 'return[0]/inserted/backing_file', mid_img)
self.assert_qmp(result, 'return[0]/inserted/backing_file_depth', 2)
self.assert_qmp(result, 'return[0]/inserted/image/filename', test_img)
self.assert_qmp(result, 'return[0]/inserted/image/backing-image/filename', mid_img)
self.assert_qmp(result, 'return[0]/inserted/image/backing-image/backing-image/filename', backing_img)
result = self.vm.qmp('query-blockstats')
self.assert_qmp(result, 'return[0]/node-name', 'top')
self.assert_qmp(result, 'return[0]/backing/node-name', 'mid')
self.assert_qmp(result, 'return[0]/backing/backing/node-name', 'base')
self.cancel_and_wait()
self.assert_no_active_block_jobs()
class TestRelativePaths(ImageCommitTestCase): class TestRelativePaths(ImageCommitTestCase):
image_len = 1 * 1024 * 1024 image_len = 1 * 1024 * 1024
test_len = 1 * 1024 * 256 test_len = 1 * 1024 * 256

View File

@ -1,5 +1,5 @@
........................... .............................
---------------------------------------------------------------------- ----------------------------------------------------------------------
Ran 27 tests Ran 29 tests
OK OK

View File

@ -42,7 +42,7 @@ class TestSingleDrive(iotests.QMPTestCase):
def setUp(self): def setUp(self):
iotests.create_image(backing_img, self.image_len) iotests.create_image(backing_img, self.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
self.vm = iotests.VM().add_drive(test_img) self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=base")
if iotests.qemu_default_machine == 'pc': if iotests.qemu_default_machine == 'pc':
self.vm.add_drive(None, 'media=cdrom', 'ide') self.vm.add_drive(None, 'media=cdrom', 'ide')
self.vm.launch() self.vm.launch()
@ -103,14 +103,12 @@ class TestSingleDrive(iotests.QMPTestCase):
target=self.qmp_target) target=self.qmp_target)
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-pause', device='drive0') self.pause_job('drive0')
self.assert_qmp(result, 'return', {})
time.sleep(1)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)
@ -169,6 +167,42 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assertTrue(iotests.compare_images(test_img, target_img), self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring') 'target image does not match source after mirroring')
# Tests that the insertion of the mirror_top filter node doesn't make a
# difference to query-block
def test_implicit_node(self):
self.assert_no_active_block_jobs()
result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
target=self.qmp_target)
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', test_img)
self.assert_qmp(result, 'return[0]/inserted/drv', iotests.imgfmt)
self.assert_qmp(result, 'return[0]/inserted/backing_file', backing_img)
self.assert_qmp(result, 'return[0]/inserted/backing_file_depth', 1)
self.assert_qmp(result, 'return[0]/inserted/image/filename', test_img)
self.assert_qmp(result, 'return[0]/inserted/image/backing-image/filename', backing_img)
result = self.vm.qmp('query-blockstats')
self.assert_qmp(result, 'return[0]/node-name', 'top')
self.assert_qmp(result, 'return[0]/backing/node-name', 'base')
self.cancel_and_wait(force=True)
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', test_img)
self.assert_qmp(result, 'return[0]/inserted/drv', iotests.imgfmt)
self.assert_qmp(result, 'return[0]/inserted/backing_file', backing_img)
self.assert_qmp(result, 'return[0]/inserted/backing_file_depth', 1)
self.assert_qmp(result, 'return[0]/inserted/image/filename', test_img)
self.assert_qmp(result, 'return[0]/inserted/image/backing-image/filename', backing_img)
result = self.vm.qmp('query-blockstats')
self.assert_qmp(result, 'return[0]/node-name', 'top')
self.assert_qmp(result, 'return[0]/backing/node-name', 'base')
self.vm.shutdown()
def test_medium_not_found(self): def test_medium_not_found(self):
if iotests.qemu_default_machine != 'pc': if iotests.qemu_default_machine != 'pc':
return return
@ -860,14 +894,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
target=quorum_repair_img, format=iotests.imgfmt) target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-pause', device='job0') self.pause_job('job0')
self.assert_qmp(result, 'return', {})
time.sleep(1)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)

View File

@ -1,5 +1,5 @@
............................................................................... .....................................................................................
---------------------------------------------------------------------- ----------------------------------------------------------------------
Ran 79 tests Ran 85 tests
OK OK

View File

@ -89,11 +89,12 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
self.vm.resume_drive('drive0') self.vm.resume_drive('drive0')
time.sleep(1) self.pause_job('drive0')
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)
@ -302,11 +303,12 @@ class TestSingleTransaction(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
self.vm.resume_drive('drive0') self.vm.resume_drive('drive0')
time.sleep(1) self.pause_job('drive0')
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)
@ -529,11 +531,12 @@ class TestDriveCompression(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {}) self.assert_qmp(result, 'return', {})
self.vm.resume_drive('drive0') self.vm.resume_drive('drive0')
time.sleep(1) self.pause_job('drive0')
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset') offset = self.dictpath(result, 'return[0]/offset')
time.sleep(1) time.sleep(0.5)
result = self.vm.qmp('query-block-jobs') result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset) self.assert_qmp(result, 'return[0]/offset', offset)

View File

@ -175,7 +175,7 @@
175 auto quick 175 auto quick
176 rw auto backing 176 rw auto backing
177 rw auto quick 177 rw auto quick
178 auto quick 178 auto
179 rw auto quick 179 rw auto quick
181 rw auto migration 181 rw auto migration
182 rw auto quick 182 rw auto quick
@ -183,4 +183,4 @@
185 rw auto 185 rw auto
186 rw auto 186 rw auto
188 rw auto quick 188 rw auto quick
189 rw auto quick 189 rw auto

View File

@ -27,6 +27,7 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
import qtest import qtest
import struct import struct
import json import json
import signal
# This will not work if arguments contain spaces but is necessary if we # This will not work if arguments contain spaces but is necessary if we
@ -137,6 +138,20 @@ def log(msg, filters=[]):
msg = flt(msg) msg = flt(msg)
print msg print msg
class Timeout:
def __init__(self, seconds, errmsg = "Timeout"):
self.seconds = seconds
self.errmsg = errmsg
def __enter__(self):
signal.signal(signal.SIGALRM, self.timeout)
signal.setitimer(signal.ITIMER_REAL, self.seconds)
return self
def __exit__(self, type, value, traceback):
signal.setitimer(signal.ITIMER_REAL, 0)
return False
def timeout(self, signum, frame):
raise Exception(self.errmsg)
class VM(qtest.QEMUQtestMachine): class VM(qtest.QEMUQtestMachine):
'''A QEMU VM''' '''A QEMU VM'''
@ -346,6 +361,18 @@ class QMPTestCase(unittest.TestCase):
event = self.wait_until_completed(drive=drive) event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror') self.assert_qmp(event, 'data/type', 'mirror')
def pause_job(self, job_id='job0'):
result = self.vm.qmp('block-job-pause', device=job_id)
self.assert_qmp(result, 'return', {})
with Timeout(1, "Timeout waiting for job to pause"):
while True:
result = self.vm.qmp('query-block-jobs')
for job in result['return']:
if job['device'] == job_id and job['paused'] == True and job['busy'] == False:
return job
def notrun(reason): def notrun(reason):
'''Skip this test suite''' '''Skip this test suite'''
# Each test in qemu-iotests has a number ("seq") # Each test in qemu-iotests has a number ("seq")