From patchwork Wed Jul 27 13:44:49 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 107100 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 47D38B6F62 for ; Thu, 28 Jul 2011 01:09:39 +1000 (EST) Received: from localhost ([::1]:36739 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qm4R9-0001zB-Os for incoming@patchwork.ozlabs.org; Wed, 27 Jul 2011 09:46:11 -0400 Received: from eggs.gnu.org ([140.186.70.92]:33436) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qm4Q9-0007FN-S4 for qemu-devel@nongnu.org; Wed, 27 Jul 2011 09:45:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qm4Q8-0004Yv-Cn for qemu-devel@nongnu.org; Wed, 27 Jul 2011 09:45:09 -0400 Received: from mtagate1.uk.ibm.com ([194.196.100.161]:53119) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qm4Q7-0004YJ-Va for qemu-devel@nongnu.org; Wed, 27 Jul 2011 09:45:08 -0400 Received: from d06nrmr1806.portsmouth.uk.ibm.com (d06nrmr1806.portsmouth.uk.ibm.com [9.149.39.193]) by mtagate1.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p6RDj7ru003523 for ; Wed, 27 Jul 2011 13:45:07 GMT Received: from d06av09.portsmouth.uk.ibm.com (d06av09.portsmouth.uk.ibm.com [9.149.37.250]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p6RDj73L2621532 for ; Wed, 27 Jul 2011 14:45:07 +0100 Received: from d06av09.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p6RDj6pU016281 for ; Wed, 27 Jul 2011 07:45:06 -0600 Received: from stefanha-thinkpad.ibm.com ([9.78.66.144]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p6RDj1DI016013; Wed, 27 Jul 2011 07:45:06 -0600 From: Stefan Hajnoczi To: Date: Wed, 27 Jul 2011 14:44:49 +0100 Message-Id: <1311774295-8696-10-git-send-email-stefanha@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1311774295-8696-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1311774295-8696-1-git-send-email-stefanha@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 194.196.100.161 Cc: Kevin Wolf , Anthony Liguori , Stefan Hajnoczi , Adam Litke Subject: [Qemu-devel] [PATCH 09/15] qmp: add block_job_cancel 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 Image streaming operations can be stopped using the block_job_cancel command. In the future other types of background operations on block devices can be cancelled using this command. The command synopsis is: block_job_cancel ---------------- Stop an active block streaming operation. This command returns once the active block streaming operation has been stopped. It is an error to call this command if no operation is in progress. The image file retains its backing file unless the streaming operation happens to complete just as it is being cancelled. A new block streaming operation can be started at a later time to finish copying all data from the backing file. Arguments: - device: device name (json-string) Errors: DeviceNotActive: streaming is not active on this device DeviceInUse: cancellation already in progress Examples: -> { "execute": "block_job_cancel", "arguments": { "device": "virtio0" } } <- { "return": {} } Signed-off-by: Stefan Hajnoczi --- blockdev.c | 34 ++++++++++++++++++++++++++++++++++ blockdev.h | 3 +++ hmp-commands.hx | 15 +++++++++++++++ qmp-commands.hx | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index cd5e49c..e9bc577 100644 --- a/blockdev.c +++ b/blockdev.c @@ -52,6 +52,8 @@ static const int if_max_devs[IF_COUNT] = { }; typedef struct StreamState { + MonitorCompletion *cancel_cb; + void *cancel_opaque; int64_t offset; /* current position in block device */ BlockDriverState *bs; QEMUTimer *timer; @@ -90,6 +92,10 @@ static void stream_free(StreamState *s) { QLIST_REMOVE(s, list); + if (s->cancel_cb) { + s->cancel_cb(s->cancel_opaque, NULL); + } + qemu_del_timer(s->timer); qemu_free_timer(s->timer); qemu_free(s); @@ -115,6 +121,8 @@ static void stream_cb(void *opaque, int nb_sectors) if (s->offset == bdrv_getlength(s->bs)) { bdrv_change_backing_file(s->bs, NULL, NULL); stream_complete(s, 0); + } else if (s->cancel_cb) { + stream_free(s); } else { qemu_mod_timer(s->timer, qemu_get_clock_ns(rt_clock)); } @@ -176,6 +184,24 @@ static StreamState *stream_start(const char *device) return s; } +static int stream_stop(const char *device, MonitorCompletion *cb, void *opaque) +{ + StreamState *s = stream_find(device); + + if (!s) { + qerror_report(QERR_DEVICE_NOT_ACTIVE, device); + return -1; + } + if (s->cancel_cb) { + qerror_report(QERR_DEVICE_IN_USE, device); + return -1; + } + + s->cancel_cb = cb; + s->cancel_opaque = opaque; + return 0; +} + /* * We automatically delete the drive when a device using it gets * unplugged. Questionable feature, but we can't just drop it. @@ -783,6 +809,14 @@ int do_block_stream(Monitor *mon, const QDict *params, QObject **ret_data) return stream_start(device) ? 0 : -1; } +int do_block_job_cancel(Monitor *mon, const QDict *params, + MonitorCompletion cb, void *opaque) +{ + const char *device = qdict_get_str(params, "device"); + + return stream_stop(device, cb, opaque); +} + static int eject_device(Monitor *mon, BlockDriverState *bs, int force) { if (!force) { diff --git a/blockdev.h b/blockdev.h index f475aa8..a3cde69 100644 --- a/blockdev.h +++ b/blockdev.h @@ -12,6 +12,7 @@ #include "block.h" #include "qemu-queue.h" +#include "monitor.h" void blockdev_mark_auto_del(BlockDriverState *bs); void blockdev_auto_del(BlockDriverState *bs); @@ -66,5 +67,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_block_stream(Monitor *mon, const QDict *params, QObject **ret_data); +int do_block_job_cancel(Monitor *mon, const QDict *params, + MonitorCompletion cb, void *opaque); #endif diff --git a/hmp-commands.hx b/hmp-commands.hx index 9bf1025..613eb76 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -52,6 +52,21 @@ Copy data from a backing file into a block device. ETEXI { + .name = "block_job_cancel", + .args_type = "device:B", + .params = "device", + .help = "Stop an active block streaming operation", + .mhandler.cmd_async = do_block_job_cancel, + .flags = MONITOR_CMD_ASYNC, + }, + +STEXI +@item block_job_cancel +@findex block_job_cancel +Stop an active block streaming operation. +ETEXI + + { .name = "q|quit", .args_type = "", .params = "", diff --git a/qmp-commands.hx b/qmp-commands.hx index 80402c7..5ab15a4 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1010,6 +1010,47 @@ Examples: EQMP { + .name = "block_job_cancel", + .args_type = "device:B", + .params = "device", + .help = "Stop an active streaming operation on a block device", + .mhandler.cmd_async = do_block_job_cancel, + .flags = MONITOR_CMD_ASYNC, + }, + +SQMP + +block_job_cancel +---------------- + +Stop an active block streaming operation. + +This command returns once the active block streaming operation has been +stopped. It is an error to call this command if no operation is in progress. + +The image file retains its backing file unless the streaming operation happens +to complete just as it is being cancelled. + +A new block streaming operation can be started at a later time to finish +copying all data from the backing file. + +Arguments: + +- device: device name (json-string) + +Errors: + +DeviceNotActive: streaming is not active on this device +DeviceInUse: cancellation already in progress + +Examples: + +-> { "execute": "block_job_cancel", "arguments": { "device": "virtio0" } } +<- { "return": {} } + +EQMP + + { .name = "qmp_capabilities", .args_type = "", .params = "",