[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 1/6] block-commit: Expose granularity
From: |
Max Reitz |
Subject: |
[Qemu-devel] [PATCH v4 1/6] block-commit: Expose granularity |
Date: |
Sat, 12 Apr 2014 20:57:35 +0200 |
Allow QMP users to manipulate the granularity used in the block-commit
command.
Signed-off-by: Max Reitz <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
---
block/commit.c | 16 +++++++++++++---
block/mirror.c | 4 ++--
blockdev.c | 22 ++++++++++++++++------
include/block/block_int.h | 10 ++++++----
qapi-schema.json | 6 +++++-
5 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/block/commit.c b/block/commit.c
index acec4ac..cf0e500 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -37,6 +37,7 @@ typedef struct CommitBlockJob {
BlockdevOnError on_error;
int base_flags;
int orig_overlay_flags;
+ int64_t granularity;
} CommitBlockJob;
static int coroutine_fn commit_populate(BlockDriverState *bs,
@@ -93,7 +94,7 @@ static void coroutine_fn commit_run(void *opaque)
}
end = s->common.len >> BDRV_SECTOR_BITS;
- buf = qemu_blockalign(top, COMMIT_BUFFER_SIZE);
+ buf = qemu_blockalign(top, s->granularity);
for (sector_num = 0; sector_num < end; sector_num += n) {
uint64_t delay_ns = 0;
@@ -109,7 +110,7 @@ wait:
}
/* Copy if allocated above the base */
ret = bdrv_is_allocated_above(top, base, sector_num,
- COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
+ s->granularity / BDRV_SECTOR_SIZE,
&n);
copy = (ret == 1);
trace_commit_one_iteration(s, sector_num, n, ret);
@@ -180,7 +181,7 @@ static const BlockJobDriver commit_job_driver = {
};
void commit_start(BlockDriverState *bs, BlockDriverState *base,
- BlockDriverState *top, int64_t speed,
+ BlockDriverState *top, int64_t speed, int64_t granularity,
BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
{
@@ -214,6 +215,13 @@ void commit_start(BlockDriverState *bs, BlockDriverState
*base,
orig_base_flags = bdrv_get_flags(base);
orig_overlay_flags = bdrv_get_flags(overlay_bs);
+ if (!granularity) {
+ granularity = COMMIT_BUFFER_SIZE;
+ }
+
+ assert(granularity >= BDRV_SECTOR_SIZE);
+ assert(is_power_of_2(granularity));
+
/* convert base & overlay_bs to r/w, if necessary */
if (!(orig_base_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, base,
@@ -244,6 +252,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState
*base,
s->base_flags = orig_base_flags;
s->orig_overlay_flags = orig_overlay_flags;
+ s->granularity = granularity;
+
s->on_error = on_error;
s->common.co = qemu_coroutine_create(commit_run);
diff --git a/block/mirror.c b/block/mirror.c
index 0ef41f9..5b1ebb2 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -632,7 +632,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState
*target,
}
void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
- int64_t speed,
+ int64_t speed, int64_t granularity,
BlockdevOnError on_error,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
@@ -674,7 +674,7 @@ void commit_active_start(BlockDriverState *bs,
BlockDriverState *base,
}
bdrv_ref(base);
- mirror_start_job(bs, base, speed, 0, 0,
+ mirror_start_job(bs, base, speed, granularity, 0,
on_error, on_error, cb, opaque, &local_err,
&commit_active_job_driver, false, base);
if (error_is_set(&local_err)) {
diff --git a/blockdev.c b/blockdev.c
index 5dd01ea..9d7bd04 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1865,8 +1865,8 @@ void qmp_block_stream(const char *device, bool has_base,
void qmp_block_commit(const char *device,
bool has_base, const char *base, const char *top,
- bool has_speed, int64_t speed,
- Error **errp)
+ bool has_speed, int64_t speed, bool has_granularity,
+ int64_t granularity, Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs, *top_bs;
@@ -1879,6 +1879,16 @@ void qmp_block_commit(const char *device,
if (!has_speed) {
speed = 0;
}
+ if (!has_granularity) {
+ granularity = 0;
+ }
+
+ if (granularity &&
+ (granularity < BDRV_SECTOR_SIZE || !is_power_of_2(granularity)))
+ {
+ error_set(errp, QERR_INVALID_PARAMETER, "granularity");
+ return;
+ }
/* drain all i/o before commits */
bdrv_drain_all();
@@ -1915,11 +1925,11 @@ void qmp_block_commit(const char *device,
}
if (top_bs == bs) {
- commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
- bs, &local_err);
+ commit_active_start(bs, base_bs, speed, granularity, on_error,
+ block_job_cb, bs, &local_err);
} else {
- commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs,
- &local_err);
+ commit_start(bs, base_bs, top_bs, speed, granularity, on_error,
+ block_job_cb, bs, &local_err);
}
if (local_err != NULL) {
error_propagate(errp, local_err);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index cd5bc73..c01b4aa 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -426,6 +426,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState
*base,
* @top: Top block device to be committed.
* @base: Block device that will be written into, and become the new top.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
+ * @granularity: The granularity, in bytes, or 0 for a default value.
* @on_error: The action to take upon error.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
@@ -433,14 +434,15 @@ void stream_start(BlockDriverState *bs, BlockDriverState
*base,
*
*/
void commit_start(BlockDriverState *bs, BlockDriverState *base,
- BlockDriverState *top, int64_t speed,
- BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
- void *opaque, Error **errp);
+ BlockDriverState *top, int64_t speed, int64_t granularity,
+ BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp);
/**
* commit_active_start:
* @bs: Active block device to be committed.
* @base: Block device that will be written into, and become the new top.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
+ * @granularity: The granularity, in bytes, or 0 for cluster size.
* @on_error: The action to take upon error.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
@@ -448,7 +450,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState
*base,
*
*/
void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
- int64_t speed,
+ int64_t speed, int64_t granularity,
BlockdevOnError on_error,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
diff --git a/qapi-schema.json b/qapi-schema.json
index 391356f..151fad3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2112,6 +2112,10 @@
#
# @speed: #optional the maximum speed, in bytes per second
#
+# @granularity: #optional the granularity to be used for the operation, in
+# bytes; has to be a power of two and at least 512, or 0 for the
+# default value (since 2.1)
+#
# Returns: Nothing on success
# If commit or stream is already active on this device, DeviceInUse
# If @device does not exist, DeviceNotFound
@@ -2124,7 +2128,7 @@
##
{ 'command': 'block-commit',
'data': { 'device': 'str', '*base': 'str', 'top': 'str',
- '*speed': 'int' } }
+ '*speed': 'int', '*granularity': 'int' } }
##
# @drive-backup
--
1.9.2