From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:57834) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SfY77-0003kk-47 for qemu-devel@nongnu.org; Fri, 15 Jun 2012 11:07:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SfY6z-0004qi-Qm for qemu-devel@nongnu.org; Fri, 15 Jun 2012 11:07:04 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:47190) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SfY6z-0004gs-Hr for qemu-devel@nongnu.org; Fri, 15 Jun 2012 11:06:57 -0400 Received: by mail-pb0-f45.google.com with SMTP id ro12so5648793pbb.4 for ; Fri, 15 Jun 2012 08:06:56 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Fri, 15 Jun 2012 17:05:37 +0200 Message-Id: <1339772759-31004-15-git-send-email-pbonzini@redhat.com> In-Reply-To: <1339772759-31004-1-git-send-email-pbonzini@redhat.com> References: <1339772759-31004-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [RFC PATCH 14/36] stream: add on_error argument List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com This patch adds support for error management to streaming. Signed-off-by: Paolo Bonzini --- block/stream.c | 28 +++++++++++++++++++++++++++- block_int.h | 3 ++- blockdev.c | 11 ++++++++--- hmp.c | 3 ++- qapi-schema.json | 9 ++++++--- qmp-commands.hx | 2 +- 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/block/stream.c b/block/stream.c index b3ede44..270c8d8 100644 --- a/block/stream.c +++ b/block/stream.c @@ -31,6 +31,7 @@ typedef struct StreamBlockJob { BlockJob common; RateLimit limit; BlockDriverState *base; + BlockdevOnError on_error; char backing_file_id[1024]; } StreamBlockJob; @@ -78,6 +79,7 @@ static void coroutine_fn stream_run(void *opaque) BlockDriverState *bs = s->common.bs; BlockDriverState *base = s->base; int64_t sector_num, end; + int error = 0; int ret = 0; int n = 0; void *buf; @@ -136,7 +138,19 @@ wait: ret = stream_populate(bs, sector_num, n, buf); } if (ret < 0) { - break; + BlockErrorAction action = + block_job_error_action(&s->common, s->common.bs, s->on_error, + true, -ret); + if (action == BDRV_ACTION_STOP) { + n = 0; + continue; + } + if (error == 0) { + error = ret; + } + if (action == BDRV_ACTION_REPORT) { + break; + } } ret = 0; @@ -148,6 +162,9 @@ wait: bdrv_disable_copy_on_read(bs); } + /* Do not remove the backing file if an error was there but ignored. */ + ret = error; + if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) { const char *base_id = NULL, *base_fmt = NULL; if (base) { @@ -183,11 +200,19 @@ static BlockJobType stream_job_type = { void stream_start(BlockDriverState *bs, BlockDriverState *base, const char *base_id, int64_t speed, + BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp) { StreamBlockJob *s; + if ((on_error == BLOCKDEV_ON_ERROR_STOP || + on_error == BLOCKDEV_ON_ERROR_ENOSPC) && + !bdrv_iostatus_is_enabled(bs)) { + error_set(errp, QERR_INVALID_PARAMETER_COMBINATION); + return; + } + s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp); if (!s) { return; @@ -198,6 +223,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id); } + s->on_error = on_error; s->common.co = qemu_coroutine_create(stream_run); trace_stream_start(bs, base, s, s->common.co, opaque); qemu_coroutine_enter(s->common.co, s); diff --git a/block_int.h b/block_int.h index 53fec71..731ef1a 100644 --- a/block_int.h +++ b/block_int.h @@ -290,6 +290,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, * @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. + * @on_error: The action to take upon error. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. * @errp: Error object. @@ -301,7 +302,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, * @base_id in the written image and to @base in the live BlockDriverState. */ void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, int64_t speed, + const char *base_id, int64_t speed, BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); diff --git a/blockdev.c b/blockdev.c index 51bc488..adb21b9 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1092,13 +1092,18 @@ static void block_stream_cb(void *opaque, int ret) } void qmp_block_stream(const char *device, bool has_base, - const char *base, bool has_speed, - int64_t speed, Error **errp) + const char *base, bool has_speed, int64_t speed, + bool has_on_error, BlockdevOnError on_error, + Error **errp) { BlockDriverState *bs; BlockDriverState *base_bs = NULL; Error *local_err = NULL; + if (!has_on_error) { + on_error = BLOCKDEV_ON_ERROR_REPORT; + } + bs = bdrv_find(device); if (!bs) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); @@ -1114,7 +1119,7 @@ void qmp_block_stream(const char *device, bool has_base, } stream_start(bs, base_bs, base, has_speed ? speed : 0, - block_stream_cb, bs, &local_err); + on_error, block_stream_cb, bs, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); return; diff --git a/hmp.c b/hmp.c index 9f6b255..b91fd32 100644 --- a/hmp.c +++ b/hmp.c @@ -843,7 +843,8 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict) int64_t speed = qdict_get_try_int(qdict, "speed", 0); qmp_block_stream(device, base != NULL, base, - qdict_haskey(qdict, "speed"), speed, &error); + qdict_haskey(qdict, "speed"), speed, + BLOCKDEV_ON_ERROR_REPORT, true, &error); hmp_handle_error(mon, &error); } diff --git a/qapi-schema.json b/qapi-schema.json index 0a1a35b..3c99dbb 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1650,6 +1650,8 @@ # # @speed: #optional the maximum speed, in bytes per second # +# @on_error: #optional the action to take on an error (default report) +# # Returns: Nothing on success # If streaming is already active on this device, DeviceInUse # If @device does not exist, DeviceNotFound @@ -1657,10 +1659,11 @@ # If @base does not exist, BaseNotFound # If @speed is invalid, InvalidParameter # -# Since: 1.1 +# Since: 1.1, on_error since 1.2 ## -{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str', - '*speed': 'int' } } +{ 'command': 'block-stream', + 'data': { 'device': 'str', '*base': 'str', '*speed': 'int', + '*on_error': 'BlockdevOnError' } } ## # @block-job-set-speed: diff --git a/qmp-commands.hx b/qmp-commands.hx index f20754a..e2d77b6 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -718,7 +718,7 @@ EQMP { .name = "block-stream", - .args_type = "device:B,base:s?,speed:o?", + .args_type = "device:B,base:s?,speed:o?,on_error:s?", .mhandler.cmd_new = qmp_marshal_input_block_stream, }, -- 1.7.10.2