* [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression
@ 2016-04-27 6:28 Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 1/3] drive-backup: added support for data compression Denis V. Lunev
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Denis V. Lunev @ 2016-04-27 6:28 UTC (permalink / raw)
To: qemu-devel
Cc: den, Pavel Butsykin, Jeff Cody, Markus Armbruster, Eric Blake,
John Snow, Stefan Hajnoczi
The idea is simple - backup is "written-once" data. It is written block
by block and it is large enough. It would be nice to save storage
space and compress it.
These patches add the ability to compress data during backup. This
functionality is implemented by means of adding options to the qmp/hmp
commands(drive-backup, blockdev-backup). The implementation is quite
simple, because the responsibility for data compression imposed on the
format driver.
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
Changes from v1:
- added unittest for backup compression (3)
Pavel Butsykin (3):
drive-backup: added support for data compression
blockdev-backup: added support for data compression
qemu-iotests: test backup compression in 055
block/backup.c | 13 ++++++
blockdev.c | 20 ++++++++-
hmp-commands.hx | 8 ++--
hmp.c | 3 +-
include/block/block_int.h | 1 +
qapi/block-core.json | 3 +-
qmp-commands.hx | 7 +++-
tests/qemu-iotests/055 | 97 +++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/055.out | 4 +-
tests/qemu-iotests/iotests.py | 10 ++---
10 files changed, 150 insertions(+), 16 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v2 1/3] drive-backup: added support for data compression
2016-04-27 6:28 [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
@ 2016-04-27 6:29 ` Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 2/3] blockdev-backup: " Denis V. Lunev
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Denis V. Lunev @ 2016-04-27 6:29 UTC (permalink / raw)
To: qemu-devel
Cc: den, Pavel Butsykin, Jeff Cody, Markus Armbruster, Eric Blake,
John Snow, Stefan Hajnoczi
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
The idea is simple - backup is "written-once" data. It is written block
by block and it is large enough. It would be nice to save storage
space and compress it.
The patch adds a flag to the qmp/hmp drive-backup command which enables
block compression. Compression should be implemented in the format driver
to enable this feature.
There are some limitations of the format driver to allow compressed writes.
We can write data only once. Though for backup this is perfectly fine.
These limitations are maintained by the driver and the error will be
reported if we are doing something wrong.
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
---
block/backup.c | 13 +++++++++++++
blockdev.c | 12 ++++++++++--
hmp-commands.hx | 8 +++++---
hmp.c | 3 ++-
include/block/block_int.h | 1 +
qapi/block-core.json | 2 +-
qmp-commands.hx | 4 +++-
7 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/block/backup.c b/block/backup.c
index 491fd14..cad0439 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -47,6 +47,7 @@ typedef struct BackupBlockJob {
uint64_t sectors_read;
unsigned long *done_bitmap;
int64_t cluster_size;
+ bool compress;
QLIST_HEAD(, CowRequest) inflight_reqs;
} BackupBlockJob;
@@ -157,6 +158,10 @@ static int coroutine_fn backup_do_cow(BlockDriverState *bs,
ret = bdrv_co_write_zeroes(job->target,
start * sectors_per_cluster,
n, BDRV_REQ_MAY_UNMAP);
+ } else if (job->compress) {
+ ret = bdrv_write_compressed(job->target,
+ start * sectors_per_cluster,
+ iov.iov_base, n);
} else {
ret = bdrv_co_writev(job->target,
start * sectors_per_cluster, n,
@@ -497,6 +502,7 @@ static void coroutine_fn backup_run(void *opaque)
void backup_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, MirrorSyncMode sync_mode,
BdrvDirtyBitmap *sync_bitmap,
+ bool compress,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockCompletionFunc *cb, void *opaque,
@@ -534,6 +540,12 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
return;
}
+ if (compress && target->drv->bdrv_write_compressed == NULL) {
+ error_setg(errp, "Compression is not supported for this drive %s",
+ bdrv_get_device_name(target));
+ return;
+ }
+
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
return;
}
@@ -580,6 +592,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
job->sync_mode = sync_mode;
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
sync_bitmap : NULL;
+ job->compress = compress;
/* If there is no backing file on the target, we cannot rely on COW if our
* backup cluster size is smaller than the target cluster size. Even for
diff --git a/blockdev.c b/blockdev.c
index f1f520a..ef72f19 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1856,6 +1856,7 @@ static void do_drive_backup(const char *device, const char *target,
bool has_mode, enum NewImageMode mode,
bool has_speed, int64_t speed,
bool has_bitmap, const char *bitmap,
+ bool has_compress, bool compress,
bool has_on_source_error,
BlockdevOnError on_source_error,
bool has_on_target_error,
@@ -1896,6 +1897,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
backup->has_mode, backup->mode,
backup->has_speed, backup->speed,
backup->has_bitmap, backup->bitmap,
+ backup->has_compress, backup->compress,
backup->has_on_source_error, backup->on_source_error,
backup->has_on_target_error, backup->on_target_error,
common->block_job_txn, &local_err);
@@ -3170,6 +3172,7 @@ static void do_drive_backup(const char *device, const char *target,
bool has_mode, enum NewImageMode mode,
bool has_speed, int64_t speed,
bool has_bitmap, const char *bitmap,
+ bool has_compress, bool compress,
bool has_on_source_error,
BlockdevOnError on_source_error,
bool has_on_target_error,
@@ -3200,6 +3203,9 @@ static void do_drive_backup(const char *device, const char *target,
if (!has_mode) {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
+ if (!has_compress) {
+ compress = false;
+ }
blk = blk_by_name(device);
if (!blk) {
@@ -3288,7 +3294,7 @@ static void do_drive_backup(const char *device, const char *target,
}
}
- backup_start(bs, target_bs, speed, sync, bmap,
+ backup_start(bs, target_bs, speed, sync, bmap, compress,
on_source_error, on_target_error,
block_job_cb, bs, txn, &local_err);
if (local_err != NULL) {
@@ -3307,6 +3313,7 @@ void qmp_drive_backup(const char *device, const char *target,
bool has_mode, enum NewImageMode mode,
bool has_speed, int64_t speed,
bool has_bitmap, const char *bitmap,
+ bool has_compress, bool compress,
bool has_on_source_error, BlockdevOnError on_source_error,
bool has_on_target_error, BlockdevOnError on_target_error,
Error **errp)
@@ -3314,6 +3321,7 @@ void qmp_drive_backup(const char *device, const char *target,
return do_drive_backup(device, target, has_format, format, sync,
has_mode, mode, has_speed, speed,
has_bitmap, bitmap,
+ has_compress, compress,
has_on_source_error, on_source_error,
has_on_target_error, on_target_error,
NULL, errp);
@@ -3378,7 +3386,7 @@ void do_blockdev_backup(const char *device, const char *target,
bdrv_ref(target_bs);
bdrv_set_aio_context(target_bs, aio_context);
- backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
+ backup_start(bs, target_bs, speed, sync, NULL, false, on_source_error,
on_target_error, block_job_cb, bs, txn, &local_err);
if (local_err != NULL) {
bdrv_unref(target_bs);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 4f4f60a..4b1d15b 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1181,8 +1181,8 @@ ETEXI
{
.name = "drive_backup",
- .args_type = "reuse:-n,full:-f,device:B,target:s,format:s?",
- .params = "[-n] [-f] device target [format]",
+ .args_type = "reuse:-n,full:-f,compress:-c,device:B,target:s,format:s?",
+ .params = "[-n] [-f] [-c] device target [format]",
.help = "initiates a point-in-time\n\t\t\t"
"copy for a device. The device's contents are\n\t\t\t"
"copied to the new image file, excluding data that\n\t\t\t"
@@ -1190,7 +1190,9 @@ ETEXI
"The -n flag requests QEMU to reuse the image found\n\t\t\t"
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
- "so that the result does not need a backing file.\n\t\t\t",
+ "so that the result does not need a backing file.\n\t\t\t"
+ "The -c flag requests QEMU to compress backup data\n\t\t\t"
+ "(if the target format supports it).\n\t\t\t",
.mhandler.cmd = hmp_drive_backup,
},
STEXI
diff --git a/hmp.c b/hmp.c
index d510236..e34593d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1094,6 +1094,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
const char *format = qdict_get_try_str(qdict, "format");
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
bool full = qdict_get_try_bool(qdict, "full", false);
+ bool compress = qdict_get_try_bool(qdict, "compress", false);
enum NewImageMode mode;
Error *err = NULL;
@@ -1111,7 +1112,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
qmp_drive_backup(device, filename, !!format, format,
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
- true, mode, false, 0, false, NULL,
+ true, mode, false, 0, false, NULL, compress, compress,
false, 0, false, 0, &err);
hmp_handle_error(mon, &err);
}
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 10d8759..142d207 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -701,6 +701,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
void backup_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, MirrorSyncMode sync_mode,
BdrvDirtyBitmap *sync_bitmap,
+ bool compress,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockCompletionFunc *cb, void *opaque,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 1d09079..ebedf0d 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -905,7 +905,7 @@
{ 'struct': 'DriveBackup',
'data': { 'device': 'str', 'target': 'str', '*format': 'str',
'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
- '*speed': 'int', '*bitmap': 'str',
+ '*speed': 'int', '*bitmap': 'str', '*compress': 'bool',
'*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index de896a5..ce36518 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1186,7 +1186,8 @@ EQMP
{
.name = "drive-backup",
.args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?,"
- "bitmap:s?,on-source-error:s?,on-target-error:s?",
+ "bitmap:s?,compress:b?,"
+ "on-source-error:s?,on-target-error:s?",
.mhandler.cmd_new = qmp_marshal_drive_backup,
},
@@ -1220,6 +1221,7 @@ Arguments:
- "mode": whether and how QEMU should create a new image
(NewImageMode, optional, default 'absolute-paths')
- "speed": the maximum speed, in bytes per second (json-int, optional)
+- "compress": compress data blocks (if the target format supports it).
- "on-source-error": the action to take on an error on the source, default
'report'. 'stop' and 'enospc' can only be used
if the block device supports io-status.
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v2 2/3] blockdev-backup: added support for data compression
2016-04-27 6:28 [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 1/3] drive-backup: added support for data compression Denis V. Lunev
@ 2016-04-27 6:29 ` Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 3/3] qemu-iotests: test backup compression in 055 Denis V. Lunev
2016-04-27 8:56 ` [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
3 siblings, 0 replies; 5+ messages in thread
From: Denis V. Lunev @ 2016-04-27 6:29 UTC (permalink / raw)
To: qemu-devel
Cc: den, Pavel Butsykin, Jeff Cody, Markus Armbruster, Eric Blake,
John Snow, Stefan Hajnoczi
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
The idea is simple - backup is "written-once" data. It is written block
by block and it is large enough. It would be nice to save storage
space and compress it.
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
---
blockdev.c | 10 +++++++++-
qapi/block-core.json | 1 +
qmp-commands.hx | 3 ++-
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index ef72f19..353c1c8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1940,6 +1940,7 @@ typedef struct BlockdevBackupState {
static void do_blockdev_backup(const char *device, const char *target,
enum MirrorSyncMode sync,
bool has_speed, int64_t speed,
+ bool has_compress, bool compress,
bool has_on_source_error,
BlockdevOnError on_source_error,
bool has_on_target_error,
@@ -1987,6 +1988,7 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
do_blockdev_backup(backup->device, backup->target,
backup->sync,
backup->has_speed, backup->speed,
+ backup->has_compress, backup->compress,
backup->has_on_source_error, backup->on_source_error,
backup->has_on_target_error, backup->on_target_error,
common->block_job_txn, &local_err);
@@ -3335,6 +3337,7 @@ BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
void do_blockdev_backup(const char *device, const char *target,
enum MirrorSyncMode sync,
bool has_speed, int64_t speed,
+ bool has_compress, bool compress,
bool has_on_source_error,
BlockdevOnError on_source_error,
bool has_on_target_error,
@@ -3356,6 +3359,9 @@ void do_blockdev_backup(const char *device, const char *target,
if (!has_on_target_error) {
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
}
+ if (!has_compress) {
+ compress = false;
+ }
blk = blk_by_name(device);
if (!blk) {
@@ -3386,7 +3392,7 @@ void do_blockdev_backup(const char *device, const char *target,
bdrv_ref(target_bs);
bdrv_set_aio_context(target_bs, aio_context);
- backup_start(bs, target_bs, speed, sync, NULL, false, on_source_error,
+ backup_start(bs, target_bs, speed, sync, NULL, compress, on_source_error,
on_target_error, block_job_cb, bs, txn, &local_err);
if (local_err != NULL) {
bdrv_unref(target_bs);
@@ -3399,6 +3405,7 @@ out:
void qmp_blockdev_backup(const char *device, const char *target,
enum MirrorSyncMode sync,
bool has_speed, int64_t speed,
+ bool has_compress, bool compress,
bool has_on_source_error,
BlockdevOnError on_source_error,
bool has_on_target_error,
@@ -3406,6 +3413,7 @@ void qmp_blockdev_backup(const char *device, const char *target,
Error **errp)
{
do_blockdev_backup(device, target, sync, has_speed, speed,
+ has_compress, compress,
has_on_source_error, on_source_error,
has_on_target_error, on_target_error,
NULL, errp);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index ebedf0d..8e47e57 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -941,6 +941,7 @@
'data': { 'device': 'str', 'target': 'str',
'sync': 'MirrorSyncMode',
'*speed': 'int',
+ '*compress': 'bool',
'*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ce36518..ff9e491 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1241,7 +1241,7 @@ EQMP
{
.name = "blockdev-backup",
- .args_type = "sync:s,device:B,target:B,speed:i?,"
+ .args_type = "sync:s,device:B,target:B,speed:i?,compress:b?,"
"on-source-error:s?,on-target-error:s?",
.mhandler.cmd_new = qmp_marshal_blockdev_backup,
},
@@ -1263,6 +1263,7 @@ Arguments:
sectors allocated in the topmost image, or "none" to only replicate
new I/O (MirrorSyncMode).
- "speed": the maximum speed, in bytes per second (json-int, optional)
+- "compress": compress data blocks (if the target format supports it).
- "on-source-error": the action to take on an error on the source, default
'report'. 'stop' and 'enospc' can only be used
if the block device supports io-status.
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v2 3/3] qemu-iotests: test backup compression in 055
2016-04-27 6:28 [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 1/3] drive-backup: added support for data compression Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 2/3] blockdev-backup: " Denis V. Lunev
@ 2016-04-27 6:29 ` Denis V. Lunev
2016-04-27 8:56 ` [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
3 siblings, 0 replies; 5+ messages in thread
From: Denis V. Lunev @ 2016-04-27 6:29 UTC (permalink / raw)
To: qemu-devel
Cc: den, Pavel Butsykin, Jeff Cody, Markus Armbruster, Eric Blake,
John Snow
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
Added cases to check the backup compression out of qcow2, raw in qcow2
on drive-backup and blockdev-backup.
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
---
tests/qemu-iotests/055 | 97 +++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/055.out | 4 +-
tests/qemu-iotests/iotests.py | 10 ++---
3 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index c8e3578..3ac6894 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -451,5 +451,102 @@ class TestSingleTransaction(iotests.QMPTestCase):
self.assert_qmp(result, 'error/class', 'GenericError')
self.assert_no_active_block_jobs()
+
+class TestDriveCompression(iotests.QMPTestCase):
+ image_len = 64 * 1024 * 1024 # MB
+ outfmt = 'qcow2'
+
+ def setUp(self):
+ # Write data to the image so we can compare later
+ qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestDriveCompression.image_len))
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
+
+ qemu_img('create', '-f', TestDriveCompression.outfmt, blockdev_target_img,
+ str(TestDriveCompression.image_len))
+ self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img,
+ format=TestDriveCompression.outfmt)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(test_img)
+ os.remove(blockdev_target_img)
+ try:
+ os.remove(target_img)
+ except OSError:
+ pass
+
+ def do_test_compress_complete(self, cmd, **args):
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_until_completed()
+
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+ iotests.imgfmt, TestDriveCompression.outfmt),
+ 'target image does not match source after backup')
+
+ def test_complete_compress_drive_bakup(self):
+ self.do_test_compress_complete('drive-backup', target=blockdev_target_img, mode='existing')
+
+ def test_complete_compress_blockdev_backup(self):
+ self.do_test_compress_complete('blockdev-backup', target='drive1')
+
+ def do_test_compress_cancel(self, cmd, **args):
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+ self.assert_qmp(result, 'return', {})
+
+ event = self.cancel_and_wait()
+ self.assert_qmp(event, 'data/type', 'backup')
+
+ def test_compress_cancel_drive_bakup(self):
+ self.do_test_compress_cancel('drive-backup', target=blockdev_target_img, mode='existing')
+
+ def test_compress_cancel_blockdev_backup(self):
+ self.do_test_compress_cancel('blockdev-backup', target='drive1')
+
+ def do_test_compress_pause(self, cmd, **args):
+ self.assert_no_active_block_jobs()
+
+ self.vm.pause_drive('drive0')
+ result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('block-job-pause', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.resume_drive('drive0')
+ time.sleep(1)
+ result = self.vm.qmp('query-block-jobs')
+ offset = self.dictpath(result, 'return[0]/offset')
+
+ time.sleep(1)
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/offset', offset)
+
+ result = self.vm.qmp('block-job-resume', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_until_completed()
+
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+ iotests.imgfmt, TestDriveCompression.outfmt),
+ 'target image does not match source after backup')
+
+ def test_compress_pause_drive_bakup(self):
+ self.do_test_compress_pause('drive-backup', target=blockdev_target_img, mode='existing')
+
+ def test_compress_pause_blockdev_backup(self):
+ self.do_test_compress_pause('blockdev-backup', target='drive1')
+
if __name__ == '__main__':
iotests.main(supported_fmts=['raw', 'qcow2'])
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
index 42314e9..5ce2f9a 100644
--- a/tests/qemu-iotests/055.out
+++ b/tests/qemu-iotests/055.out
@@ -1,5 +1,5 @@
-........................
+..............................
----------------------------------------------------------------------
-Ran 24 tests
+Ran 30 tests
OK
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 56f988a..382771c 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -89,10 +89,10 @@ def qemu_io(*args):
sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
return subp.communicate()[0]
-def compare_images(img1, img2):
+def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
'''Return True if two image files are identical'''
- return qemu_img('compare', '-f', imgfmt,
- '-F', imgfmt, img1, img2) == 0
+ return qemu_img('compare', '-f', fmt1,
+ '-F', fmt2, img1, img2) == 0
def create_image(name, size):
'''Create a fully-allocated raw image with sector markers'''
@@ -175,14 +175,14 @@ class VM(object):
self._args.append(opts)
return self
- def add_drive(self, path, opts='', interface='virtio'):
+ def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
'''Add a virtio-blk drive to the VM'''
options = ['if=%s' % interface,
'id=drive%d' % self._num_drives]
if path is not None:
options.append('file=%s' % path)
- options.append('format=%s' % imgfmt)
+ options.append('format=%s' % format)
options.append('cache=%s' % cachemode)
if opts:
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression
2016-04-27 6:28 [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
` (2 preceding siblings ...)
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 3/3] qemu-iotests: test backup compression in 055 Denis V. Lunev
@ 2016-04-27 8:56 ` Denis V. Lunev
3 siblings, 0 replies; 5+ messages in thread
From: Denis V. Lunev @ 2016-04-27 8:56 UTC (permalink / raw)
To: qemu-devel
Cc: Pavel Butsykin, Jeff Cody, Markus Armbruster, Eric Blake,
John Snow, Stefan Hajnoczi
On 04/27/2016 09:28 AM, Denis V. Lunev wrote:
> The idea is simple - backup is "written-once" data. It is written block
> by block and it is large enough. It would be nice to save storage
> space and compress it.
>
> These patches add the ability to compress data during backup. This
> functionality is implemented by means of adding options to the qmp/hmp
> commands(drive-backup, blockdev-backup). The implementation is quite
> simple, because the responsibility for data compression imposed on the
> format driver.
>
> Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Jeff Cody <jcody@redhat.com>
> CC: Markus Armbruster <armbru@redhat.com>
> CC: Eric Blake <eblake@redhat.com>
> CC: John Snow <jsnow@redhat.com>
> CC: Stefan Hajnoczi <stefanha@redhat.com>
>
> Changes from v1:
> - added unittest for backup compression (3)
>
> Pavel Butsykin (3):
> drive-backup: added support for data compression
> blockdev-backup: added support for data compression
> qemu-iotests: test backup compression in 055
>
> block/backup.c | 13 ++++++
> blockdev.c | 20 ++++++++-
> hmp-commands.hx | 8 ++--
> hmp.c | 3 +-
> include/block/block_int.h | 1 +
> qapi/block-core.json | 3 +-
> qmp-commands.hx | 7 +++-
> tests/qemu-iotests/055 | 97 +++++++++++++++++++++++++++++++++++++++++++
> tests/qemu-iotests/055.out | 4 +-
> tests/qemu-iotests/iotests.py | 10 ++---
> 10 files changed, 150 insertions(+), 16 deletions(-)
>
pls do not spend the time with this at the moment.
Locking and some other stuff should be re-worked.
Thank you.
Den
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-04-27 8:57 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-27 6:28 [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 1/3] drive-backup: added support for data compression Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 2/3] blockdev-backup: " Denis V. Lunev
2016-04-27 6:29 ` [Qemu-devel] [PATCH v2 3/3] qemu-iotests: test backup compression in 055 Denis V. Lunev
2016-04-27 8:56 ` [Qemu-devel] [PATCH for 2.7 v2 0/3] backup compression Denis V. Lunev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).