From patchwork Fri Jun 15 15:05:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 165196 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 6E5F5B6FBE for ; Sat, 16 Jun 2012 02:26:30 +1000 (EST) Received: from localhost ([::1]:43974 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SfZLw-0001qU-As for incoming@patchwork.ozlabs.org; Fri, 15 Jun 2012 12:26:28 -0400 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) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=SlfC7RSIM9xUZ7c/aRFJXnsH1myOiPx9Y9/J9PwDLCw=; b=HlU1v/xTCZ74ZrudW0JKSvj9lghAWQcWSRQyytptk9/r3EmOjv4RSfL1j0ria+wKzx EqpmqIxAxbxVlglRnqUX+QyES9RnXx0lwq/5qI019roWZv6bOK5EML+aM6vgiVgAhpu0 9uFx1N+FL6tDY5ONnXExYQUbI+Oa8F+n2Z8p5rkhWWLbbcpo4O21b2TzRLNTPUQuWwq3 3o7zqsVErfpptaqTVKvPxFDalhsEfQk8tEtUqV70WfLrsFR4mkiByTybJpOFz9sNKiIK ta2m6RVMTgOFjDzi1OIrCbxCXdr3+2/wSi1d4Bi+3ogW/nHpntwVfBXc7XF0FXInuV+E DDmg== Received: by 10.68.217.40 with SMTP id ov8mr20933918pbc.131.1339772816644; Fri, 15 Jun 2012 08:06:56 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-204-25.ip51.fastwebnet.it. [93.34.204.25]) by mx.google.com with ESMTPS id rs3sm13501390pbc.47.2012.06.15.08.06.53 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 15 Jun 2012 08:06:55 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 15 Jun 2012 17:05:37 +0200 Message-Id: <1339772759-31004-15-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.10.2 In-Reply-To: <1339772759-31004-1-git-send-email-pbonzini@redhat.com> References: <1339772759-31004-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.45 Cc: kwolf@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [RFC PATCH 14/36] stream: add on_error argument 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 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, },