From patchwork Wed Apr 25 13:17:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 155021 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B968EB6EF3 for ; Thu, 26 Apr 2012 01:56:59 +1000 (EST) Received: from localhost ([::1]:53711 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SN3Cm-0004P0-OQ for incoming@patchwork.ozlabs.org; Wed, 25 Apr 2012 10:28:28 -0400 Received: from eggs.gnu.org ([208.118.235.92]:50562) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SN3CN-0003Wc-Sf for qemu-devel@nongnu.org; Wed, 25 Apr 2012 10:28:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SN3CC-0006Ex-FF for qemu-devel@nongnu.org; Wed, 25 Apr 2012 10:28:03 -0400 Received: from e06smtp14.uk.ibm.com ([195.75.94.110]:57775) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SN3CC-0006Dl-3H for qemu-devel@nongnu.org; Wed, 25 Apr 2012 10:27:52 -0400 Received: from /spool/local by e06smtp14.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 25 Apr 2012 14:17:22 +0100 Received: from d06nrmr1806.portsmouth.uk.ibm.com (9.149.39.193) by e06smtp14.uk.ibm.com (192.168.101.144) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 25 Apr 2012 14:17:21 +0100 Received: from d06av05.portsmouth.uk.ibm.com (d06av05.portsmouth.uk.ibm.com [9.149.37.229]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q3PDHL5Q2670702 for ; Wed, 25 Apr 2012 14:17:21 +0100 Received: from d06av05.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av05.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q3PDHK3K001398 for ; Wed, 25 Apr 2012 07:17:20 -0600 Received: from localhost ([9.145.156.72]) by d06av05.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q3PDHKQU001379; Wed, 25 Apr 2012 07:17:20 -0600 From: Stefan Hajnoczi To: Date: Wed, 25 Apr 2012 14:17:10 +0100 Message-Id: <1335359831-18473-5-git-send-email-stefanha@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1335359831-18473-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1335359831-18473-1-git-send-email-stefanha@linux.vnet.ibm.com> x-cbid: 12042513-1948-0000-0000-0000019F97DA X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 195.75.94.110 Cc: Kevin Wolf , Paolo Bonzini , Eric Blake , Stefan Hajnoczi , Luiz Capitulino Subject: [Qemu-devel] [PATCH v3 4/5] block: add 'speed' optional parameter to block-stream X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Allow streaming operations to be started with an initial speed limit. This eliminates the window of time between starting streaming and issuing block-job-set-speed. Users should use the new optional 'speed' parameter instead so that speed limits are in effect immediately when the job starts. Signed-off-by: Stefan Hajnoczi Acked-by: Kevin Wolf --- block.c | 18 ++++++++++++++++-- block/stream.c | 5 +++-- block_int.h | 9 ++++++--- blockdev.c | 6 ++++-- hmp-commands.hx | 4 ++-- hmp.c | 4 +++- qapi-schema.json | 9 +++++++-- qmp-commands.hx | 2 +- 8 files changed, 42 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index 1ab6e52..43c794c 100644 --- a/block.c +++ b/block.c @@ -4083,8 +4083,8 @@ out: } void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque, - Error **errp) + int64_t speed, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp) { BlockJob *job; @@ -4100,6 +4100,20 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, job->cb = cb; job->opaque = opaque; bs->job = job; + + /* Only set speed when necessary to avoid NotSupported error */ + if (speed != 0) { + Error *local_err = NULL; + + block_job_set_speed(job, speed, &local_err); + if (error_is_set(&local_err)) { + bs->job = NULL; + g_free(job); + bdrv_set_in_use(bs, 0); + error_propagate(errp, local_err); + return NULL; + } + } return job; } diff --git a/block/stream.c b/block/stream.c index b66242a..6724af2 100644 --- a/block/stream.c +++ b/block/stream.c @@ -281,13 +281,14 @@ static BlockJobType stream_job_type = { }; void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, BlockDriverCompletionFunc *cb, + const char *base_id, int64_t speed, + BlockDriverCompletionFunc *cb, void *opaque, Error **errp) { StreamBlockJob *s; Coroutine *co; - s = block_job_create(&stream_job_type, bs, cb, opaque, errp); + s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp); if (!s) { return; } diff --git a/block_int.h b/block_int.h index 624b2e6..086832a 100644 --- a/block_int.h +++ b/block_int.h @@ -344,6 +344,7 @@ int is_windows_drive(const char *filename); * block_job_create: * @job_type: The class object for the newly-created job. * @bs: The block + * @speed: The maximum speed, in bytes per second, or 0 for unlimited. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. * @errp: Error object. @@ -358,8 +359,8 @@ int is_windows_drive(const char *filename); * called from a wrapper that is specific to the job type. */ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque, - Error **errp); + int64_t speed, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp); /** * block_job_complete: @@ -418,6 +419,7 @@ void block_job_cancel_sync(BlockJob *job); * flatten the whole backing file chain onto @bs. * @base_id: The file name that will be written to @bs as the new * backing file if the job completes. Ignored if @base is %NULL. + * @speed: The maximum speed, in bytes per second, or 0 for unlimited. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. * @errp: Error object. @@ -429,7 +431,8 @@ void block_job_cancel_sync(BlockJob *job); * @base_id in the written image and to @base in the live BlockDriverState. */ void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, BlockDriverCompletionFunc *cb, + const char *base_id, int64_t speed, + BlockDriverCompletionFunc *cb, void *opaque, Error **errp); #endif /* BLOCK_INT_H */ diff --git a/blockdev.c b/blockdev.c index 80b62c3..d25ffea 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1091,7 +1091,8 @@ static void block_stream_cb(void *opaque, int ret) } void qmp_block_stream(const char *device, bool has_base, - const char *base, Error **errp) + const char *base, bool has_speed, + int64_t speed, Error **errp) { BlockDriverState *bs; BlockDriverState *base_bs = NULL; @@ -1111,7 +1112,8 @@ void qmp_block_stream(const char *device, bool has_base, } } - stream_start(bs, base_bs, base, block_stream_cb, bs, &local_err); + stream_start(bs, base_bs, base, has_speed ? speed : 0, + block_stream_cb, bs, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); return; diff --git a/hmp-commands.hx b/hmp-commands.hx index 8a929f0..18cb415 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -71,8 +71,8 @@ ETEXI { .name = "block_stream", - .args_type = "device:B,base:s?", - .params = "device [base]", + .args_type = "device:B,speed:o?,base:s?", + .params = "device [speed [base]]", .help = "copy data from a backing file into a block device", .mhandler.cmd = hmp_block_stream, }, diff --git a/hmp.c b/hmp.c index f3e5163..eb96618 100644 --- a/hmp.c +++ b/hmp.c @@ -835,8 +835,10 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict) Error *error = NULL; const char *device = qdict_get_str(qdict, "device"); const char *base = qdict_get_try_str(qdict, "base"); + int64_t speed = qdict_get_try_int(qdict, "speed", 0); - qmp_block_stream(device, base != NULL, base, &error); + qmp_block_stream(device, base != NULL, base, + qdict_haskey(qdict, "speed"), speed, &error); hmp_handle_error(mon, &error); } diff --git a/qapi-schema.json b/qapi-schema.json index d56fcb6..9193fb9 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1571,15 +1571,19 @@ # # @base: #optional the common backing file name # +# @speed: #optional the maximum speed, in bytes per second +# # Returns: Nothing on success # If streaming is already active on this device, DeviceInUse # If @device does not exist, DeviceNotFound # If image streaming is not supported by this device, NotSupported # If @base does not exist, BaseNotFound +# If @speed is invalid, InvalidParameter # # Since: 1.1 ## -{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str' } } +{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str', + '*speed': 'int' } } ## # @block-job-set-speed: @@ -1592,7 +1596,8 @@ # # @device: the device name # -# @speed: the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second, or 0 for unlimited. +# Defaults to 0. # # Returns: Nothing on success # If the job type does not support throttling, NotSupported diff --git a/qmp-commands.hx b/qmp-commands.hx index b07ed59..c810c74 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -688,7 +688,7 @@ EQMP { .name = "block-stream", - .args_type = "device:B,base:s?", + .args_type = "device:B,base:s?,speed:o?", .mhandler.cmd_new = qmp_marshal_input_block_stream, },