* [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next)
@ 2013-11-29 16:45 Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 01/41] block: make BdrvRequestFlags public Kevin Wolf
` (39 more replies)
0 siblings, 40 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
The following changes since commit 7dc65c02fe3fb8f3146ce0b9ff5fec5945329f0e:
Open 2.0 development tree (2013-11-27 14:02:45 -0800)
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git tags/for-anthony
for you to fetch changes up to 981cbf59b5360647e908186e7306ee9013a58c88:
qemu-iotests: Add sample image and test for VMDK version 3 (2013-11-29 17:41:14 +0100)
----------------------------------------------------------------
Block patches for 2.0 (flushing block-next)
----------------------------------------------------------------
Charlie Shepherd (3):
Test coroutine execution order
COW: Speed up writes
COW: Extend checking allocated bits to beyond one sector
Fam Zheng (10):
block: per caller dirty bitmap
qapi: Change BlockDirtyInfo to list
qemu-iotests: Drop local version of cancel_and_wait from 040
blkdebug: add "remove_break" command
qemu-iotest: Add pause_drive and resume_drive methods
qemu-iotests: Make test case 030, 040 and 055 deterministic
qemu-iotests: Filter qemu-io output in 025
qemu-iotests: Filter out 'qemu-io> ' prompt
vmdk: Allow read only open of VMDK version 3
qemu-iotests: Add sample image and test for VMDK version 3
Kevin Wolf (5):
qdict: Fix memory leak in qdict_do_flatten()
qdict: Optimise qdict_do_flatten()
block: Enable BDRV_O_SNAPSHOT with driver-specific options
qemu-iotests: Test snapshot mode
block: Use BDRV_O_NO_BACKING where appropriate
Liu Yuan (4):
sheepdog: implement .bdrv_get_allocated_file_size
MAINTAINERS: add sheepdog development mailing list
sheepdog: refactor do_sd_create()
sheepdog: support user-defined redundancy option
Max Reitz (2):
util/error: Save errno from clobbering
block/stream: Don't stream unbacked devices
Peter Lieven (17):
block: make BdrvRequestFlags public
block: add flags to bdrv_*_write_zeroes
block: introduce BDRV_REQ_MAY_UNMAP request flag
block: add logical block provisioning info to BlockDriverInfo
block: add wrappers for logical block provisioning information
block/iscsi: add .bdrv_get_info
block: add BlockLimits structure to BlockDriverState
block/raw: copy BlockLimits on raw_open
block: honour BlockLimits in bdrv_co_do_write_zeroes
block: honour BlockLimits in bdrv_co_discard
iscsi: set limits in BlockDriverState
iscsi: simplify iscsi_co_discard
iscsi: add bdrv_co_write_zeroes
block: introduce bdrv_make_zero
block/get_block_status: fix BDRV_BLOCK_ZERO for unallocated blocks
qemu-img: add support for fully allocated images
qemu-img: conditionally zero out target on convert
MAINTAINERS | 1 +
block-migration.c | 25 +-
block.c | 364 +-
block/backup.c | 3 +-
block/blkdebug.c | 27 +
block/cow.c | 124 +-
block/iscsi.c | 150 +-
block/mirror.c | 23 +-
block/qapi.c | 9 +-
block/qcow2-cluster.c | 2 +-
block/qcow2.c | 5 +-
block/qed.c | 3 +-
block/raw_bsd.c | 6 +-
block/sheepdog.c | 130 +-
block/stream.c | 5 +
block/vmdk.c | 14 +-
include/block/block.h | 48 +-
include/block/block_int.h | 24 +-
qapi-schema.json | 6 +-
qemu-img.c | 20 +-
qemu-img.texi | 6 +
qemu-io-cmds.c | 24 +-
qobject/qdict.c | 14 +-
tests/qemu-iotests/013.out | 44080 ++++++-------
tests/qemu-iotests/014.out | 64204 +++++++++----------
tests/qemu-iotests/017.out | 1080 +-
tests/qemu-iotests/018.out | 1080 +-
tests/qemu-iotests/019.out | 1636 +-
tests/qemu-iotests/020.out | 1080 +-
tests/qemu-iotests/022.out | 8816 +--
tests/qemu-iotests/023.out | 26800 ++++----
tests/qemu-iotests/024.out | 164 +-
tests/qemu-iotests/025 | 2 +-
tests/qemu-iotests/025.out | 18 +-
tests/qemu-iotests/028.out | 458 +-
tests/qemu-iotests/030 | 16 +-
tests/qemu-iotests/032.out | 68 +-
tests/qemu-iotests/035.out | 2 +-
tests/qemu-iotests/037.out | 616 +-
tests/qemu-iotests/038.out | 714 +-
tests/qemu-iotests/040 | 19 +-
tests/qemu-iotests/046.out | 232 +-
tests/qemu-iotests/047.out | 20 +-
tests/qemu-iotests/048.out | 34 +-
tests/qemu-iotests/051 | 17 +
tests/qemu-iotests/051.out | 54 +-
tests/qemu-iotests/055 | 14 +-
tests/qemu-iotests/059 | 5 +
tests/qemu-iotests/059.out | 5 +
tests/qemu-iotests/common.filter | 3 +-
tests/qemu-iotests/iotests.py | 18 +-
.../sample_images/iotest-version3.vmdk.bz2 | Bin 0 -> 414 bytes
tests/test-coroutine.c | 54 +
util/error.c | 6 +
54 files changed, 76509 insertions(+), 75839 deletions(-)
create mode 100644 tests/qemu-iotests/sample_images/iotest-version3.vmdk.bz2
^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 01/41] block: make BdrvRequestFlags public
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 02/41] block: add flags to bdrv_*_write_zeroes Kevin Wolf
` (38 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 5 -----
include/block/block.h | 5 +++++
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/block.c b/block.c
index 382ea71..3dc6c12 100644
--- a/block.c
+++ b/block.c
@@ -51,11 +51,6 @@
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
-typedef enum {
- BDRV_REQ_COPY_ON_READ = 0x1,
- BDRV_REQ_ZERO_WRITE = 0x2,
-} BdrvRequestFlags;
-
static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
diff --git a/include/block/block.h b/include/block/block.h
index 3560deb..ba2082c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -62,6 +62,11 @@ typedef struct BlockDevOps {
void (*resize_cb)(void *opaque);
} BlockDevOps;
+typedef enum {
+ BDRV_REQ_COPY_ON_READ = 0x1,
+ BDRV_REQ_ZERO_WRITE = 0x2,
+} BdrvRequestFlags;
+
#define BDRV_O_RDWR 0x0002
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 02/41] block: add flags to bdrv_*_write_zeroes
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 01/41] block: make BdrvRequestFlags public Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 03/41] block: introduce BDRV_REQ_MAY_UNMAP request flag Kevin Wolf
` (37 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block-migration.c | 2 +-
block.c | 20 +++++++++++---------
block/backup.c | 3 ++-
block/qcow2-cluster.c | 2 +-
block/qcow2.c | 2 +-
block/qed.c | 3 ++-
block/raw_bsd.c | 5 +++--
block/vmdk.c | 3 ++-
include/block/block.h | 4 ++--
include/block/block_int.h | 2 +-
qemu-io-cmds.c | 2 +-
11 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index daf9ec1..713a8e3 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -780,7 +780,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
}
if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
- ret = bdrv_write_zeroes(bs, addr, nr_sectors);
+ ret = bdrv_write_zeroes(bs, addr, nr_sectors, 0);
} else {
buf = g_malloc(BLOCK_SIZE);
qemu_get_buffer(f, buf, BLOCK_SIZE);
diff --git a/block.c b/block.c
index 3dc6c12..e14ba48 100644
--- a/block.c
+++ b/block.c
@@ -79,7 +79,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
bool is_write);
static void coroutine_fn bdrv_co_do_rw(void *opaque);
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors);
+ int64_t sector_num, int nb_sectors, BdrvRequestFlags flags);
static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -2392,10 +2392,11 @@ int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov)
return bdrv_rwv_co(bs, sector_num, qiov, true, 0);
}
-int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
+int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, BdrvRequestFlags flags)
{
return bdrv_rw_co(bs, sector_num, NULL, nb_sectors, true,
- BDRV_REQ_ZERO_WRITE);
+ BDRV_REQ_ZERO_WRITE | flags);
}
int bdrv_pread(BlockDriverState *bs, int64_t offset,
@@ -2577,7 +2578,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
if (drv->bdrv_co_write_zeroes &&
buffer_is_zero(bounce_buffer, iov.iov_len)) {
ret = bdrv_co_do_write_zeroes(bs, cluster_sector_num,
- cluster_nb_sectors);
+ cluster_nb_sectors, 0);
} else {
/* This does not change the data on the disk, it is not necessary
* to flush even in cache=writethrough mode.
@@ -2711,7 +2712,7 @@ int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,
}
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors)
+ int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
{
BlockDriver *drv = bs->drv;
QEMUIOVector qiov;
@@ -2723,7 +2724,7 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
/* First try the efficient write zeroes operation */
if (drv->bdrv_co_write_zeroes) {
- ret = drv->bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
+ ret = drv->bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);
if (ret != -ENOTSUP) {
return ret;
}
@@ -2778,7 +2779,7 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
if (ret < 0) {
/* Do nothing, write notifier decided to fail this request */
} else if (flags & BDRV_REQ_ZERO_WRITE) {
- ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors);
+ ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors, flags);
} else {
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
}
@@ -2812,12 +2813,13 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
}
int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors)
+ int64_t sector_num, int nb_sectors,
+ BdrvRequestFlags flags)
{
trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
- BDRV_REQ_ZERO_WRITE);
+ BDRV_REQ_ZERO_WRITE | flags);
}
/**
diff --git a/block/backup.c b/block/backup.c
index cad14c9..830a179 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -138,7 +138,8 @@ static int coroutine_fn backup_do_cow(BlockDriverState *bs,
if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
ret = bdrv_co_write_zeroes(job->target,
- start * BACKUP_SECTORS_PER_CLUSTER, n);
+ start * BACKUP_SECTORS_PER_CLUSTER,
+ n, 0);
} else {
ret = bdrv_co_writev(job->target,
start * BACKUP_SECTORS_PER_CLUSTER, n,
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 791083a..11f9c50 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1613,7 +1613,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
}
ret = bdrv_write_zeroes(bs->file, offset / BDRV_SECTOR_SIZE,
- s->cluster_sectors);
+ s->cluster_sectors, 0);
if (ret < 0) {
if (!preallocated) {
qcow2_free_clusters(bs, offset, s->cluster_size,
diff --git a/block/qcow2.c b/block/qcow2.c
index 6e5d98d..2fe37ed 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1696,7 +1696,7 @@ static int qcow2_make_empty(BlockDriverState *bs)
}
static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors)
+ int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
{
int ret;
BDRVQcowState *s = bs->opaque;
diff --git a/block/qed.c b/block/qed.c
index 6c0cba0..adc2736 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1397,7 +1397,8 @@ static void coroutine_fn qed_co_write_zeroes_cb(void *opaque, int ret)
static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
int64_t sector_num,
- int nb_sectors)
+ int nb_sectors,
+ BdrvRequestFlags flags)
{
BlockDriverAIOCB *blockacb;
BDRVQEDState *s = bs->opaque;
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 2265dcc..fb5181b 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -68,9 +68,10 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
}
static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors)
+ int64_t sector_num, int nb_sectors,
+ BdrvRequestFlags flags)
{
- return bdrv_co_write_zeroes(bs->file, sector_num, nb_sectors);
+ return bdrv_co_write_zeroes(bs->file, sector_num, nb_sectors, flags);
}
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
diff --git a/block/vmdk.c b/block/vmdk.c
index a7ebd0f..6555663 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1419,7 +1419,8 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
int64_t sector_num,
- int nb_sectors)
+ int nb_sectors,
+ BdrvRequestFlags flags)
{
int ret;
BDRVVmdkState *s = bs->opaque;
diff --git a/include/block/block.h b/include/block/block.h
index ba2082c..8ba9f0c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -192,7 +192,7 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors);
+ int nb_sectors, BdrvRequestFlags flags);
int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov);
int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count);
@@ -214,7 +214,7 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
* because it may allocate memory for the entire region.
*/
int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors);
+ int nb_sectors, BdrvRequestFlags flags);
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
const char *backing_file);
int bdrv_get_backing_file_depth(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1666066..d798208 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -130,7 +130,7 @@ struct BlockDriver {
* instead.
*/
int coroutine_fn (*bdrv_co_write_zeroes)(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors);
+ int64_t sector_num, int nb_sectors, BdrvRequestFlags flags);
int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors);
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 667f4e4..7e9fecb 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -442,7 +442,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
CoWriteZeroes *data = opaque;
data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
- data->count / BDRV_SECTOR_SIZE);
+ data->count / BDRV_SECTOR_SIZE, 0);
data->done = true;
if (data->ret < 0) {
*data->total = data->ret;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 03/41] block: introduce BDRV_REQ_MAY_UNMAP request flag
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 01/41] block: make BdrvRequestFlags public Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 02/41] block: add flags to bdrv_*_write_zeroes Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 04/41] block: add logical block provisioning info to BlockDriverInfo Kevin Wolf
` (36 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block-migration.c | 3 ++-
block.c | 4 ++++
block/backup.c | 2 +-
include/block/block.h | 7 +++++++
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index 713a8e3..fc4ef93 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -780,7 +780,8 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
}
if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
- ret = bdrv_write_zeroes(bs, addr, nr_sectors, 0);
+ ret = bdrv_write_zeroes(bs, addr, nr_sectors,
+ BDRV_REQ_MAY_UNMAP);
} else {
buf = g_malloc(BLOCK_SIZE);
qemu_get_buffer(f, buf, BLOCK_SIZE);
diff --git a/block.c b/block.c
index e14ba48..d34e974 100644
--- a/block.c
+++ b/block.c
@@ -2818,6 +2818,10 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
{
trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
+ if (!(bs->open_flags & BDRV_O_UNMAP)) {
+ flags &= ~BDRV_REQ_MAY_UNMAP;
+ }
+
return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
BDRV_REQ_ZERO_WRITE | flags);
}
diff --git a/block/backup.c b/block/backup.c
index 830a179..0198514 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -139,7 +139,7 @@ static int coroutine_fn backup_do_cow(BlockDriverState *bs,
if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
ret = bdrv_co_write_zeroes(job->target,
start * BACKUP_SECTORS_PER_CLUSTER,
- n, 0);
+ n, BDRV_REQ_MAY_UNMAP);
} else {
ret = bdrv_co_writev(job->target,
start * BACKUP_SECTORS_PER_CLUSTER, n,
diff --git a/include/block/block.h b/include/block/block.h
index 8ba9f0c..1f30a56 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -65,6 +65,13 @@ typedef struct BlockDevOps {
typedef enum {
BDRV_REQ_COPY_ON_READ = 0x1,
BDRV_REQ_ZERO_WRITE = 0x2,
+ /* The BDRV_REQ_MAY_UNMAP flag is used to indicate that the block driver
+ * is allowed to optimize a write zeroes request by unmapping (discarding)
+ * blocks if it is guaranteed that the result will read back as
+ * zeroes. The flag is only passed to the driver if the block device is
+ * opened with BDRV_O_UNMAP.
+ */
+ BDRV_REQ_MAY_UNMAP = 0x4,
} BdrvRequestFlags;
#define BDRV_O_RDWR 0x0002
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 04/41] block: add logical block provisioning info to BlockDriverInfo
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (2 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 03/41] block: introduce BDRV_REQ_MAY_UNMAP request flag Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 05/41] block: add wrappers for logical block provisioning information Kevin Wolf
` (35 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
include/block/block.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/include/block/block.h b/include/block/block.h
index 1f30a56..9c76967 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -18,6 +18,22 @@ typedef struct BlockDriverInfo {
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
bool is_dirty;
+ /*
+ * True if unallocated blocks read back as zeroes. This is equivalent
+ * to the the LBPRZ flag in the SCSI logical block provisioning page.
+ */
+ bool unallocated_blocks_are_zero;
+ /*
+ * True if the driver can optimize writing zeroes by unmapping
+ * sectors. This is equivalent to the BLKDISCARDZEROES ioctl in Linux
+ * with the difference that in qemu a discard is allowed to silently
+ * fail. Therefore we have to use bdrv_write_zeroes with the
+ * BDRV_REQ_MAY_UNMAP flag for an optimized zero write with unmapping.
+ * After this call the driver has to guarantee that the contents read
+ * back as zero. It is additionally required that the block device is
+ * opened with BDRV_O_UNMAP flag for this to work.
+ */
+ bool can_write_zeroes_with_unmap;
} BlockDriverInfo;
typedef struct BlockFragInfo {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 05/41] block: add wrappers for logical block provisioning information
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (3 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 04/41] block: add logical block provisioning info to BlockDriverInfo Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 06/41] block/iscsi: add .bdrv_get_info Kevin Wolf
` (34 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
This adds 2 wrappers to read the unallocated_blocks_are_zero and
can_write_zeroes_with_unmap info from the BDI. The wrappers are
required to check for the existence of a backing_hd and
if the devices are opened with the correct flags.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 30 ++++++++++++++++++++++++++++++
include/block/block.h | 2 ++
2 files changed, 32 insertions(+)
diff --git a/block.c b/block.c
index d34e974..3759582 100644
--- a/block.c
+++ b/block.c
@@ -3103,6 +3103,36 @@ int bdrv_has_zero_init(BlockDriverState *bs)
return 0;
}
+bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
+{
+ BlockDriverInfo bdi;
+
+ if (bs->backing_hd) {
+ return false;
+ }
+
+ if (bdrv_get_info(bs, &bdi) == 0) {
+ return bdi.unallocated_blocks_are_zero;
+ }
+
+ return false;
+}
+
+bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
+{
+ BlockDriverInfo bdi;
+
+ if (bs->backing_hd || !(bs->open_flags & BDRV_O_UNMAP)) {
+ return false;
+ }
+
+ if (bdrv_get_info(bs, &bdi) == 0) {
+ return bdi.can_write_zeroes_with_unmap;
+ }
+
+ return false;
+}
+
typedef struct BdrvCoGetBlockStatusData {
BlockDriverState *bs;
BlockDriverState *base;
diff --git a/include/block/block.h b/include/block/block.h
index 9c76967..803c5ca 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -344,6 +344,8 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
int bdrv_has_zero_init_1(BlockDriverState *bs);
int bdrv_has_zero_init(BlockDriverState *bs);
+bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
+bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 06/41] block/iscsi: add .bdrv_get_info
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (4 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 05/41] block: add wrappers for logical block provisioning information Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 07/41] block: add BlockLimits structure to BlockDriverState Kevin Wolf
` (33 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/iscsi.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/block/iscsi.c b/block/iscsi.c
index a2d578c..3095887 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1506,6 +1506,14 @@ out:
return ret;
}
+static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+ IscsiLun *iscsilun = bs->opaque;
+ bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
+ bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
+ return 0;
+}
+
static QEMUOptionParameter iscsi_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@@ -1527,6 +1535,7 @@ static BlockDriver bdrv_iscsi = {
.create_options = iscsi_create_options,
.bdrv_getlength = iscsi_getlength,
+ .bdrv_get_info = iscsi_get_info,
.bdrv_truncate = iscsi_truncate,
#if defined(LIBISCSI_FEATURE_IOVECTOR)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 07/41] block: add BlockLimits structure to BlockDriverState
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (5 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 06/41] block/iscsi: add .bdrv_get_info Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 08/41] block/raw: copy BlockLimits on raw_open Kevin Wolf
` (32 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
this patch adds BlockLimits which introduces discard and write_zeroes
limits and alignment information to the BlockDriverState.
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
include/block/block_int.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d798208..95140b6 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -230,6 +230,20 @@ struct BlockDriver {
QLIST_ENTRY(BlockDriver) list;
};
+typedef struct BlockLimits {
+ /* maximum number of sectors that can be discarded at once */
+ int max_discard;
+
+ /* optimal alignment for discard requests in sectors */
+ int64_t discard_alignment;
+
+ /* maximum number of sectors that can zeroized at once */
+ int max_write_zeroes;
+
+ /* optimal alignment for write zeroes requests in sectors */
+ int64_t write_zeroes_alignment;
+} BlockLimits;
+
/*
* Note: the function bdrv_append() copies and swaps contents of
* BlockDriverStates, so if you add new fields to this struct, please
@@ -283,6 +297,9 @@ struct BlockDriverState {
uint64_t total_time_ns[BDRV_MAX_IOTYPE];
uint64_t wr_highest_sector;
+ /* I/O Limits */
+ BlockLimits bl;
+
/* Whether the disk can expand beyond total_sectors */
int growable;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 08/41] block/raw: copy BlockLimits on raw_open
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (6 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 07/41] block: add BlockLimits structure to BlockDriverState Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 09/41] block: honour BlockLimits in bdrv_co_do_write_zeroes Kevin Wolf
` (31 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/raw_bsd.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index fb5181b..978ae7a 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -150,6 +150,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
bs->sg = bs->file->sg;
+ bs->bl = bs->file->bl;
return 0;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 09/41] block: honour BlockLimits in bdrv_co_do_write_zeroes
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (7 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 08/41] block/raw: copy BlockLimits on raw_open Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 10/41] block: honour BlockLimits in bdrv_co_discard Kevin Wolf
` (30 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 49 insertions(+), 16 deletions(-)
diff --git a/block.c b/block.c
index 3759582..b4194da 100644
--- a/block.c
+++ b/block.c
@@ -2711,32 +2711,65 @@ int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,
BDRV_REQ_COPY_ON_READ);
}
+/* if no limit is specified in the BlockLimits use a default
+ * of 32768 512-byte sectors (16 MiB) per request.
+ */
+#define MAX_WRITE_ZEROES_DEFAULT 32768
+
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
{
BlockDriver *drv = bs->drv;
QEMUIOVector qiov;
- struct iovec iov;
- int ret;
+ struct iovec iov = {0};
+ int ret = 0;
- /* TODO Emulate only part of misaligned requests instead of letting block
- * drivers return -ENOTSUP and emulate everything */
+ int max_write_zeroes = bs->bl.max_write_zeroes ?
+ bs->bl.max_write_zeroes : MAX_WRITE_ZEROES_DEFAULT;
- /* First try the efficient write zeroes operation */
- if (drv->bdrv_co_write_zeroes) {
- ret = drv->bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);
- if (ret != -ENOTSUP) {
- return ret;
+ while (nb_sectors > 0 && !ret) {
+ int num = nb_sectors;
+
+ /* align request */
+ if (bs->bl.write_zeroes_alignment &&
+ num >= bs->bl.write_zeroes_alignment &&
+ sector_num % bs->bl.write_zeroes_alignment) {
+ if (num > bs->bl.write_zeroes_alignment) {
+ num = bs->bl.write_zeroes_alignment;
+ }
+ num -= sector_num % bs->bl.write_zeroes_alignment;
}
- }
- /* Fall back to bounce buffer if write zeroes is unsupported */
- iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
- iov.iov_base = qemu_blockalign(bs, iov.iov_len);
- memset(iov.iov_base, 0, iov.iov_len);
- qemu_iovec_init_external(&qiov, &iov, 1);
+ /* limit request size */
+ if (num > max_write_zeroes) {
+ num = max_write_zeroes;
+ }
+
+ ret = -ENOTSUP;
+ /* First try the efficient write zeroes operation */
+ if (drv->bdrv_co_write_zeroes) {
+ ret = drv->bdrv_co_write_zeroes(bs, sector_num, num, flags);
+ }
+
+ if (ret == -ENOTSUP) {
+ /* Fall back to bounce buffer if write zeroes is unsupported */
+ iov.iov_len = num * BDRV_SECTOR_SIZE;
+ if (iov.iov_base == NULL) {
+ /* allocate bounce buffer only once and ensure that it
+ * is big enough for this and all future requests.
+ */
+ size_t bufsize = num <= nb_sectors ? num : max_write_zeroes;
+ iov.iov_base = qemu_blockalign(bs, bufsize * BDRV_SECTOR_SIZE);
+ memset(iov.iov_base, 0, bufsize * BDRV_SECTOR_SIZE);
+ }
+ qemu_iovec_init_external(&qiov, &iov, 1);
- ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, &qiov);
+ ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov);
+ }
+
+ sector_num += num;
+ nb_sectors -= num;
+ }
qemu_vfree(iov.iov_base);
return ret;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 10/41] block: honour BlockLimits in bdrv_co_discard
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (8 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 09/41] block: honour BlockLimits in bdrv_co_do_write_zeroes Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 11/41] iscsi: set limits in BlockDriverState Kevin Wolf
` (29 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/block.c b/block.c
index b4194da..df5a603 100644
--- a/block.c
+++ b/block.c
@@ -4243,6 +4243,11 @@ static void coroutine_fn bdrv_discard_co_entry(void *opaque)
rwco->ret = bdrv_co_discard(rwco->bs, rwco->sector_num, rwco->nb_sectors);
}
+/* if no limit is specified in the BlockLimits use a default
+ * of 32768 512-byte sectors (16 MiB) per request.
+ */
+#define MAX_DISCARD_DEFAULT 32768
+
int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
@@ -4264,7 +4269,37 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
}
if (bs->drv->bdrv_co_discard) {
- return bs->drv->bdrv_co_discard(bs, sector_num, nb_sectors);
+ int max_discard = bs->bl.max_discard ?
+ bs->bl.max_discard : MAX_DISCARD_DEFAULT;
+
+ while (nb_sectors > 0) {
+ int ret;
+ int num = nb_sectors;
+
+ /* align request */
+ if (bs->bl.discard_alignment &&
+ num >= bs->bl.discard_alignment &&
+ sector_num % bs->bl.discard_alignment) {
+ if (num > bs->bl.discard_alignment) {
+ num = bs->bl.discard_alignment;
+ }
+ num -= sector_num % bs->bl.discard_alignment;
+ }
+
+ /* limit request size */
+ if (num > max_discard) {
+ num = max_discard;
+ }
+
+ ret = bs->drv->bdrv_co_discard(bs, sector_num, num);
+ if (ret) {
+ return ret;
+ }
+
+ sector_num += num;
+ nb_sectors -= num;
+ }
+ return 0;
} else if (bs->drv->bdrv_aio_discard) {
BlockDriverAIOCB *acb;
CoroutineIOCompletion co = {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 11/41] iscsi: set limits in BlockDriverState
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (9 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 10/41] block: honour BlockLimits in bdrv_co_discard Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 12/41] iscsi: simplify iscsi_co_discard Kevin Wolf
` (28 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/iscsi.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/block/iscsi.c b/block/iscsi.c
index 3095887..1cafa78 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1384,6 +1384,20 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
sizeof(struct scsi_inquiry_block_limits));
scsi_free_scsi_task(task);
task = NULL;
+
+ if (iscsilun->bl.max_unmap < 0xffffffff) {
+ bs->bl.max_discard = sector_lun2qemu(iscsilun->bl.max_unmap,
+ iscsilun);
+ }
+ bs->bl.discard_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
+ iscsilun);
+
+ if (iscsilun->bl.max_ws_len < 0xffffffff) {
+ bs->bl.max_write_zeroes = sector_lun2qemu(iscsilun->bl.max_ws_len,
+ iscsilun);
+ }
+ bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
+ iscsilun);
}
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 12/41] iscsi: simplify iscsi_co_discard
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (10 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 11/41] iscsi: set limits in BlockDriverState Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 13/41] iscsi: add bdrv_co_write_zeroes Kevin Wolf
` (27 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
now that bdrv_co_discard can handle limits we do not need
the request split logic here anymore.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/iscsi.c | 67 ++++++++++++++++++++++-------------------------------------
1 file changed, 25 insertions(+), 42 deletions(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 1cafa78..f91134e 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -87,7 +87,6 @@ typedef struct IscsiAIOCB {
#define NOP_INTERVAL 5000
#define MAX_NOP_FAILURES 3
#define ISCSI_CMD_RETRIES 5
-#define ISCSI_MAX_UNMAP 131072
static void
iscsi_bh_cb(void *p)
@@ -912,8 +911,6 @@ coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
IscsiLun *iscsilun = bs->opaque;
struct IscsiTask iTask;
struct unmap_list list;
- uint32_t nb_blocks;
- uint32_t max_unmap;
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
return -EINVAL;
@@ -925,52 +922,38 @@ coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
}
list.lba = sector_qemu2lun(sector_num, iscsilun);
- nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
+ list.num = sector_qemu2lun(nb_sectors, iscsilun);
- max_unmap = iscsilun->bl.max_unmap;
- if (max_unmap == 0xffffffff) {
- max_unmap = ISCSI_MAX_UNMAP;
- }
-
- while (nb_blocks > 0) {
- iscsi_co_init_iscsitask(iscsilun, &iTask);
- list.num = nb_blocks;
- if (list.num > max_unmap) {
- list.num = max_unmap;
- }
+ iscsi_co_init_iscsitask(iscsilun, &iTask);
retry:
- if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,
- iscsi_co_generic_cb, &iTask) == NULL) {
- return -EIO;
- }
-
- while (!iTask.complete) {
- iscsi_set_events(iscsilun);
- qemu_coroutine_yield();
- }
+ if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,
+ iscsi_co_generic_cb, &iTask) == NULL) {
+ return -EIO;
+ }
- if (iTask.task != NULL) {
- scsi_free_scsi_task(iTask.task);
- iTask.task = NULL;
- }
+ while (!iTask.complete) {
+ iscsi_set_events(iscsilun);
+ qemu_coroutine_yield();
+ }
- if (iTask.do_retry) {
- goto retry;
- }
+ if (iTask.task != NULL) {
+ scsi_free_scsi_task(iTask.task);
+ iTask.task = NULL;
+ }
- if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
- /* the target might fail with a check condition if it
- is not happy with the alignment of the UNMAP request
- we silently fail in this case */
- return 0;
- }
+ if (iTask.do_retry) {
+ goto retry;
+ }
- if (iTask.status != SCSI_STATUS_GOOD) {
- return -EIO;
- }
+ if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
+ /* the target might fail with a check condition if it
+ is not happy with the alignment of the UNMAP request
+ we silently fail in this case */
+ return 0;
+ }
- list.lba += list.num;
- nb_blocks -= list.num;
+ if (iTask.status != SCSI_STATUS_GOOD) {
+ return -EIO;
}
return 0;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 13/41] iscsi: add bdrv_co_write_zeroes
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (11 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 12/41] iscsi: simplify iscsi_co_discard Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 14/41] block: introduce bdrv_make_zero Kevin Wolf
` (26 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/iscsi.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/block/iscsi.c b/block/iscsi.c
index f91134e..b7b5238 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -56,6 +56,7 @@ typedef struct IscsiLun {
uint8_t lbprz;
struct scsi_inquiry_logical_block_provisioning lbp;
struct scsi_inquiry_block_limits bl;
+ unsigned char *zeroblock;
} IscsiLun;
typedef struct IscsiTask {
@@ -959,6 +960,65 @@ retry:
return 0;
}
+#if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED)
+
+static int
+coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, BdrvRequestFlags flags)
+{
+ IscsiLun *iscsilun = bs->opaque;
+ struct IscsiTask iTask;
+ uint64_t lba;
+ uint32_t nb_blocks;
+
+ if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
+ return -EINVAL;
+ }
+
+ if (!iscsilun->lbp.lbpws) {
+ /* WRITE SAME is not supported by the target */
+ return -ENOTSUP;
+ }
+
+ lba = sector_qemu2lun(sector_num, iscsilun);
+ nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
+
+ if (iscsilun->zeroblock == NULL) {
+ iscsilun->zeroblock = g_malloc0(iscsilun->block_size);
+ }
+
+ iscsi_co_init_iscsitask(iscsilun, &iTask);
+retry:
+ if (iscsi_writesame16_task(iscsilun->iscsi, iscsilun->lun, lba,
+ iscsilun->zeroblock, iscsilun->block_size,
+ nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
+ 0, 0, iscsi_co_generic_cb, &iTask) == NULL) {
+ return -EIO;
+ }
+
+ while (!iTask.complete) {
+ iscsi_set_events(iscsilun);
+ qemu_coroutine_yield();
+ }
+
+ if (iTask.task != NULL) {
+ scsi_free_scsi_task(iTask.task);
+ iTask.task = NULL;
+ }
+
+ if (iTask.do_retry) {
+ goto retry;
+ }
+
+ if (iTask.status != SCSI_STATUS_GOOD) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#endif /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED */
+
static int parse_chap(struct iscsi_context *iscsi, const char *target)
{
QemuOptsList *list;
@@ -1421,6 +1481,7 @@ static void iscsi_close(BlockDriverState *bs)
}
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
iscsi_destroy_context(iscsi);
+ g_free(iscsilun->zeroblock);
memset(iscsilun, 0, sizeof(IscsiLun));
}
@@ -1539,6 +1600,9 @@ static BlockDriver bdrv_iscsi = {
.bdrv_co_get_block_status = iscsi_co_get_block_status,
#endif
.bdrv_co_discard = iscsi_co_discard,
+#if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED)
+ .bdrv_co_write_zeroes = iscsi_co_write_zeroes,
+#endif
.bdrv_aio_readv = iscsi_aio_readv,
.bdrv_aio_writev = iscsi_aio_writev,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 14/41] block: introduce bdrv_make_zero
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (12 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 13/41] iscsi: add bdrv_co_write_zeroes Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 15/41] block/get_block_status: fix BDRV_BLOCK_ZERO for unallocated blocks Kevin Wolf
` (25 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
this patch adds a call to completely zero out a block device.
the operation is sped up by checking the block status and
only writing zeroes to the device if they currently do not
return zeroes. optionally the zero writing can be sped up
by setting the flag BDRV_REQ_MAY_UNMAP to emulate the zero
write by unmapping if the driver supports it.
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 37 +++++++++++++++++++++++++++++++++++++
include/block/block.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/block.c b/block.c
index df5a603..c390f20 100644
--- a/block.c
+++ b/block.c
@@ -2399,6 +2399,43 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
BDRV_REQ_ZERO_WRITE | flags);
}
+/*
+ * Completely zero out a block device with the help of bdrv_write_zeroes.
+ * The operation is sped up by checking the block status and only writing
+ * zeroes to the device if they currently do not return zeroes. Optional
+ * flags are passed through to bdrv_write_zeroes (e.g. BDRV_REQ_MAY_UNMAP).
+ *
+ * Returns < 0 on error, 0 on success. For error codes see bdrv_write().
+ */
+int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
+{
+ int64_t target_size = bdrv_getlength(bs) / BDRV_SECTOR_SIZE;
+ int64_t ret, nb_sectors, sector_num = 0;
+ int n;
+
+ for (;;) {
+ nb_sectors = target_size - sector_num;
+ if (nb_sectors <= 0) {
+ return 0;
+ }
+ if (nb_sectors > INT_MAX) {
+ nb_sectors = INT_MAX;
+ }
+ ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n);
+ if (ret & BDRV_BLOCK_ZERO) {
+ sector_num += n;
+ continue;
+ }
+ ret = bdrv_write_zeroes(bs, sector_num, n, flags);
+ if (ret < 0) {
+ error_report("error writing zeroes at sector %" PRId64 ": %s",
+ sector_num, strerror(-ret));
+ return ret;
+ }
+ sector_num += n;
+ }
+}
+
int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count1)
{
diff --git a/include/block/block.h b/include/block/block.h
index 803c5ca..4d9e67c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -216,6 +216,7 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, BdrvRequestFlags flags);
+int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags);
int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov);
int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 15/41] block/get_block_status: fix BDRV_BLOCK_ZERO for unallocated blocks
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (13 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 14/41] block: introduce bdrv_make_zero Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 16/41] qemu-img: add support for fully allocated images Kevin Wolf
` (24 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
this patch does 2 things:
a) only do additional call outs if BDRV_BLOCK_ZERO is not already set.
b) use the newly introduced bdrv_unallocated_blocks_are_zero()
to return the zero state of an unallocated block. the used callout
to bdrv_has_zero_init() is only valid right after bdrv_create.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block.c b/block.c
index c390f20..e22b55f 100644
--- a/block.c
+++ b/block.c
@@ -3272,8 +3272,8 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
*pnum, pnum);
}
- if (!(ret & BDRV_BLOCK_DATA)) {
- if (bdrv_has_zero_init(bs)) {
+ if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) {
+ if (bdrv_unallocated_blocks_are_zero(bs)) {
ret |= BDRV_BLOCK_ZERO;
} else if (bs->backing_hd) {
BlockDriverState *bs2 = bs->backing_hd;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 16/41] qemu-img: add support for fully allocated images
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (14 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 15/41] block/get_block_status: fix BDRV_BLOCK_ZERO for unallocated blocks Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 17/41] qemu-img: conditionally zero out target on convert Kevin Wolf
` (23 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
qemu-img.c | 10 +++++++---
qemu-img.texi | 6 ++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index b6b5644..cc3fed7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -100,8 +100,12 @@ static void help(void)
" '-h' with or without a command shows this help and lists the supported formats\n"
" '-p' show progress of command (only certain commands)\n"
" '-q' use Quiet mode - do not print any output (except errors)\n"
- " '-S' indicates the consecutive number of bytes that must contain only zeros\n"
- " for qemu-img to create a sparse image during conversion\n"
+ " '-S' indicates the consecutive number of bytes (defaults to 4k) that must\n"
+ " contain only zeros for qemu-img to create a sparse image during\n"
+ " conversion. If the number of bytes is 0, the source will not be scanned for\n"
+ " unallocated or zero sectors, and the destination image will always be\n"
+ " fully allocated\n"
+ " images will always be fully allocated\n"
" '--output' takes the format in which the output must be done (human or json)\n"
" '-n' skips the target volume creation (useful if the volume is created\n"
" prior to running qemu-img)\n"
@@ -1465,7 +1469,7 @@ static int img_convert(int argc, char **argv)
/* signal EOF to align */
bdrv_write_compressed(out_bs, 0, NULL, 0);
} else {
- int has_zero_init = bdrv_has_zero_init(out_bs);
+ int has_zero_init = min_sparse ? bdrv_has_zero_init(out_bs) : 0;
sector_num = 0; // total number of sectors converted so far
nb_sectors = total_sectors - sector_num;
diff --git a/qemu-img.texi b/qemu-img.texi
index 768054e..da36975 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -193,6 +193,12 @@ Image conversion is also useful to get smaller image when using a
growable format such as @code{qcow} or @code{cow}: the empty sectors
are detected and suppressed from the destination image.
+@var{sparse_size} indicates the consecutive number of bytes (defaults to 4k)
+that must contain only zeros for qemu-img to create a sparse image during
+conversion. If @var{sparse_size} is 0, the source will not be scanned for
+unallocated or zero sectors, and the destination image will always be
+fully allocated.
+
You can use the @var{backing_file} option to force the output image to be
created as a copy on write image of the specified base image; the
@var{backing_file} should have the same content as the input's base image,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 17/41] qemu-img: conditionally zero out target on convert
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (15 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 16/41] qemu-img: add support for fully allocated images Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 18/41] util/error: Save errno from clobbering Kevin Wolf
` (22 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Peter Lieven <pl@kamp.de>
If the target has_zero_init = 0, but supports efficiently
writing zeroes by unmapping we call bdrv_make_zero to
avoid fully allocating the target. This currently works
only for iscsi. It can be extended to raw with
BLKDISCARDZEROES for example.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
qemu-img.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/qemu-img.c b/qemu-img.c
index cc3fed7..dc0c2f0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1355,7 +1355,7 @@ static int img_convert(int argc, char **argv)
}
}
- flags = BDRV_O_RDWR;
+ flags = min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
@@ -1471,6 +1471,14 @@ static int img_convert(int argc, char **argv)
} else {
int has_zero_init = min_sparse ? bdrv_has_zero_init(out_bs) : 0;
+ if (!has_zero_init && bdrv_can_write_zeroes_with_unmap(out_bs)) {
+ ret = bdrv_make_zero(out_bs, BDRV_REQ_MAY_UNMAP);
+ if (ret < 0) {
+ goto out;
+ }
+ has_zero_init = 1;
+ }
+
sector_num = 0; // total number of sectors converted so far
nb_sectors = total_sectors - sector_num;
if (nb_sectors != 0) {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 18/41] util/error: Save errno from clobbering
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (16 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 17/41] qemu-img: conditionally zero out target on convert Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 19/41] Test coroutine execution order Kevin Wolf
` (21 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Max Reitz <mreitz@redhat.com>
There may be calls to error_setg() and especially error_setg_errno()
which blindly (and until now wrongly) assume these functions not to
clobber errno (e.g., they pass errno to error_setg_errno() and return
-errno afterwards). Instead of trying to find and fix all of these
constructs, just make sure error_setg() and error_setg_errno() indeed do
not clobber errno.
Suggested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
util/error.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/util/error.c b/util/error.c
index ec0faa6..3ee362a 100644
--- a/util/error.c
+++ b/util/error.c
@@ -27,6 +27,7 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
{
Error *err;
va_list ap;
+ int saved_errno = errno;
if (errp == NULL) {
return;
@@ -41,6 +42,8 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
err->err_class = err_class;
*errp = err;
+
+ errno = saved_errno;
}
void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
@@ -49,6 +52,7 @@ void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
Error *err;
char *msg1;
va_list ap;
+ int saved_errno = errno;
if (errp == NULL) {
return;
@@ -69,6 +73,8 @@ void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
err->err_class = err_class;
*errp = err;
+
+ errno = saved_errno;
}
void error_setg_file_open(Error **errp, int os_errno, const char *filename)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 19/41] Test coroutine execution order
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (17 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 18/41] util/error: Save errno from clobbering Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 20/41] sheepdog: implement .bdrv_get_allocated_file_size Kevin Wolf
` (20 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Charlie Shepherd <charlie@ctshepherd.com>
This patch adds a test for coroutine execution order in test-coroutine -
this catches a bug in the CPC coroutine implementation.
Signed-off-by: Charlie Shepherd <charlie@ctshepherd.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/test-coroutine.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
index 15a885e..760636d 100644
--- a/tests/test-coroutine.c
+++ b/tests/test-coroutine.c
@@ -150,6 +150,59 @@ static void test_lifecycle(void)
g_assert(done); /* expect done to be true (second time) */
}
+
+#define RECORD_SIZE 10 /* Leave some room for expansion */
+struct coroutine_position {
+ int func;
+ int state;
+};
+static struct coroutine_position records[RECORD_SIZE];
+static unsigned record_pos;
+
+static void record_push(int func, int state)
+{
+ struct coroutine_position *cp = &records[record_pos++];
+ g_assert_cmpint(record_pos, <, RECORD_SIZE);
+ cp->func = func;
+ cp->state = state;
+}
+
+static void coroutine_fn co_order_test(void *opaque)
+{
+ record_push(2, 1);
+ g_assert(qemu_in_coroutine());
+ qemu_coroutine_yield();
+ record_push(2, 2);
+ g_assert(qemu_in_coroutine());
+}
+
+static void do_order_test(void)
+{
+ Coroutine *co;
+
+ co = qemu_coroutine_create(co_order_test);
+ record_push(1, 1);
+ qemu_coroutine_enter(co, NULL);
+ record_push(1, 2);
+ g_assert(!qemu_in_coroutine());
+ qemu_coroutine_enter(co, NULL);
+ record_push(1, 3);
+ g_assert(!qemu_in_coroutine());
+}
+
+static void test_order(void)
+{
+ int i;
+ const struct coroutine_position expected_pos[] = {
+ {1, 1,}, {2, 1}, {1, 2}, {2, 2}, {1, 3}
+ };
+ do_order_test();
+ g_assert_cmpint(record_pos, ==, 5);
+ for (i = 0; i < record_pos; i++) {
+ g_assert_cmpint(records[i].func , ==, expected_pos[i].func );
+ g_assert_cmpint(records[i].state, ==, expected_pos[i].state);
+ }
+}
/*
* Lifecycle benchmark
*/
@@ -243,6 +296,7 @@ int main(int argc, char **argv)
g_test_add_func("/basic/nesting", test_nesting);
g_test_add_func("/basic/self", test_self);
g_test_add_func("/basic/in_coroutine", test_in_coroutine);
+ g_test_add_func("/basic/order", test_order);
if (g_test_perf()) {
g_test_add_func("/perf/lifecycle", perf_lifecycle);
g_test_add_func("/perf/nesting", perf_nesting);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 20/41] sheepdog: implement .bdrv_get_allocated_file_size
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (18 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 19/41] Test coroutine execution order Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 21/41] block/stream: Don't stream unbacked devices Kevin Wolf
` (19 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Liu Yuan <namei.unix@gmail.com>
With this patch, qemu-img info sheepdog:image will show disk size for sheepdog
images.
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Liu Yuan <namei.unix@gmail.com>
Reviewed-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/sheepdog.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index ef387de..252d7ad 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2407,6 +2407,22 @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
return ret;
}
+static int64_t sd_get_allocated_file_size(BlockDriverState *bs)
+{
+ BDRVSheepdogState *s = bs->opaque;
+ SheepdogInode *inode = &s->inode;
+ unsigned long i, last = DIV_ROUND_UP(inode->vdi_size, SD_DATA_OBJ_SIZE);
+ uint64_t size = 0;
+
+ for (i = 0; i < last; i++) {
+ if (inode->data_vdi_id[i] == 0) {
+ continue;
+ }
+ size += SD_DATA_OBJ_SIZE;
+ }
+ return size;
+}
+
static QEMUOptionParameter sd_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@@ -2436,6 +2452,7 @@ static BlockDriver bdrv_sheepdog = {
.bdrv_create = sd_create,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
+ .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
.bdrv_truncate = sd_truncate,
.bdrv_co_readv = sd_co_readv,
@@ -2465,6 +2482,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
.bdrv_create = sd_create,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
+ .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
.bdrv_truncate = sd_truncate,
.bdrv_co_readv = sd_co_readv,
@@ -2494,6 +2512,7 @@ static BlockDriver bdrv_sheepdog_unix = {
.bdrv_create = sd_create,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
+ .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
.bdrv_truncate = sd_truncate,
.bdrv_co_readv = sd_co_readv,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 21/41] block/stream: Don't stream unbacked devices
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (19 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 20/41] sheepdog: implement .bdrv_get_allocated_file_size Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 22/41] block: per caller dirty bitmap Kevin Wolf
` (18 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Max Reitz <mreitz@redhat.com>
If a block device is unbacked, a streaming blockjob should immediately
finish instead of beginning to try to stream, then noticing the backing
file does not contain even the first sector (since it does not exist)
and then finishing normally.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/stream.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/block/stream.c b/block/stream.c
index 694fd42..46bec7d 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -88,6 +88,11 @@ static void coroutine_fn stream_run(void *opaque)
int n = 0;
void *buf;
+ if (!bs->backing_hd) {
+ block_job_completed(&s->common, 0);
+ return;
+ }
+
s->common.len = bdrv_getlength(bs);
if (s->common.len < 0) {
block_job_completed(&s->common, s->common.len);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 22/41] block: per caller dirty bitmap
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (20 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 21/41] block/stream: Don't stream unbacked devices Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list Kevin Wolf
` (17 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
Previously a BlockDriverState has only one dirty bitmap, so only one
caller (e.g. a block job) can keep track of writing. This changes the
dirty bitmap to a list and creates a BdrvDirtyBitmap for each caller, the
lifecycle is managed with these new functions:
bdrv_create_dirty_bitmap
bdrv_release_dirty_bitmap
Where BdrvDirtyBitmap is a linked list wrapper structure of HBitmap.
In place of bdrv_set_dirty_tracking, a BdrvDirtyBitmap pointer argument
is added to these functions, since each caller has its own dirty bitmap:
bdrv_get_dirty
bdrv_dirty_iter_init
bdrv_get_dirty_count
bdrv_set_dirty and bdrv_reset_dirty prototypes are unchanged but will
internally walk the list of all dirty bitmaps and set them one by one.
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block-migration.c | 22 +++++++++----
block.c | 83 ++++++++++++++++++++++++++++-------------------
block/mirror.c | 23 +++++++------
block/qapi.c | 8 -----
include/block/block.h | 11 ++++---
include/block/block_int.h | 2 +-
6 files changed, 86 insertions(+), 63 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index fc4ef93..897fdba 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -58,6 +58,7 @@ typedef struct BlkMigDevState {
/* Protected by block migration lock. */
unsigned long *aio_bitmap;
int64_t completed_sectors;
+ BdrvDirtyBitmap *dirty_bitmap;
} BlkMigDevState;
typedef struct BlkMigBlock {
@@ -309,12 +310,21 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
/* Called with iothread lock taken. */
-static void set_dirty_tracking(int enable)
+static void set_dirty_tracking(void)
{
BlkMigDevState *bmds;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
- bdrv_set_dirty_tracking(bmds->bs, enable ? BLOCK_SIZE : 0);
+ bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
+ }
+}
+
+static void unset_dirty_tracking(void)
+{
+ BlkMigDevState *bmds;
+
+ QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
+ bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
}
}
@@ -432,7 +442,7 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
} else {
blk_mig_unlock();
}
- if (bdrv_get_dirty(bmds->bs, sector)) {
+ if (bdrv_get_dirty(bmds->bs, bmds->dirty_bitmap, sector)) {
if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
nr_sectors = total_sectors - sector;
@@ -554,7 +564,7 @@ static int64_t get_remaining_dirty(void)
int64_t dirty = 0;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
- dirty += bdrv_get_dirty_count(bmds->bs);
+ dirty += bdrv_get_dirty_count(bmds->bs, bmds->dirty_bitmap);
}
return dirty << BDRV_SECTOR_BITS;
@@ -569,7 +579,7 @@ static void blk_mig_cleanup(void)
bdrv_drain_all();
- set_dirty_tracking(0);
+ unset_dirty_tracking();
blk_mig_lock();
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
@@ -604,7 +614,7 @@ static int block_save_setup(QEMUFile *f, void *opaque)
init_blk_migration(f);
/* start track dirty blocks */
- set_dirty_tracking(1);
+ set_dirty_tracking();
qemu_mutex_unlock_iothread();
ret = flush_blks(f);
diff --git a/block.c b/block.c
index e22b55f..d792d53 100644
--- a/block.c
+++ b/block.c
@@ -49,6 +49,11 @@
#include <windows.h>
#endif
+struct BdrvDirtyBitmap {
+ HBitmap *bitmap;
+ QLIST_ENTRY(BdrvDirtyBitmap) list;
+};
+
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
@@ -318,6 +323,7 @@ BlockDriverState *bdrv_new(const char *device_name)
BlockDriverState *bs;
bs = g_malloc0(sizeof(BlockDriverState));
+ QLIST_INIT(&bs->dirty_bitmaps);
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
if (device_name[0] != '\0') {
QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
@@ -1617,7 +1623,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
bs_dest->iostatus = bs_src->iostatus;
/* dirty bitmap */
- bs_dest->dirty_bitmap = bs_src->dirty_bitmap;
+ bs_dest->dirty_bitmaps = bs_src->dirty_bitmaps;
/* reference count */
bs_dest->refcnt = bs_src->refcnt;
@@ -1650,7 +1656,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
/* bs_new must be anonymous and shouldn't have anything fancy enabled */
assert(bs_new->device_name[0] == '\0');
- assert(bs_new->dirty_bitmap == NULL);
+ assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
assert(bs_new->job == NULL);
assert(bs_new->dev == NULL);
assert(bs_new->in_use == 0);
@@ -1711,6 +1717,7 @@ static void bdrv_delete(BlockDriverState *bs)
assert(!bs->job);
assert(!bs->in_use);
assert(!bs->refcnt);
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
bdrv_close(bs);
@@ -2858,9 +2865,7 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
ret = bdrv_co_flush(bs);
}
- if (bs->dirty_bitmap) {
- bdrv_set_dirty(bs, sector_num, nb_sectors);
- }
+ bdrv_set_dirty(bs, sector_num, nb_sectors);
if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
bs->wr_highest_sector = sector_num + nb_sectors - 1;
@@ -3431,7 +3436,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
- assert(!bs->dirty_bitmap);
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
@@ -4296,9 +4301,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
return -EROFS;
}
- if (bs->dirty_bitmap) {
- bdrv_reset_dirty(bs, sector_num, nb_sectors);
- }
+ bdrv_reset_dirty(bs, sector_num, nb_sectors);
/* Do nothing if disabled. */
if (!(bs->open_flags & BDRV_O_UNMAP)) {
@@ -4490,58 +4493,70 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
return true;
}
-void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity)
+BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
{
int64_t bitmap_size;
+ BdrvDirtyBitmap *bitmap;
assert((granularity & (granularity - 1)) == 0);
- if (granularity) {
- granularity >>= BDRV_SECTOR_BITS;
- assert(!bs->dirty_bitmap);
- bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
- bs->dirty_bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
- } else {
- if (bs->dirty_bitmap) {
- hbitmap_free(bs->dirty_bitmap);
- bs->dirty_bitmap = NULL;
+ granularity >>= BDRV_SECTOR_BITS;
+ assert(granularity);
+ bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
+ bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
+ bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
+ QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
+ return bitmap;
+}
+
+void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
+{
+ BdrvDirtyBitmap *bm, *next;
+ QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
+ if (bm == bitmap) {
+ QLIST_REMOVE(bitmap, list);
+ hbitmap_free(bitmap->bitmap);
+ g_free(bitmap);
+ return;
}
}
}
-int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
+int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector)
{
- if (bs->dirty_bitmap) {
- return hbitmap_get(bs->dirty_bitmap, sector);
+ if (bitmap) {
+ return hbitmap_get(bitmap->bitmap, sector);
} else {
return 0;
}
}
-void bdrv_dirty_iter_init(BlockDriverState *bs, HBitmapIter *hbi)
+void bdrv_dirty_iter_init(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap, HBitmapIter *hbi)
{
- hbitmap_iter_init(hbi, bs->dirty_bitmap, 0);
+ hbitmap_iter_init(hbi, bitmap->bitmap, 0);
}
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors)
{
- hbitmap_set(bs->dirty_bitmap, cur_sector, nr_sectors);
+ BdrvDirtyBitmap *bitmap;
+ QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
+ hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
+ }
}
-void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
- int nr_sectors)
+void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors)
{
- hbitmap_reset(bs->dirty_bitmap, cur_sector, nr_sectors);
+ BdrvDirtyBitmap *bitmap;
+ QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
+ hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
+ }
}
-int64_t bdrv_get_dirty_count(BlockDriverState *bs)
+int64_t bdrv_get_dirty_count(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
{
- if (bs->dirty_bitmap) {
- return hbitmap_count(bs->dirty_bitmap);
- } else {
- return 0;
- }
+ return hbitmap_count(bitmap->bitmap);
}
/* Get a reference to bs */
diff --git a/block/mirror.c b/block/mirror.c
index 7b95acf..6dc27ad 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -39,6 +39,7 @@ typedef struct MirrorBlockJob {
int64_t granularity;
size_t buf_size;
unsigned long *cow_bitmap;
+ BdrvDirtyBitmap *dirty_bitmap;
HBitmapIter hbi;
uint8_t *buf;
QSIMPLEQ_HEAD(, MirrorBuffer) buf_free;
@@ -145,9 +146,10 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
s->sector_num = hbitmap_iter_next(&s->hbi);
if (s->sector_num < 0) {
- bdrv_dirty_iter_init(source, &s->hbi);
+ bdrv_dirty_iter_init(source, s->dirty_bitmap, &s->hbi);
s->sector_num = hbitmap_iter_next(&s->hbi);
- trace_mirror_restart_iter(s, bdrv_get_dirty_count(source));
+ trace_mirror_restart_iter(s,
+ bdrv_get_dirty_count(source, s->dirty_bitmap));
assert(s->sector_num >= 0);
}
@@ -183,7 +185,7 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
do {
int added_sectors, added_chunks;
- if (!bdrv_get_dirty(source, next_sector) ||
+ if (!bdrv_get_dirty(source, s->dirty_bitmap, next_sector) ||
test_bit(next_chunk, s->in_flight_bitmap)) {
assert(nb_sectors > 0);
break;
@@ -249,7 +251,8 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
/* Advance the HBitmapIter in parallel, so that we do not examine
* the same sector twice.
*/
- if (next_sector > hbitmap_next_sector && bdrv_get_dirty(source, next_sector)) {
+ if (next_sector > hbitmap_next_sector
+ && bdrv_get_dirty(source, s->dirty_bitmap, next_sector)) {
hbitmap_next_sector = hbitmap_iter_next(&s->hbi);
}
@@ -355,7 +358,7 @@ static void coroutine_fn mirror_run(void *opaque)
}
}
- bdrv_dirty_iter_init(bs, &s->hbi);
+ bdrv_dirty_iter_init(bs, s->dirty_bitmap, &s->hbi);
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
for (;;) {
uint64_t delay_ns;
@@ -367,7 +370,7 @@ static void coroutine_fn mirror_run(void *opaque)
goto immediate_exit;
}
- cnt = bdrv_get_dirty_count(bs);
+ cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);
/* Note that even when no rate limit is applied we need to yield
* periodically with no pending I/O so that qemu_aio_flush() returns.
@@ -409,7 +412,7 @@ static void coroutine_fn mirror_run(void *opaque)
should_complete = s->should_complete ||
block_job_is_cancelled(&s->common);
- cnt = bdrv_get_dirty_count(bs);
+ cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);
}
}
@@ -424,7 +427,7 @@ static void coroutine_fn mirror_run(void *opaque)
*/
trace_mirror_before_drain(s, cnt);
bdrv_drain_all();
- cnt = bdrv_get_dirty_count(bs);
+ cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);
}
ret = 0;
@@ -471,7 +474,7 @@ immediate_exit:
qemu_vfree(s->buf);
g_free(s->cow_bitmap);
g_free(s->in_flight_bitmap);
- bdrv_set_dirty_tracking(bs, 0);
+ bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);
bdrv_iostatus_disable(s->target);
if (s->should_complete && ret == 0) {
if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) {
@@ -575,7 +578,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
s->granularity = granularity;
s->buf_size = MAX(buf_size, granularity);
- bdrv_set_dirty_tracking(bs, granularity);
+ s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity);
bdrv_set_enable_write_cache(s->target, true);
bdrv_set_on_error(s->target, on_target_error, on_target_error);
bdrv_iostatus_enable(s->target);
diff --git a/block/qapi.c b/block/qapi.c
index 5880b3e..6b0cdcf 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -204,14 +204,6 @@ void bdrv_query_info(BlockDriverState *bs,
info->io_status = bs->iostatus;
}
- if (bs->dirty_bitmap) {
- info->has_dirty = true;
- info->dirty = g_malloc0(sizeof(*info->dirty));
- info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE;
- info->dirty->granularity =
- ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap));
- }
-
if (bs->drv) {
info->has_inserted = true;
info->inserted = g_malloc0(sizeof(*info->inserted));
diff --git a/include/block/block.h b/include/block/block.h
index 4d9e67c..33ae9a9 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -419,12 +419,15 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
struct HBitmapIter;
-void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity);
-int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
+typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
+BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
+void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
+int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
-void bdrv_dirty_iter_init(BlockDriverState *bs, struct HBitmapIter *hbi);
-int64_t bdrv_get_dirty_count(BlockDriverState *bs);
+void bdrv_dirty_iter_init(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
+int64_t bdrv_get_dirty_count(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
void bdrv_enable_copy_on_read(BlockDriverState *bs);
void bdrv_disable_copy_on_read(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 95140b6..3c5e9cb 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -318,7 +318,7 @@ struct BlockDriverState {
bool iostatus_enabled;
BlockDeviceIoStatus iostatus;
char device_name[32];
- HBitmap *dirty_bitmap;
+ QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
int refcnt;
int in_use; /* users other than guest access, eg. block migration */
QTAILQ_ENTRY(BlockDriverState) list;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (21 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 22/41] block: per caller dirty bitmap Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-30 20:38 ` Eric Blake
2013-11-29 16:45 ` [Qemu-devel] [PULL 24/41] COW: Speed up writes Kevin Wolf
` (16 subsequent siblings)
39 siblings, 1 reply; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
We have multiple dirty bitmaps in BDS now, switch QAPI to allow query
it (BlockInfo.dirty_bitmaps), and also drop old BlockInfo.dirty.
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 20 ++++++++++++++++++++
block/qapi.c | 5 +++++
include/block/block.h | 1 +
qapi-schema.json | 6 +++---
4 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/block.c b/block.c
index d792d53..765bbae 100644
--- a/block.c
+++ b/block.c
@@ -4522,6 +4522,26 @@ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
}
}
+BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
+{
+ BdrvDirtyBitmap *bm;
+ BlockDirtyInfoList *list = NULL;
+ BlockDirtyInfoList **plist = &list;
+
+ QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
+ BlockDirtyInfo *info = g_malloc0(sizeof(BlockDirtyInfo));
+ BlockDirtyInfoList *entry = g_malloc0(sizeof(BlockDirtyInfoList));
+ info->count = bdrv_get_dirty_count(bs, bm);
+ info->granularity =
+ ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bm->bitmap));
+ entry->value = info;
+ *plist = entry;
+ plist = &entry->next;
+ }
+
+ return list;
+}
+
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector)
{
if (bitmap) {
diff --git a/block/qapi.c b/block/qapi.c
index 6b0cdcf..a32cb79 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -204,6 +204,11 @@ void bdrv_query_info(BlockDriverState *bs,
info->io_status = bs->iostatus;
}
+ if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
+ info->has_dirty_bitmaps = true;
+ info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);
+ }
+
if (bs->drv) {
info->has_inserted = true;
info->inserted = g_malloc0(sizeof(*info->inserted));
diff --git a/include/block/block.h b/include/block/block.h
index 33ae9a9..b6bdae8 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -422,6 +422,7 @@ struct HBitmapIter;
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
+BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
diff --git a/qapi-schema.json b/qapi-schema.json
index 83fa485..8630eb5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -948,8 +948,8 @@
# @tray_open: #optional True if the device has a tray and it is open
# (only present if removable is true)
#
-# @dirty: #optional dirty bitmap information (only present if the dirty
-# bitmap is enabled)
+# @dirty-bitmaps: #optional dirty bitmaps information (only present if the
+# driver has one or more dirty bitmaps) (Since 1.8)
#
# @io-status: #optional @BlockDeviceIoStatus. Only present if the device
# supports it and the VM is configured to stop on errors
@@ -963,7 +963,7 @@
'data': {'device': 'str', 'type': 'str', 'removable': 'bool',
'locked': 'bool', '*inserted': 'BlockDeviceInfo',
'*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus',
- '*dirty': 'BlockDirtyInfo' } }
+ '*dirty-bitmaps': ['BlockDirtyInfo'] } }
##
# @query-block:
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 24/41] COW: Speed up writes
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (22 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 25/41] COW: Extend checking allocated bits to beyond one sector Kevin Wolf
` (15 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Charlie Shepherd <charlie@ctshepherd.com>
Process a whole sector's worth of COW bits by reading a sector, setting
the bits after skipping any already set bits, then writing it out again.
Make sure we only flush once before writing metadata, and only if we
need to write metadata.
Signed-off-by: Charlie Shepherd <charlie@ctshepherd.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/cow.c | 88 +++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 50 insertions(+), 38 deletions(-)
diff --git a/block/cow.c b/block/cow.c
index 909c3e7..f759496 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -103,40 +103,18 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
-/*
- * XXX(hch): right now these functions are extremely inefficient.
- * We should just read the whole bitmap we'll need in one go instead.
- */
-static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum, bool *first)
+static inline void cow_set_bits(uint8_t *bitmap, int start, int64_t nb_sectors)
{
- uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
- uint8_t bitmap;
- int ret;
-
- ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
- if (ret < 0) {
- return ret;
- }
-
- if (bitmap & (1 << (bitnum % 8))) {
- return 0;
- }
-
- if (*first) {
- ret = bdrv_flush(bs->file);
- if (ret < 0) {
- return ret;
+ int64_t bitnum = start, last = start + nb_sectors;
+ while (bitnum < last) {
+ if ((bitnum & 7) == 0 && bitnum + 8 <= last) {
+ bitmap[bitnum / 8] = 0xFF;
+ bitnum += 8;
+ continue;
}
- *first = false;
+ bitmap[bitnum/8] |= (1 << (bitnum % 8));
+ bitnum++;
}
-
- bitmap |= (1 << (bitnum % 8));
-
- ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap));
- if (ret < 0) {
- return ret;
- }
- return 0;
}
#define BITS_PER_BITMAP_SECTOR (512 * 8)
@@ -204,18 +182,52 @@ static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs,
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
- int error = 0;
- int i;
+ int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
+ uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
bool first = true;
+ int sector_bits;
+
+ for ( ; nb_sectors;
+ bitnum += sector_bits,
+ nb_sectors -= sector_bits,
+ offset += BDRV_SECTOR_SIZE) {
+ int ret, set;
+ uint8_t bitmap[BDRV_SECTOR_SIZE];
+
+ bitnum &= BITS_PER_BITMAP_SECTOR - 1;
+ sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);
+
+ ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Skip over any already set bits */
+ set = cow_find_streak(bitmap, 1, bitnum, sector_bits);
+ bitnum += set;
+ sector_bits -= set;
+ nb_sectors -= set;
+ if (!sector_bits) {
+ continue;
+ }
+
+ if (first) {
+ ret = bdrv_flush(bs->file);
+ if (ret < 0) {
+ return ret;
+ }
+ first = false;
+ }
+
+ cow_set_bits(bitmap, bitnum, sector_bits);
- for (i = 0; i < nb_sectors; i++) {
- error = cow_set_bit(bs, sector_num + i, &first);
- if (error) {
- break;
+ ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap));
+ if (ret < 0) {
+ return ret;
}
}
- return error;
+ return 0;
}
static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 25/41] COW: Extend checking allocated bits to beyond one sector
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (23 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 24/41] COW: Speed up writes Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 26/41] MAINTAINERS: add sheepdog development mailing list Kevin Wolf
` (14 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Charlie Shepherd <charlie@ctshepherd.com>
cow_co_is_allocated() only checks one sector's worth of allocated bits
before returning. This is allowed but (slightly) inefficient, so extend
it to check all of the file's metadata sectors.
Signed-off-by: Charlie Shepherd <charlie@ctshepherd.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
[kwolf: silenced compiler warning (-Wmaybe-uninitialized for changed)]
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/cow.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/block/cow.c b/block/cow.c
index f759496..dc15e46 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -152,18 +152,34 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
{
int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
- uint8_t bitmap[BDRV_SECTOR_SIZE];
- int ret;
- int changed;
+ bool first = true;
+ int changed = 0, same = 0;
- ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
- if (ret < 0) {
- return ret;
- }
+ do {
+ int ret;
+ uint8_t bitmap[BDRV_SECTOR_SIZE];
+
+ bitnum &= BITS_PER_BITMAP_SECTOR - 1;
+ int sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);
+
+ ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (first) {
+ changed = cow_test_bit(bitnum, bitmap);
+ first = false;
+ }
+
+ same += cow_find_streak(bitmap, changed, bitnum, nb_sectors);
+
+ bitnum += sector_bits;
+ nb_sectors -= sector_bits;
+ offset += BDRV_SECTOR_SIZE;
+ } while (nb_sectors);
- bitnum &= BITS_PER_BITMAP_SECTOR - 1;
- changed = cow_test_bit(bitnum, bitmap);
- *num_same = cow_find_streak(bitmap, changed, bitnum, nb_sectors);
+ *num_same = same;
return changed;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 26/41] MAINTAINERS: add sheepdog development mailing list
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (24 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 25/41] COW: Extend checking allocated bits to beyond one sector Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 27/41] qdict: Fix memory leak in qdict_do_flatten() Kevin Wolf
` (13 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Liu Yuan <namei.unix@gmail.com>
This will help people find mailing list relevant to sheepdog.
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Liu Yuan <namei.unix@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c19133f..3e61ac8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -879,6 +879,7 @@ F: block/rbd.c
Sheepdog
M: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
M: Liu Yuan <namei.unix@gmail.com>
+L: sheepdog@lists.wpkg.org
S: Supported
F: block/sheepdog.c
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 27/41] qdict: Fix memory leak in qdict_do_flatten()
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (25 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 26/41] MAINTAINERS: add sheepdog development mailing list Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 28/41] qdict: Optimise qdict_do_flatten() Kevin Wolf
` (12 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
Reported-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
qobject/qdict.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 0f3e0a6..60d6cd5 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -481,7 +481,7 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
{
QObject *value;
const QDictEntry *entry, *next;
- const char *new_key;
+ char *new_key;
bool delete;
entry = qdict_first(qdict);
@@ -506,6 +506,8 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
delete = true;
}
+ g_free(new_key);
+
if (delete) {
qdict_del(qdict, entry->key);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 28/41] qdict: Optimise qdict_do_flatten()
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (26 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 27/41] qdict: Fix memory leak in qdict_do_flatten() Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 29/41] sheepdog: refactor do_sd_create() Kevin Wolf
` (11 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
Nested QDicts used to be both entered recursively in order to move their
entries to the target QDict and also be moved themselves to the target
QDict like all other objects. This is harmless because for the top
level, qdict_do_flatten() will encounter the (now empty) QDict for a
second time and then delete it, but at the same time it's obviously
unnecessary overhead. Just delete nested QDicts directly after moving
all of their entries.
Reported-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
qobject/qdict.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 60d6cd5..17e14f0 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -494,16 +494,20 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
delete = false;
if (prefix) {
- qobject_incref(value);
new_key = g_strdup_printf("%s.%s", prefix, entry->key);
- qdict_put_obj(target, new_key, value);
- delete = true;
}
if (qobject_type(value) == QTYPE_QDICT) {
+ /* Entries of QDicts are processed recursively, the QDict object
+ * itself disappears. */
qdict_do_flatten(qobject_to_qdict(value), target,
new_key ? new_key : entry->key);
delete = true;
+ } else if (prefix) {
+ /* All other objects are moved to the target unchanged. */
+ qobject_incref(value);
+ qdict_put_obj(target, new_key, value);
+ delete = true;
}
g_free(new_key);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 29/41] sheepdog: refactor do_sd_create()
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (27 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 28/41] qdict: Optimise qdict_do_flatten() Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 30/41] sheepdog: support user-defined redundancy option Kevin Wolf
` (10 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Liu Yuan <namei.unix@gmail.com>
We can actually use BDRVSheepdogState *s to pass most of the parameters.
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Liu Yuan <namei.unix@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/sheepdog.c | 37 +++++++++++++++----------------------
1 file changed, 15 insertions(+), 22 deletions(-)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 252d7ad..ae43675 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1464,9 +1464,7 @@ out:
return ret;
}
-static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
- uint32_t base_vid, uint32_t *vdi_id, int snapshot,
- uint8_t copy_policy)
+static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
{
SheepdogVdiReq hdr;
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
@@ -1483,11 +1481,11 @@ static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
* does not fit in buf? For now, just truncate and avoid buffer overrun.
*/
memset(buf, 0, sizeof(buf));
- pstrcpy(buf, sizeof(buf), filename);
+ pstrcpy(buf, sizeof(buf), s->name);
memset(&hdr, 0, sizeof(hdr));
hdr.opcode = SD_OP_NEW_VDI;
- hdr.vdi_id = base_vid;
+ hdr.vdi_id = s->inode.vdi_id;
wlen = SD_MAX_VDI_LEN;
@@ -1495,8 +1493,8 @@ static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
hdr.snapid = snapshot;
hdr.data_length = wlen;
- hdr.vdi_size = vdi_size;
- hdr.copy_policy = copy_policy;
+ hdr.vdi_size = s->inode.vdi_size;
+ hdr.copy_policy = s->inode.copy_policy;
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
@@ -1507,7 +1505,7 @@ static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
}
if (rsp->result != SD_RES_SUCCESS) {
- error_report("%s, %s", sd_strerror(rsp->result), filename);
+ error_report("%s, %s", sd_strerror(rsp->result), s->inode.name);
return -EIO;
}
@@ -1568,23 +1566,21 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
Error **errp)
{
int ret = 0;
- uint32_t vid = 0, base_vid = 0;
- int64_t vdi_size = 0;
+ uint32_t vid = 0;
char *backing_file = NULL;
BDRVSheepdogState *s;
- char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
+ char tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
bool prealloc = false;
Error *local_err = NULL;
s = g_malloc0(sizeof(BDRVSheepdogState));
- memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
if (strstr(filename, "://")) {
- ret = sd_parse_uri(s, filename, vdi, &snapid, tag);
+ ret = sd_parse_uri(s, filename, s->name, &snapid, tag);
} else {
- ret = parse_vdiname(s, filename, vdi, &snapid, tag);
+ ret = parse_vdiname(s, filename, s->name, &snapid, tag);
}
if (ret < 0) {
goto out;
@@ -1592,7 +1588,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
- vdi_size = options->value.n;
+ s->inode.vdi_size = options->value.n;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
@@ -1610,7 +1606,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
options++;
}
- if (vdi_size > SD_MAX_VDI_SIZE) {
+ if (s->inode.vdi_size > SD_MAX_VDI_SIZE) {
error_report("too big image size");
ret = -EINVAL;
goto out;
@@ -1645,12 +1641,11 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
goto out;
}
- base_vid = s->inode.vdi_id;
bdrv_unref(bs);
}
/* TODO: allow users to specify copy number */
- ret = do_sd_create(s, vdi, vdi_size, base_vid, &vid, 0, 0);
+ ret = do_sd_create(s, &vid, 0);
if (!prealloc || ret) {
goto out;
}
@@ -1833,8 +1828,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
* false bail out.
*/
deleted = sd_delete(s);
- ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &vid,
- !deleted, s->inode.copy_policy);
+ ret = do_sd_create(s, &vid, !deleted);
if (ret) {
goto out;
}
@@ -2097,8 +2091,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
goto cleanup;
}
- ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,
- 1, s->inode.copy_policy);
+ ret = do_sd_create(s, &new_vid, 1);
if (ret < 0) {
error_report("failed to create inode for snapshot. %s",
strerror(errno));
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 30/41] sheepdog: support user-defined redundancy option
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (28 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 29/41] sheepdog: refactor do_sd_create() Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 31/41] qemu-iotests: Drop local version of cancel_and_wait from 040 Kevin Wolf
` (9 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Liu Yuan <namei.unix@gmail.com>
Sheepdog support two kinds of redundancy, full replication and erasure coding.
# create a fully replicated vdi with x copies
-o redundancy=x (1 <= x <= SD_MAX_COPIES)
# create a erasure coded vdi with x data strips and y parity strips
-o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
E.g, to convert a vdi into sheepdog vdi 'test' with 8:3 erasure coding scheme
$ qemu-img convert -o redundancy=8:3 linux-0.2.img sheepdog:test
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Liu Yuan <namei.unix@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/sheepdog.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-
include/block/block_int.h | 1 +
2 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index ae43675..b4ae50f 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -91,6 +91,14 @@
#define SD_NR_VDIS (1U << 24)
#define SD_DATA_OBJ_SIZE (UINT64_C(1) << 22)
#define SD_MAX_VDI_SIZE (SD_DATA_OBJ_SIZE * MAX_DATA_OBJS)
+/*
+ * For erasure coding, we use at most SD_EC_MAX_STRIP for data strips and
+ * (SD_EC_MAX_STRIP - 1) for parity strips
+ *
+ * SD_MAX_COPIES is sum of number of data strips and parity strips.
+ */
+#define SD_EC_MAX_STRIP 16
+#define SD_MAX_COPIES (SD_EC_MAX_STRIP * 2 - 1)
#define SD_INODE_SIZE (sizeof(SheepdogInode))
#define CURRENT_VDI_ID 0
@@ -1495,6 +1503,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
hdr.data_length = wlen;
hdr.vdi_size = s->inode.vdi_size;
hdr.copy_policy = s->inode.copy_policy;
+ hdr.copies = s->inode.nr_copies;
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
@@ -1562,6 +1571,60 @@ out:
return ret;
}
+/*
+ * Sheepdog support two kinds of redundancy, full replication and erasure
+ * coding.
+ *
+ * # create a fully replicated vdi with x copies
+ * -o redundancy=x (1 <= x <= SD_MAX_COPIES)
+ *
+ * # create a erasure coded vdi with x data strips and y parity strips
+ * -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
+ */
+static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
+{
+ struct SheepdogInode *inode = &s->inode;
+ const char *n1, *n2;
+ long copy, parity;
+ char p[10];
+
+ pstrcpy(p, sizeof(p), opt);
+ n1 = strtok(p, ":");
+ n2 = strtok(NULL, ":");
+
+ if (!n1) {
+ return -EINVAL;
+ }
+
+ copy = strtol(n1, NULL, 10);
+ if (copy > SD_MAX_COPIES || copy < 1) {
+ return -EINVAL;
+ }
+ if (!n2) {
+ inode->copy_policy = 0;
+ inode->nr_copies = copy;
+ return 0;
+ }
+
+ if (copy != 2 && copy != 4 && copy != 8 && copy != 16) {
+ return -EINVAL;
+ }
+
+ parity = strtol(n2, NULL, 10);
+ if (parity >= SD_EC_MAX_STRIP || parity < 1) {
+ return -EINVAL;
+ }
+
+ /*
+ * 4 bits for parity and 4 bits for data.
+ * We have to compress upper data bits because it can't represent 16
+ */
+ inode->copy_policy = ((copy / 2) << 4) + parity;
+ inode->nr_copies = copy + parity;
+
+ return 0;
+}
+
static int sd_create(const char *filename, QEMUOptionParameter *options,
Error **errp)
{
@@ -1602,6 +1665,11 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
ret = -EINVAL;
goto out;
}
+ } else if (!strcmp(options->name, BLOCK_OPT_REDUNDANCY)) {
+ ret = parse_redundancy(s, options->value.s);
+ if (ret < 0) {
+ goto out;
+ }
}
options++;
}
@@ -1644,7 +1712,6 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
bdrv_unref(bs);
}
- /* TODO: allow users to specify copy number */
ret = do_sd_create(s, &vid, 0);
if (!prealloc || ret) {
goto out;
@@ -2432,6 +2499,11 @@ static QEMUOptionParameter sd_create_options[] = {
.type = OPT_STRING,
.help = "Preallocation mode (allowed values: off, full)"
},
+ {
+ .name = BLOCK_OPT_REDUNDANCY,
+ .type = OPT_STRING,
+ .help = "Redundancy of the image"
+ },
{ NULL }
};
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 3c5e9cb..d0f70c4 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -53,6 +53,7 @@
#define BLOCK_OPT_COMPAT_LEVEL "compat"
#define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts"
#define BLOCK_OPT_ADAPTER_TYPE "adapter_type"
+#define BLOCK_OPT_REDUNDANCY "redundancy"
typedef struct BdrvTrackedRequest {
BlockDriverState *bs;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 31/41] qemu-iotests: Drop local version of cancel_and_wait from 040
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (29 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 30/41] sheepdog: support user-defined redundancy option Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 32/41] blkdebug: add "remove_break" command Kevin Wolf
` (8 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
iotests.py already has one.
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qemu-iotests/040 | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index a2e18c5..0e85136 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -39,21 +39,6 @@ class ImageCommitTestCase(iotests.QMPTestCase):
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return', [])
- def cancel_and_wait(self, drive='drive0'):
- '''Cancel a block job and wait for it to finish'''
- result = self.vm.qmp('block-job-cancel', device=drive)
- self.assert_qmp(result, 'return', {})
-
- cancelled = False
- while not cancelled:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_CANCELLED':
- self.assert_qmp(event, 'data/type', 'commit')
- self.assert_qmp(event, 'data/device', drive)
- cancelled = True
-
- self.assert_no_active_commit()
-
class TestSingleDrive(ImageCommitTestCase):
image_len = 1 * 1024 * 1024
test_len = 1 * 1024 * 256
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 32/41] blkdebug: add "remove_break" command
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (30 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 31/41] qemu-iotests: Drop local version of cancel_and_wait from 040 Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 33/41] qemu-iotest: Add pause_drive and resume_drive methods Kevin Wolf
` (7 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
This adds "remove_break" command which is the reverse of blkdebug
command "break": it removes all breakpoints with given tag and resumes
all the requests.
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block.c | 13 +++++++++++++
block/blkdebug.c | 27 +++++++++++++++++++++++++++
include/block/block.h | 1 +
include/block/block_int.h | 2 ++
qemu-io-cmds.c | 22 ++++++++++++++++++++++
5 files changed, 65 insertions(+)
diff --git a/block.c b/block.c
index 765bbae..faa52d4 100644
--- a/block.c
+++ b/block.c
@@ -3525,6 +3525,19 @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
return -ENOTSUP;
}
+int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
+{
+ while (bs && bs->drv && !bs->drv->bdrv_debug_remove_breakpoint) {
+ bs = bs->file;
+ }
+
+ if (bs && bs->drv && bs->drv->bdrv_debug_remove_breakpoint) {
+ return bs->drv->bdrv_debug_remove_breakpoint(bs, tag);
+ }
+
+ return -ENOTSUP;
+}
+
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
{
while (bs && bs->drv && !bs->drv->bdrv_debug_resume) {
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 16d2b91..37cf028 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -605,6 +605,31 @@ static int blkdebug_debug_resume(BlockDriverState *bs, const char *tag)
return -ENOENT;
}
+static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs,
+ const char *tag)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+ BlkdebugSuspendedReq *r;
+ BlkdebugRule *rule, *next;
+ int i, ret = -ENOENT;
+
+ for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
+ QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
+ if (rule->action == ACTION_SUSPEND &&
+ !strcmp(rule->options.suspend.tag, tag)) {
+ remove_rule(rule);
+ ret = 0;
+ }
+ }
+ }
+ QLIST_FOREACH(r, &s->suspended_reqs, next) {
+ if (!strcmp(r->tag, tag)) {
+ qemu_coroutine_enter(r->co, NULL);
+ ret = 0;
+ }
+ }
+ return ret;
+}
static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
{
@@ -639,6 +664,8 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_debug_event = blkdebug_debug_event,
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
+ .bdrv_debug_remove_breakpoint
+ = blkdebug_debug_remove_breakpoint,
.bdrv_debug_resume = blkdebug_debug_resume,
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
};
diff --git a/include/block/block.h b/include/block/block.h
index b6bdae8..5beccbf 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -519,6 +519,7 @@ void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
const char *tag);
+int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag);
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d0f70c4..773899b 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -219,6 +219,8 @@ struct BlockDriver {
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event,
const char *tag);
+ int (*bdrv_debug_remove_breakpoint)(BlockDriverState *bs,
+ const char *tag);
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 7e9fecb..85e4982 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1956,6 +1956,18 @@ static int break_f(BlockDriverState *bs, int argc, char **argv)
return 0;
}
+static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int ret;
+
+ ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
+ if (ret < 0) {
+ printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
+ }
+
+ return 0;
+}
+
static const cmdinfo_t break_cmd = {
.name = "break",
.argmin = 2,
@@ -1966,6 +1978,15 @@ static const cmdinfo_t break_cmd = {
"request as tag",
};
+static const cmdinfo_t remove_break_cmd = {
+ .name = "remove_break",
+ .argmin = 1,
+ .argmax = 1,
+ .cfunc = remove_break_f,
+ .args = "tag",
+ .oneline = "remove a breakpoint by tag",
+};
+
static int resume_f(BlockDriverState *bs, int argc, char **argv)
{
int ret;
@@ -2126,6 +2147,7 @@ static void __attribute((constructor)) init_qemuio_commands(void)
qemuio_add_command(&alloc_cmd);
qemuio_add_command(&map_cmd);
qemuio_add_command(&break_cmd);
+ qemuio_add_command(&remove_break_cmd);
qemuio_add_command(&resume_cmd);
qemuio_add_command(&wait_break_cmd);
qemuio_add_command(&abort_cmd);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 33/41] qemu-iotest: Add pause_drive and resume_drive methods
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (31 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 32/41] blkdebug: add "remove_break" command Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 34/41] qemu-iotests: Make test case 030, 040 and 055 deterministic Kevin Wolf
` (6 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
They wrap blkdebug "break" and "remove_break".
Add optional argument "resume" to cancel_and_wait().
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qemu-iotests/iotests.py | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index fb10ff4..10c9a99 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -107,6 +107,19 @@ class VM(object):
self._num_drives += 1
return self
+ def pause_drive(self, drive, event=None):
+ '''Pause drive r/w operations'''
+ if not event:
+ self.pause_drive(drive, "read_aio")
+ self.pause_drive(drive, "write_aio")
+ return
+ self.qmp('human-monitor-command',
+ command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive))
+
+ def resume_drive(self, drive):
+ self.qmp('human-monitor-command',
+ command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive))
+
def hmp_qemu_io(self, drive, cmd):
'''Write to a given drive using an HMP command'''
return self.qmp('human-monitor-command',
@@ -222,11 +235,14 @@ class QMPTestCase(unittest.TestCase):
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return', [])
- def cancel_and_wait(self, drive='drive0', force=False):
+ def cancel_and_wait(self, drive='drive0', force=False, resume=False):
'''Cancel a block job and wait for it to finish, returning the event'''
result = self.vm.qmp('block-job-cancel', device=drive, force=force)
self.assert_qmp(result, 'return', {})
+ if resume:
+ self.vm.resume_drive(drive)
+
cancelled = False
result = None
while not cancelled:
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 34/41] qemu-iotests: Make test case 030, 040 and 055 deterministic
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (32 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 33/41] qemu-iotest: Add pause_drive and resume_drive methods Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 35/41] block: Enable BDRV_O_SNAPSHOT with driver-specific options Kevin Wolf
` (5 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
Pause the drive and start the block job, so we won't miss the block job.
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qemu-iotests/030 | 16 +++++++++++-----
tests/qemu-iotests/040 | 4 +++-
tests/qemu-iotests/055 | 14 +++++++++++---
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index d0f96ea..59a34f7 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -34,6 +34,7 @@ class TestSingleDrive(iotests.QMPTestCase):
iotests.create_image(backing_img, TestSingleDrive.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
+ qemu_io('-c', 'write -P 0x1 0 512', backing_img)
self.vm = iotests.VM().add_drive(test_img)
self.vm.launch()
@@ -69,6 +70,7 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_stream_pause(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
@@ -86,6 +88,7 @@ class TestSingleDrive(iotests.QMPTestCase):
result = self.vm.qmp('block-job-resume', device='drive0')
self.assert_qmp(result, 'return', {})
+ self.vm.resume_drive('drive0')
completed = False
while not completed:
for event in self.vm.get_qmp_events(wait=True):
@@ -391,7 +394,7 @@ class TestStreamStop(iotests.QMPTestCase):
qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
- self.vm = iotests.VM().add_drive(test_img)
+ self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
self.vm.launch()
def tearDown(self):
@@ -402,6 +405,7 @@ class TestStreamStop(iotests.QMPTestCase):
def test_stream_stop(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
@@ -409,7 +413,7 @@ class TestStreamStop(iotests.QMPTestCase):
events = self.vm.get_qmp_events(wait=False)
self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
- self.cancel_and_wait()
+ self.cancel_and_wait(resume=True)
class TestSetSpeed(iotests.QMPTestCase):
image_len = 80 * 1024 * 1024 # MB
@@ -419,7 +423,7 @@ class TestSetSpeed(iotests.QMPTestCase):
qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
- self.vm = iotests.VM().add_drive(test_img)
+ self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
self.vm.launch()
def tearDown(self):
@@ -453,6 +457,7 @@ class TestSetSpeed(iotests.QMPTestCase):
def test_set_speed(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
@@ -469,7 +474,8 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return[0]/device', 'drive0')
self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
- self.cancel_and_wait()
+ self.cancel_and_wait(resume=True)
+ self.vm.pause_drive('drive0')
# Check setting speed in block-stream works
result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
@@ -479,7 +485,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return[0]/device', 'drive0')
self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
- self.cancel_and_wait()
+ self.cancel_and_wait(resume=True)
def test_set_speed_invalid(self):
self.assert_no_active_block_jobs()
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index 0e85136..18dcd61 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -228,6 +228,7 @@ class TestSetSpeed(ImageCommitTestCase):
qemu_img('create', backing_img, str(TestSetSpeed.image_len))
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
+ qemu_io('-c', 'write -P 0x1 0 512', test_img)
self.vm = iotests.VM().add_drive(test_img)
self.vm.launch()
@@ -240,6 +241,7 @@ class TestSetSpeed(ImageCommitTestCase):
def test_set_speed(self):
self.assert_no_active_commit()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('block-commit', device='drive0', top=mid_img, speed=1024 * 1024)
self.assert_qmp(result, 'return', {})
@@ -248,7 +250,7 @@ class TestSetSpeed(ImageCommitTestCase):
self.assert_qmp(result, 'return[0]/device', 'drive0')
self.assert_qmp(result, 'return[0]/speed', 1024 * 1024)
- self.cancel_and_wait()
+ self.cancel_and_wait(resume=True)
if __name__ == '__main__':
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index 44bb025..451b67d 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -63,6 +63,7 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_pause(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('drive-backup', device='drive0',
target=target_img, sync='full')
self.assert_qmp(result, 'return', {})
@@ -70,6 +71,7 @@ class TestSingleDrive(iotests.QMPTestCase):
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')
@@ -113,6 +115,7 @@ class TestSetSpeed(iotests.QMPTestCase):
def setUp(self):
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len))
+ qemu_io('-c', 'write -P1 0 512', test_img)
self.vm = iotests.VM().add_drive(test_img)
self.vm.launch()
@@ -124,6 +127,7 @@ class TestSetSpeed(iotests.QMPTestCase):
def test_set_speed(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('drive-backup', device='drive0',
target=target_img, sync='full')
self.assert_qmp(result, 'return', {})
@@ -141,10 +145,11 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return[0]/device', 'drive0')
self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
- event = self.cancel_and_wait()
+ event = self.cancel_and_wait(resume=True)
self.assert_qmp(event, 'data/type', 'backup')
# Check setting speed in drive-backup works
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('drive-backup', device='drive0',
target=target_img, sync='full', speed=4*1024*1024)
self.assert_qmp(result, 'return', {})
@@ -153,7 +158,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return[0]/device', 'drive0')
self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
- event = self.cancel_and_wait()
+ event = self.cancel_and_wait(resume=True)
self.assert_qmp(event, 'data/type', 'backup')
def test_set_speed_invalid(self):
@@ -165,6 +170,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('drive-backup', device='drive0',
target=target_img, sync='full')
self.assert_qmp(result, 'return', {})
@@ -172,7 +178,7 @@ class TestSetSpeed(iotests.QMPTestCase):
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
self.assert_qmp(result, 'error/class', 'GenericError')
- event = self.cancel_and_wait()
+ event = self.cancel_and_wait(resume=True)
self.assert_qmp(event, 'data/type', 'backup')
class TestSingleTransaction(iotests.QMPTestCase):
@@ -214,6 +220,7 @@ class TestSingleTransaction(iotests.QMPTestCase):
def test_pause(self):
self.assert_no_active_block_jobs()
+ self.vm.pause_drive('drive0')
result = self.vm.qmp('transaction', actions=[{
'type': 'drive-backup',
'data': { 'device': 'drive0',
@@ -226,6 +233,7 @@ class TestSingleTransaction(iotests.QMPTestCase):
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')
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 35/41] block: Enable BDRV_O_SNAPSHOT with driver-specific options
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (33 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 34/41] qemu-iotests: Make test case 030, 040 and 055 deterministic Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 36/41] qemu-iotests: Test snapshot mode Kevin Wolf
` (4 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
In the case of snapshot=on, don't rely on the backing file path in the
temporary image any more, but override the backing file with the given
set of options. This way, block drivers that don't use a file name can
be accessed with snapshot=on, for example:
-drive file.driver=nbd,file.host=localhost,snapshot=on
Which becomes internally something like:
file.filename=/tmp/vl.AWQZCu,backing.file.driver=nbd,backing.file.host=localhost
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 47 +++++++++++++++++++++--------------------------
1 file changed, 21 insertions(+), 26 deletions(-)
diff --git a/block.c b/block.c
index faa52d4..08dd7f2 100644
--- a/block.c
+++ b/block.c
@@ -1053,21 +1053,15 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
int64_t total_size;
BlockDriver *bdrv_qcow2;
QEMUOptionParameter *create_options;
- char backing_filename[PATH_MAX];
-
- if (qdict_size(options) != 0) {
- error_setg(errp, "Can't use snapshot=on with driver-specific options");
- ret = -EINVAL;
- goto fail;
- }
- assert(filename != NULL);
+ QDict *snapshot_options;
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
- /* if there is a backing file, use it */
+ /* Get the required size from the image */
bs1 = bdrv_new("");
- ret = bdrv_open(bs1, filename, NULL, 0, drv, &local_err);
+ QINCREF(options);
+ ret = bdrv_open(bs1, filename, options, 0, drv, &local_err);
if (ret < 0) {
bdrv_unref(bs1);
goto fail;
@@ -1076,33 +1070,18 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
bdrv_unref(bs1);
+ /* Create the temporary image */
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not get temporary filename");
goto fail;
}
- /* Real path is meaningless for protocols */
- if (path_has_protocol(filename)) {
- snprintf(backing_filename, sizeof(backing_filename),
- "%s", filename);
- } else if (!realpath(filename, backing_filename)) {
- ret = -errno;
- error_setg_errno(errp, errno, "Could not resolve path '%s'", filename);
- goto fail;
- }
-
bdrv_qcow2 = bdrv_find_format("qcow2");
create_options = parse_option_parameters("", bdrv_qcow2->create_options,
NULL);
set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
- set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,
- backing_filename);
- if (drv) {
- set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,
- drv->format_name);
- }
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
free_option_parameters(create_options);
@@ -1115,6 +1094,22 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
goto fail;
}
+ /* Prepare a new options QDict for the temporary file, where user
+ * options refer to the backing file */
+ if (filename) {
+ qdict_put(options, "file.filename", qstring_from_str(filename));
+ }
+ if (drv) {
+ qdict_put(options, "driver", qstring_from_str(drv->format_name));
+ }
+
+ snapshot_options = qdict_new();
+ qdict_put(snapshot_options, "backing", options);
+ qdict_flatten(snapshot_options);
+
+ bs->options = snapshot_options;
+ options = qdict_clone_shallow(bs->options);
+
filename = tmp_filename;
drv = bdrv_qcow2;
bs->is_temporary = 1;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 36/41] qemu-iotests: Test snapshot mode
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (34 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 35/41] block: Enable BDRV_O_SNAPSHOT with driver-specific options Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 37/41] block: Use BDRV_O_NO_BACKING where appropriate Kevin Wolf
` (3 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
tests/qemu-iotests/051 | 17 +++++++++++++++
tests/qemu-iotests/051.out | 54 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 3a75bda..b23d91b 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -183,6 +183,23 @@ run_qemu -hda foo:bar
run_qemu -drive file=foo:bar
run_qemu -drive file.filename=foo:bar
+echo
+echo === Snapshot mode ===
+echo
+
+$QEMU_IO -c "write -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io
+
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2 -snapshot | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io
+
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=off | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 8769c8e..ddef87c 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -29,11 +29,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TE
=== Overriding backing file ===
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i^[[K^[[Din^[[K^[[D^[[Dinf^[[K^[[D^[[D^[[Dinfo^[[K^[[D^[[D^[[D^[[Dinfo ^[[K^[[D^[[D^[[D^[[D^[[Dinfo b^[[K^[[D^[[D^[[D^[[D^[[D^[[Dinfo bl^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo blo^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo bloc^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo block^[[K
-ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
- Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
-(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) i^[[K^[[Din^[[K^[[D^[[Dinf^[[K^[[D^[[D^[[Dinfo^[[K^[[D^[[D^[[D^[[Dinfo ^[[K^[[D^[[D^[[D^[[D^[[Dinfo b^[[K^[[D^[[D^[[D^[[D^[[D^[[Dinfo bl^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo blo^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo bloc^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dinfo block^[[K
+ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
+ Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
@@ -237,4 +237,48 @@ QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown proto
Testing: -drive file.filename=foo:bar
QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory
+
+=== Snapshot mode ===
+
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) q^[[K^[[Dqe^[[K^[[D^[[Dqem^[[K^[[D^[[D^[[Dqemu^[[K^[[D^[[D^[[D^[[Dqemu-^[[K^[[D^[[D^[[D^[[D^[[Dqemu-i^[[K^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io i^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io id^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-h^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wr^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wri^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D!
^[[D^[[Dqemu-io ide0-hd0 "writ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x2^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w!
rite -P 0x22^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"^[[K
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) q^[[K^[[Dqe^[[K^[[D^[[Dqem^[[K^[[D^[[D^[[Dqemu^[[K^[[D^[[D^[[D^[[Dqemu-^[[K^[[D^[[D^[[D^[[D^[[Dqemu-i^[[K^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io i^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io id^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-h^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wr^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wri^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D!
^[[D^[[Dqemu-io ide0-hd0 "writ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x2^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w!
rite -P 0x22^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"^[[K
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) q^[[K^[[Dqe^[[K^[[D^[[Dqem^[[K^[[D^[[D^[[Dqemu^[[K^[[D^[[D^[[D^[[Dqemu-^[[K^[[D^[[D^[[D^[[D^[[Dqemu-i^[[K^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io i^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io id^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-h^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wr^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wri^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D!
^[[D^[[Dqemu-io ide0-hd0 "writ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x2^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w!
rite -P 0x22^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"^[[K
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) q^[[K^[[Dqe^[[K^[[D^[[Dqem^[[K^[[D^[[D^[[Dqemu^[[K^[[D^[[D^[[D^[[Dqemu-^[[K^[[D^[[D^[[D^[[D^[[Dqemu-i^[[K^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io i^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io id^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-h^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wr^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wri^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D!
^[[D^[[Dqemu-io ide0-hd0 "writ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x2^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w!
rite -P 0x22^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"^[[K
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) q^[[K^[[Dqe^[[K^[[D^[[Dqem^[[K^[[D^[[D^[[Dqemu^[[K^[[D^[[D^[[D^[[Dqemu-^[[K^[[D^[[D^[[D^[[D^[[Dqemu-i^[[K^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io i^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io id^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-h^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wr^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "wri^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D!
^[[D^[[Dqemu-io ide0-hd0 "writ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x2^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "w!
rite -P 0x22^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 ^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k^[[K^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"^[[K
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 37/41] block: Use BDRV_O_NO_BACKING where appropriate
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (35 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 36/41] qemu-iotests: Test snapshot mode Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 38/41] qemu-iotests: Filter qemu-io output in 025 Kevin Wolf
` (2 subsequent siblings)
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
If you open an image temporarily just because you want to check its size
or get it flushed, there's no real reason to open the whole backing file
chain.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
---
block.c | 3 ++-
block/qcow2.c | 3 ++-
block/vmdk.c | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/block.c b/block.c
index 08dd7f2..3d78581 100644
--- a/block.c
+++ b/block.c
@@ -1061,7 +1061,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
/* Get the required size from the image */
bs1 = bdrv_new("");
QINCREF(options);
- ret = bdrv_open(bs1, filename, options, 0, drv, &local_err);
+ ret = bdrv_open(bs1, filename, options, BDRV_O_NO_BACKING,
+ drv, &local_err);
if (ret < 0) {
bdrv_unref(bs1);
goto fail;
diff --git a/block/qcow2.c b/block/qcow2.c
index 2fe37ed..8e2b6c7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1588,7 +1588,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
ret = bdrv_open(bs, filename, NULL,
- BDRV_O_RDWR | BDRV_O_CACHE_WB, drv, &local_err);
+ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
+ drv, &local_err);
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
goto out;
diff --git a/block/vmdk.c b/block/vmdk.c
index 6555663..5fb6c81 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1690,7 +1690,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
}
if (backing_file) {
BlockDriverState *bs = bdrv_new("");
- ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp);
+ ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
if (ret != 0) {
bdrv_unref(bs);
return ret;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 38/41] qemu-iotests: Filter qemu-io output in 025
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (36 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 37/41] block: Use BDRV_O_NO_BACKING where appropriate Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 40/41] vmdk: Allow read only open of VMDK version 3 Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 41/41] qemu-iotests: Add sample image and test for " Kevin Wolf
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/qemu-iotests/025 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025
index a7241cc..9426c93 100755
--- a/tests/qemu-iotests/025
+++ b/tests/qemu-iotests/025
@@ -56,7 +56,7 @@ _check_test_img
echo
echo "=== Resizing image"
-$QEMU_IO "$TEST_IMG" <<EOF
+$QEMU_IO "$TEST_IMG" <<EOF | _filter_qemu_io
length
truncate $big_size
length
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 40/41] vmdk: Allow read only open of VMDK version 3
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (37 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 38/41] qemu-iotests: Filter qemu-io output in 025 Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 41/41] qemu-iotests: Add sample image and test for " Kevin Wolf
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vmdk.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index 5fb6c81..88d09e3 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -605,13 +605,20 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
header = footer.header;
}
- if (le32_to_cpu(header.version) >= 3) {
+ if (le32_to_cpu(header.version) > 3) {
char buf[64];
snprintf(buf, sizeof(buf), "VMDK version %d",
le32_to_cpu(header.version));
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "vmdk", buf);
return -ENOTSUP;
+ } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
+ /* VMware KB 2064959 explains that version 3 added support for
+ * persistent changed block tracking (CBT), and backup software can
+ * read it as version=1 if it doesn't care about the changed area
+ * information. So we are safe to enable read only. */
+ error_setg(errp, "VMDK version 3 must be read only");
+ return -EINVAL;
}
if (le32_to_cpu(header.num_gtes_per_gt) > 512) {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [Qemu-devel] [PULL 41/41] qemu-iotests: Add sample image and test for VMDK version 3
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
` (38 preceding siblings ...)
2013-11-29 16:45 ` [Qemu-devel] [PULL 40/41] vmdk: Allow read only open of VMDK version 3 Kevin Wolf
@ 2013-11-29 16:45 ` Kevin Wolf
39 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-11-29 16:45 UTC (permalink / raw)
To: anthony; +Cc: kwolf, qemu-devel
From: Fam Zheng <famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/qemu-iotests/059 | 5 +++++
tests/qemu-iotests/059.out | 5 +++++
tests/qemu-iotests/sample_images/iotest-version3.vmdk.bz2 | Bin 0 -> 414 bytes
3 files changed, 10 insertions(+)
create mode 100644 tests/qemu-iotests/sample_images/iotest-version3.vmdk.bz2
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 6a27ac9..4926645 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -75,6 +75,11 @@ echo
echo "=== Testing monolithicFlat with zeroed_grain ==="
IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
+echo
+echo "=== Testing version 3 ==="
+_use_sample_img iotest-version3.vmdk.bz2
+_img_info
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 2ded8a9..0aadd56 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -25,4 +25,9 @@ virtual size: 2.0G (2147483648 bytes)
=== Testing monolithicFlat with zeroed_grain ===
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
+
+=== Testing version 3 ===
+image: TEST_DIR/iotest-version3.IMGFMT
+file format: IMGFMT
+virtual size: 1.0G (1073741824 bytes)
*** done
diff --git a/tests/qemu-iotests/sample_images/iotest-version3.vmdk.bz2 b/tests/qemu-iotests/sample_images/iotest-version3.vmdk.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..30abf217e72d38e97b1e34a5db6add15ca3812d9
GIT binary patch
literal 414
zcmV;P0b%|^T4*^jL0KkKS-4ab^Z){!-`M?<SOa_FKX2WrKkwggU;qFBpa4(^umM=u
z+94F$O))(usK{+bfDHzK0MKX+G7S`-Q`Ge`dYS+L00uw+000t1nx~<uv^3HWP-tix
z00uw<K=hVO#1Ez%h~;8tm5}gs2_-azgp&-Agak%FkPaO6#E>Q}oWup($ZYNuP+onz
zC89&oo+5m#SRo3f$tj3j4cj-uY<9AFkA%eEJTaa)*;e;U06X$QBY(3aGcne4@Z5Q`
zOld1c2c2n5eaHx1cF@GqGfd88M9D~UB914v;WOL96@WSu-<9};viD>nCB_lZ=L5MA
zWAhh{E!lb{@J3L6J+%};gkaKNrNrxivB)qiB85a>b>(iaNAFyd9Z|7XRWs!&h*2TY
z2uM_*TOC2Lp=5yL%rudbN4;JP^)svmH_P%A-P+35?p=v$3M>tU*);6x0S=pmRj{{|
z7O<gW34|a7q?sHzkqRsX5{K7j5{vUyiDt@86*TlpddQ`yx%PYS=jA|vGbjHSaz!{$
IkhoM7^luBcZ~y=R
literal 0
HcmV?d00001
--
1.8.1.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list
2013-11-29 16:45 ` [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list Kevin Wolf
@ 2013-11-30 20:38 ` Eric Blake
2013-12-02 10:29 ` Kevin Wolf
0 siblings, 1 reply; 43+ messages in thread
From: Eric Blake @ 2013-11-30 20:38 UTC (permalink / raw)
To: Kevin Wolf, anthony; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 909 bytes --]
On 11/29/2013 09:45 AM, Kevin Wolf wrote:
> From: Fam Zheng <famz@redhat.com>
>
> We have multiple dirty bitmaps in BDS now, switch QAPI to allow query
> it (BlockInfo.dirty_bitmaps), and also drop old BlockInfo.dirty.
>
> +++ b/qapi-schema.json
> @@ -948,8 +948,8 @@
> # @tray_open: #optional True if the device has a tray and it is open
> # (only present if removable is true)
> #
> -# @dirty: #optional dirty bitmap information (only present if the dirty
> -# bitmap is enabled)
> +# @dirty-bitmaps: #optional dirty bitmaps information (only present if the
> +# driver has one or more dirty bitmaps) (Since 1.8)
The cover letter mentions 2.0; should we scrub the tree looking for
other out-of-date references to 1.8 and update them?
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list
2013-11-30 20:38 ` Eric Blake
@ 2013-12-02 10:29 ` Kevin Wolf
0 siblings, 0 replies; 43+ messages in thread
From: Kevin Wolf @ 2013-12-02 10:29 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-devel, anthony
[-- Attachment #1: Type: text/plain, Size: 1000 bytes --]
Am 30.11.2013 um 21:38 hat Eric Blake geschrieben:
> On 11/29/2013 09:45 AM, Kevin Wolf wrote:
> > From: Fam Zheng <famz@redhat.com>
> >
> > We have multiple dirty bitmaps in BDS now, switch QAPI to allow query
> > it (BlockInfo.dirty_bitmaps), and also drop old BlockInfo.dirty.
> >
>
> > +++ b/qapi-schema.json
> > @@ -948,8 +948,8 @@
> > # @tray_open: #optional True if the device has a tray and it is open
> > # (only present if removable is true)
> > #
> > -# @dirty: #optional dirty bitmap information (only present if the dirty
> > -# bitmap is enabled)
> > +# @dirty-bitmaps: #optional dirty bitmaps information (only present if the
> > +# driver has one or more dirty bitmaps) (Since 1.8)
>
> The cover letter mentions 2.0; should we scrub the tree looking for
> other out-of-date references to 1.8 and update them?
Probably a good idea once all -next branches have been merged that could
bring in more references.
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2013-12-02 10:29 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-29 16:45 [Qemu-devel] [PULL 00/41] Block patches for 2.0 (flushing block-next) Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 01/41] block: make BdrvRequestFlags public Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 02/41] block: add flags to bdrv_*_write_zeroes Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 03/41] block: introduce BDRV_REQ_MAY_UNMAP request flag Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 04/41] block: add logical block provisioning info to BlockDriverInfo Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 05/41] block: add wrappers for logical block provisioning information Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 06/41] block/iscsi: add .bdrv_get_info Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 07/41] block: add BlockLimits structure to BlockDriverState Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 08/41] block/raw: copy BlockLimits on raw_open Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 09/41] block: honour BlockLimits in bdrv_co_do_write_zeroes Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 10/41] block: honour BlockLimits in bdrv_co_discard Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 11/41] iscsi: set limits in BlockDriverState Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 12/41] iscsi: simplify iscsi_co_discard Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 13/41] iscsi: add bdrv_co_write_zeroes Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 14/41] block: introduce bdrv_make_zero Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 15/41] block/get_block_status: fix BDRV_BLOCK_ZERO for unallocated blocks Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 16/41] qemu-img: add support for fully allocated images Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 17/41] qemu-img: conditionally zero out target on convert Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 18/41] util/error: Save errno from clobbering Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 19/41] Test coroutine execution order Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 20/41] sheepdog: implement .bdrv_get_allocated_file_size Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 21/41] block/stream: Don't stream unbacked devices Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 22/41] block: per caller dirty bitmap Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 23/41] qapi: Change BlockDirtyInfo to list Kevin Wolf
2013-11-30 20:38 ` Eric Blake
2013-12-02 10:29 ` Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 24/41] COW: Speed up writes Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 25/41] COW: Extend checking allocated bits to beyond one sector Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 26/41] MAINTAINERS: add sheepdog development mailing list Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 27/41] qdict: Fix memory leak in qdict_do_flatten() Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 28/41] qdict: Optimise qdict_do_flatten() Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 29/41] sheepdog: refactor do_sd_create() Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 30/41] sheepdog: support user-defined redundancy option Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 31/41] qemu-iotests: Drop local version of cancel_and_wait from 040 Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 32/41] blkdebug: add "remove_break" command Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 33/41] qemu-iotest: Add pause_drive and resume_drive methods Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 34/41] qemu-iotests: Make test case 030, 040 and 055 deterministic Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 35/41] block: Enable BDRV_O_SNAPSHOT with driver-specific options Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 36/41] qemu-iotests: Test snapshot mode Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 37/41] block: Use BDRV_O_NO_BACKING where appropriate Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 38/41] qemu-iotests: Filter qemu-io output in 025 Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 40/41] vmdk: Allow read only open of VMDK version 3 Kevin Wolf
2013-11-29 16:45 ` [Qemu-devel] [PULL 41/41] qemu-iotests: Add sample image and test for " Kevin Wolf
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).