From patchwork Tue Sep 25 16:29:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Cody X-Patchwork-Id: 186859 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 EACEC2C007D for ; Wed, 26 Sep 2012 03:16:43 +1000 (EST) Received: from localhost ([::1]:60304 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGY1t-0005N9-V2 for incoming@patchwork.ozlabs.org; Tue, 25 Sep 2012 12:30:37 -0400 Received: from eggs.gnu.org ([208.118.235.92]:52923) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGY1H-0003x8-4U for qemu-devel@nongnu.org; Tue, 25 Sep 2012 12:30:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TGY1C-00021k-8w for qemu-devel@nongnu.org; Tue, 25 Sep 2012 12:29:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:29039) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGY1B-00021f-WF for qemu-devel@nongnu.org; Tue, 25 Sep 2012 12:29:54 -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 q8PGTrpD028520 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 25 Sep 2012 12:29:53 -0400 Received: from localhost ([10.3.112.11]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q8PGTpLw019268 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Tue, 25 Sep 2012 12:29:52 -0400 From: Jeff Cody To: qemu-devel@nongnu.org Date: Tue, 25 Sep 2012 12:29:37 -0400 Message-Id: <75bbfc268498ae3733d7ffb896ab0852527d5b11.1348589526.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: 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: kwolf@redhat.com, pbonzini@redhat.com, eblake@redhat.com Subject: [Qemu-devel] [PATCH v2 5/7] QAPI: add command for live block commit, 'block-commit' 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 The command for live block commit is added, which has the following arguments: device: the block device to perform the commit on (mandatory) base: the base image to commit into; optional (if not specified, it is the underlying original image) top: the top image of the commit - all data from inside top down to base will be committed into base. optional (if not specified, it is one below the active image) - see note below speed: maximum speed, in bytes/sec note: eventually this will support merging down the active layer, but that code is not yet complete. If the active layer is passed in currently as top, or top is left to the default, then an error will be returned. The is done as a block job, so upon completion a BLOCK_JOB_COMPLETED will be emitted. Signed-off-by: Jeff Cody --- QMP/qmp-events.txt | 6 +++-- blockdev.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ qapi-schema.json | 35 +++++++++++++++++++++++++++++ qmp-commands.hx | 6 +++++ 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 2878058..4491020 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -50,7 +50,8 @@ Emitted when a block job has been cancelled. Data: -- "type": Job type ("stream" for image streaming, json-string) +- "type": Job type (json-string; "stream" for image streaming + "commit" for block commit) - "device": Device name (json-string) - "len": Maximum progress value (json-int) - "offset": Current progress value (json-int) @@ -73,7 +74,8 @@ Emitted when a block job has completed. Data: -- "type": Job type ("stream" for image streaming, json-string) +- "type": Job type (json-string; "stream" for image streaming + "commit" for block commit) - "device": Device name (json-string) - "len": Maximum progress value (json-int) - "offset": Current progress value (json-int) diff --git a/blockdev.c b/blockdev.c index 9caa16f..6f1080c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1124,6 +1124,70 @@ void qmp_block_stream(const char *device, bool has_base, trace_qmp_block_stream(bs, bs->job); } +void qmp_block_commit(const char *device, + bool has_base, const char *base, + bool has_top, const char *top, + bool has_speed, int64_t speed, + Error **errp) +{ + BlockDriverState *bs; + BlockDriverState *base_bs, *top_bs; + Error *local_err = NULL; + /* This will be part of the QMP command, if/when the + * BlockdevOnError change for blkmirror makes it in + */ + BlockErrorAction on_error = BLOCK_ERR_REPORT; + + /* drain all i/o before commits */ + bdrv_drain_all(); + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + if (base && has_base) { + base_bs = bdrv_find_backing_image(bs, base); + } else { + base_bs = bdrv_find_base(bs); + } + + if (base_bs == NULL) { + error_set(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL"); + return; + } + + if (top && has_top) { + /* if we want to allow the active layer, + * use 'bdrv_find_image()' here */ + top_bs = bdrv_find_backing_image(bs, top); + } else { + /* default is one below the active layer, unless that is + * the base */ + top_bs = bs->backing_hd; + if (top_bs == base_bs) { + error_setg(errp, + "Invalid files for merge: top and base are the same"); + return; + } + } + if (top_bs == NULL) { + error_setg(errp, "Top image file %s not found", top ? top : "NULL"); + return; + } + + commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs, + &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + /* Grab a reference so hotplug does not delete the BlockDriverState from + * underneath us. + */ + drive_get_ref(drive_get_by_blockdev(bs)); +} + static BlockJob *find_block_job(const char *device) { BlockDriverState *bs; diff --git a/qapi-schema.json b/qapi-schema.json index 14e4419..e614453 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1468,6 +1468,41 @@ 'returns': 'str' } ## +# @block-commit +# +# Live commit of data from overlay image nodes into backing nodes - i.e., +# writes data between 'top' and 'base' into 'base'. +# +# @device: the name of the device +# +# @base: #optional The file name of the backing image to write data into. +# If not specified, this is the deepest backing image +# +# @top: #optional The file name of the backing image within the image chain, +# which contains the topmost data to be committed down. +# If not specified, this is one layer below the active +# layer (i.e. active->backing_hd). +# +# If top == base, that is an error. +# +# +# @speed: #optional the maximum speed, in bytes per second +# +# Returns: Nothing on success +# If commit or stream is already active on this device, DeviceInUse +# If @device does not exist, DeviceNotFound +# If image commit is not supported by this device, NotSupported +# If @base does not exist, a generic error is returned +# If @top does not exist, a generic error is returned +# If @speed is invalid, InvalidParameter +# +# Since: 1.3 +# +## +{ 'command': 'block-commit', + 'data': { 'device': 'str', '*base': 'str', '*top': 'str', + '*speed': 'int' } } + # @migrate_cancel # # Cancel the current executing migration process. diff --git a/qmp-commands.hx b/qmp-commands.hx index 6e21ddb..e244763 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -792,6 +792,12 @@ EQMP }, { + .name = "block-commit", + .args_type = "device:B,base:s?,top:s?,speed:o?", + .mhandler.cmd_new = qmp_marshal_input_block_commit, + }, + + { .name = "block-job-set-speed", .args_type = "device:B,speed:o", .mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,