From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:43842) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RjANq-0000F1-De for qemu-devel@nongnu.org; Fri, 06 Jan 2012 09:03:06 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RjANo-0001QY-2H for qemu-devel@nongnu.org; Fri, 06 Jan 2012 09:03:02 -0500 Received: from e06smtp10.uk.ibm.com ([195.75.94.106]:34877) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RjANn-0001Pv-Lz for qemu-devel@nongnu.org; Fri, 06 Jan 2012 09:02:59 -0500 Received: from /spool/local by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 6 Jan 2012 14:02:58 -0000 Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q06E2qJE1921038 for ; Fri, 6 Jan 2012 14:02:52 GMT Received: from d06av07.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q06E2qSI013568 for ; Fri, 6 Jan 2012 07:02:52 -0700 From: Stefan Hajnoczi Date: Fri, 6 Jan 2012 14:01:36 +0000 Message-Id: <1325858501-25741-11-git-send-email-stefanha@linux.vnet.ibm.com> In-Reply-To: <1325858501-25741-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1325858501-25741-1-git-send-email-stefanha@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH v4 10/15] blockdev: make image streaming safe across hotplug List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Marcelo Tosatti , Stefan Hajnoczi , Luiz Capitulino Unplugging a storage interface like virtio-blk causes the host block device to be deleted too. Long-running operations like block migration must take a DriveInfo reference to prevent the BlockDriverState from being freed. For image streaming we can do the same thing. Note that it is not possible to acquire/release the drive reference in block.c where the block job functions live because drive_get_ref()/drive_put_ref() are blockdev.c functions. Calling them from block.c would be a layering violation - tools like qemu-img don't even link against blockdev.c. Signed-off-by: Stefan Hajnoczi --- blockdev.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 4549c9e..45a6ba6 100644 --- a/blockdev.c +++ b/blockdev.c @@ -202,6 +202,37 @@ void drive_get_ref(DriveInfo *dinfo) dinfo->refcount++; } +typedef struct { + QEMUBH *bh; + DriveInfo *dinfo; +} DrivePutRefBH; + +static void drive_put_ref_bh(void *opaque) +{ + DrivePutRefBH *s = opaque; + + drive_put_ref(s->dinfo); + qemu_bh_delete(s->bh); + g_free(s); +} + +/* + * Release a drive reference in a BH + * + * It is not possible to use drive_put_ref() from a callback function when the + * callers still need the drive. In such cases we schedule a BH to release the + * reference. + */ +static void drive_put_ref_bh_schedule(DriveInfo *dinfo) +{ + DrivePutRefBH *s; + + s = g_new(DrivePutRefBH, 1); + s->bh = qemu_bh_new(drive_put_ref_bh, s); + s->dinfo = dinfo; + qemu_bh_schedule(s->bh); +} + static int parse_block_error_action(const char *buf, int is_read) { if (!strcmp(buf, "ignore")) { @@ -917,6 +948,8 @@ static void block_stream_cb(void *opaque, int ret) monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj); } qobject_decref(obj); + + drive_put_ref_bh_schedule(drive_get_by_blockdev(bs)); } void qmp_block_stream(const char *device, bool has_base, @@ -949,6 +982,11 @@ void qmp_block_stream(const char *device, bool has_base, } } + /* Grab a reference so hotplug does not delete the BlockDriverState from + * underneath us. + */ + drive_get_ref(drive_get_by_blockdev(bs)); + trace_qmp_block_stream(bs, bs->job); } -- 1.7.7.3