From patchwork Fri Apr 27 15:00:59 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 155534 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 ABCA3B6FA7 for ; Sat, 28 Apr 2012 02:18:29 +1000 (EST) Received: from localhost ([::1]:52523 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SNnTK-0007q7-7P for incoming@patchwork.ozlabs.org; Fri, 27 Apr 2012 11:52:38 -0400 Received: from eggs.gnu.org ([208.118.235.92]:52649) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SNnSN-0006VV-R2 for qemu-devel@nongnu.org; Fri, 27 Apr 2012 11:51:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SNnSL-0006zZ-6v for qemu-devel@nongnu.org; Fri, 27 Apr 2012 11:51:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34858) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SNnSK-0006zK-UQ for qemu-devel@nongnu.org; Fri, 27 Apr 2012 11:51:37 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q3RFpUK6028988 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 27 Apr 2012 11:51:32 -0400 Received: from localhost (ovpn-116-78.ams2.redhat.com [10.36.116.78]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q3RF14gP005962; Fri, 27 Apr 2012 11:01:05 -0400 From: Luiz Capitulino To: aliguori@us.ibm.com Date: Fri, 27 Apr 2012 12:00:59 -0300 Message-Id: <1335538861-24977-5-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1335538861-24977-1-git-send-email-lcapitulino@redhat.com> References: <1335538861-24977-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org, Stefan Hajnoczi Subject: [Qemu-devel] [PULL 4/6] 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 From: Stefan Hajnoczi 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 Signed-off-by: Luiz Capitulino --- 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, },