From patchwork Tue Mar 6 17:56:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 144971 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 88811B6F62 for ; Wed, 7 Mar 2012 04:58:27 +1100 (EST) Received: from localhost ([::1]:45234 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4yeX-00026M-Fz for incoming@patchwork.ozlabs.org; Tue, 06 Mar 2012 12:58:25 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56753) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4ydF-00085K-Ds for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:57:07 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4yd7-0002IW-8K for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:57:04 -0500 Received: from mail-gy0-f173.google.com ([209.85.160.173]:40828) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4yd6-0002I9-Uw for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:57 -0500 Received: by ghrr14 with SMTP id r14so2852300ghr.4 for ; Tue, 06 Mar 2012 09:56:55 -0800 (PST) Received-SPF: pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.203.98 as permitted sender) client-ip=10.50.203.98; Authentication-Results: mr.google.com; spf=pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.203.98 as permitted sender) smtp.mail=paolo.bonzini@gmail.com; dkim=pass header.i=paolo.bonzini@gmail.com Received: from mr.google.com ([10.50.203.98]) by 10.50.203.98 with SMTP id kp2mr11426186igc.5.1331056614765 (num_hops = 1); Tue, 06 Mar 2012 09:56:54 -0800 (PST) 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=SuRkWWYAEJJtfYaCCs0Bl0kotUhiQu/jdZaBUZqjfzU=; b=u2IhUcyP7tk6g+xqZbWKKvro2GaB8+5YLJqke/ZU6exyTjnfJ3a9bK+g5mHJmutH57 UA0Q7VInxLm4p8VzrKLsq67SbqfYsuT4RUQq6Kz0VhNvbF/SzKNpCgiN6+P94qm3tCyO Y4KoE39mgjVmln7hHnWje6d/6fFT3mHX45IE8aQLlfNG6M7UIeabXTKghuDpZPQd+Zva yy1xOD4lRY5YCGF+4adtoC5rJur9M6MPK6FrmRmOmjFmA4OrPxGi3zmm5kSOsrpSScYh SM51KcGdnIzHxnTrSZ2GrDjRet+pVQmcsTxIa+MmPtItkDyttBzSjcj7OuSlOsIb/4yJ nSoA== Received: by 10.50.203.98 with SMTP id kp2mr9532454igc.5.1331056614673; Tue, 06 Mar 2012 09:56:54 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id s8sm10504373igw.16.2012.03.06.09.56.51 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Mar 2012 09:56:53 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 6 Mar 2012 18:56:03 +0100 Message-Id: <1331056563-7503-11-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1331056563-7503-1-git-send-email-pbonzini@redhat.com> References: <1331056563-7503-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.173 Cc: kwolf@redhat.com, fsimonce@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v4 10/10] Add the drive-reopen command 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: Federico Simoncelli Signed-off-by: Federico Simoncelli Signed-off-by: Paolo Bonzini --- blockdev.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmp-commands.hx | 16 +++++++++++++ hmp.c | 11 +++++++++ hmp.h | 1 + qapi-schema.json | 22 ++++++++++++++++++ qmp-commands.hx | 30 +++++++++++++++++++++++++ 6 files changed, 143 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 2958419..df8ce14 100644 --- a/blockdev.c +++ b/blockdev.c @@ -646,6 +646,69 @@ void do_commit(Monitor *mon, const QDict *qdict) } } +static void change_blockdev_image(const char *device, const char *new_image_file, + const char *format, Error **errp) +{ + BlockDriverState *bs; + BlockDriver *drv, *old_drv, *proto_drv; + int ret = 0; + int flags; + char old_filename[1024]; + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + if (bdrv_in_use(bs)) { + error_set(errp, QERR_DEVICE_IN_USE, device); + return; + } + + pstrcpy(old_filename, sizeof(old_filename), bs->filename); + + old_drv = bs->drv; + flags = bs->open_flags; + + drv = bdrv_find_format(format); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + proto_drv = bdrv_find_protocol(new_image_file); + if (!proto_drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + bdrv_drain_all(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, new_image_file, flags, drv); + /* + * If reopening the image file we just created fails, fall back + * and try to re-open the original image. If that fails too, we + * are in serious trouble. + */ + if (ret != 0) { + ret = bdrv_open(bs, old_filename, flags, old_drv); + if (ret != 0) { + error_set(errp, QERR_OPEN_FILE_FAILED, old_filename); + } else { + error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); + } + } +} + +void qmp_drive_reopen(const char *device, const char *new_image_file, + bool has_format, const char *format, Error **errp) +{ + change_blockdev_image(device, new_image_file, + has_format ? format : "qcow2", errp); +} + static void blockdev_do_action(int kind, void *data, Error **errp) { BlockdevAction action; diff --git a/hmp-commands.hx b/hmp-commands.hx index 9c49c33..4afde71 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -925,6 +925,22 @@ using the specified target. ETEXI { + .name = "drive_reopen", + .args_type = "device:B,new-image-file:s,format:s?", + .params = "device new-image-file [format]", + .help = "Assigns a new image file to a device.\n\t\t\t" + "The image will be opened using the format\n\t\t\t" + "specified or 'qcow2' by default.\n\t\t\t", + .mhandler.cmd = hmp_drive_reopen, + }, + +STEXI +@item drive_reopen +@findex drive_reopen +Assigns a new image file to a device. +ETEXI + + { .name = "drive_add", .args_type = "pci_addr:s,opts:s", .params = "[[:]:]\n" diff --git a/hmp.c b/hmp.c index e706db9..ec41d83 100644 --- a/hmp.c +++ b/hmp.c @@ -738,6 +738,17 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &errp); } +void hmp_drive_reopen(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "new-image-file"); + const char *format = qdict_get_try_str(qdict, "format"); + Error *errp = NULL; + + qmp_drive_reopen(device, filename, !!format, format, &errp); + hmp_handle_error(mon, &errp); +} + void hmp_migrate_cancel(Monitor *mon, const QDict *qdict) { qmp_migrate_cancel(NULL); diff --git a/hmp.h b/hmp.h index 5352f00..648a84f 100644 --- a/hmp.h +++ b/hmp.h @@ -49,6 +49,7 @@ void hmp_balloon(Monitor *mon, const QDict *qdict); void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); void hmp_drive_mirror(Monitor *mon, const QDict *qdict); +void hmp_drive_reopen(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); diff --git a/qapi-schema.json b/qapi-schema.json index 4cebf78..21eb256 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1235,6 +1235,28 @@ '*mode': 'NewImageMode'} } ## +# @drive-reopen +# +# Assigns a new image file to a device. +# +# @device: the name of the device for which we are changing the image file. +# +# @new-image-file: the target of the new image. If the file doesn't exists the +# command will fail. +# +# @format: #optional the format of the new image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @new-image-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Since 1.1 +## +{ 'command': 'drive-reopen', + 'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } } + +## # @human-monitor-command: # # Execute a command on the human monitor and return the output. diff --git a/qmp-commands.hx b/qmp-commands.hx index 122ebe7..7fc30c2 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -818,6 +818,36 @@ Example: EQMP { + .name = "drive-reopen", + .args_type = "device:B,new-image-file:s,format:s?", + .mhandler.cmd_new = qmp_marshal_input_drive_reopen, + }, + +SQMP +drive-reopen +------------ + +Assigns a new image file to a device. Except extremely rare cases where the +guest is expecting the drive to change its content, the new image should +contain the same data of the current one. One use case is to terminate +a drive-mirror command. + +Arguments: + +- "device": device name to operate on (json-string) +- "new-image-file": name of new image file (json-string) +- "format": format of new image (json-string, optional) + +Example: + +-> { "execute": "drive-reopen", "arguments": {"device": "ide-hd0", + "new-image-file": "/some/place/my-image", + "format": "qcow2" } } +<- { "return": {} } + +EQMP + + { .name = "balloon", .args_type = "value:M", .mhandler.cmd_new = qmp_marshal_input_balloon,