From patchwork Fri Nov 22 05:24:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fam Zheng X-Patchwork-Id: 293330 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 247BF2C00B6 for ; Fri, 22 Nov 2013 16:26:01 +1100 (EST) Received: from localhost ([::1]:36726 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VjjFe-0007dU-F4 for incoming@patchwork.ozlabs.org; Fri, 22 Nov 2013 00:25:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57083) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VjjEx-0007SL-9M for qemu-devel@nongnu.org; Fri, 22 Nov 2013 00:25:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VjjEq-0004aj-H8 for qemu-devel@nongnu.org; Fri, 22 Nov 2013 00:25:15 -0500 Received: from mx1.redhat.com ([209.132.183.28]:7632) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VjjEq-0004aN-9f for qemu-devel@nongnu.org; Fri, 22 Nov 2013 00:25:08 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rAM5P7wZ032151 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 22 Nov 2013 00:25:07 -0500 Received: from ad.nay.redhat.com ([10.66.6.190]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id rAM5OvCu010362; Fri, 22 Nov 2013 00:25:04 -0500 From: Fam Zheng To: qemu-devel@nongnu.org Date: Fri, 22 Nov 2013 13:24:49 +0800 Message-Id: <1385097894-1380-3-git-send-email-famz@redhat.com> In-Reply-To: <1385097894-1380-1-git-send-email-famz@redhat.com> References: <1385097894-1380-1-git-send-email-famz@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, hbrock@redhat.com, rjones@redhat.com, imain@redhat.com, stefanha@redhat.com, pbonzini@redhat.com Subject: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState 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 BlockDriverState.op_blockers is an array of list with BLOCK_OP_TYPE_MAX elements. Each list is a list of blockers of an operation type (BlockOpType), that marks this BDS is currently blocked for certain type of operation with reason errors stored in the list. The rule of usage is: * BDS user who wants to take an operation should check if there's any blocker of the type with bdrv_op_is_blocked(). * BDS user who wants to block certain types of operation, should call bdrv_op_block (or bdrv_op_block_all to block all types of operations, which is similar to bdrv_set_in_use of now). * A blocker is only referenced by op_blockers, so the lifecycle is managed by caller, and shouldn't be lost until unblock, so typically a caller does these: - Allocate a blocker with error_setg or similar, call bdrv_op_block() to block some operations. - Hold the blocker, do his job. - Unblock operations that it blocked, with the same reason pointer passed to bdrv_op_unblock(). - Release the blocker with error_free(). Signed-off-by: Fam Zheng --- block.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ include/block/block.h | 6 ++++++ include/block/block_int.h | 5 +++++ 3 files changed, 66 insertions(+) diff --git a/block.c b/block.c index 382ea71..2b18a43 100644 --- a/block.c +++ b/block.c @@ -4425,6 +4425,61 @@ void bdrv_unref(BlockDriverState *bs) } } +struct BdrvOpBlocker { + Error *reason; + QLIST_ENTRY(BdrvOpBlocker) list; +}; + +bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp) +{ + BdrvOpBlocker *blocker; + assert(op >=0 && op < BLOCK_OP_TYPE_MAX); + if (!QLIST_EMPTY(&bs->op_blockers[op])) { + blocker = QLIST_FIRST(&bs->op_blockers[op]); + *errp = error_copy(blocker->reason); + return true; + } + return false; +} + +void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason) +{ + BdrvOpBlocker *blocker; + assert(op >=0 && op < BLOCK_OP_TYPE_MAX); + + blocker = g_malloc0(sizeof(BdrvOpBlocker)); + blocker->reason = reason; + QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list); +} + +void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason) +{ + BdrvOpBlocker *blocker, *next; + assert(op >=0 && op < BLOCK_OP_TYPE_MAX); + QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) { + if (blocker->reason == reason) { + QLIST_REMOVE(blocker, list); + g_free(blocker); + } + } +} + +void bdrv_op_block_all(BlockDriverState *bs, Error *reason) +{ + int i; + for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { + bdrv_op_block(bs, i, reason); + } +} + +void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason) +{ + int i; + for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { + bdrv_op_unblock(bs, i, reason); + } +} + void bdrv_set_in_use(BlockDriverState *bs, int in_use) { assert(bs->in_use != in_use); diff --git a/include/block/block.h b/include/block/block.h index 3560deb..693d305 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -403,6 +403,12 @@ void bdrv_unref(BlockDriverState *bs); void bdrv_set_in_use(BlockDriverState *bs, int in_use); int bdrv_in_use(BlockDriverState *bs); +bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp); +void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason); +void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason); +void bdrv_op_block_all(BlockDriverState *bs, Error *reason); +void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason); + #ifdef CONFIG_LINUX_AIO int raw_get_aio_fd(BlockDriverState *bs); #else diff --git a/include/block/block_int.h b/include/block/block_int.h index 1666066..d8cef85 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -230,6 +230,8 @@ struct BlockDriver { QLIST_ENTRY(BlockDriver) list; }; +typedef struct BdrvOpBlocker BdrvOpBlocker; + /* * Note: the function bdrv_append() copies and swaps contents of * BlockDriverStates, so if you add new fields to this struct, please @@ -308,6 +310,9 @@ struct BlockDriverState { QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; + /* operation blockers */ + QLIST_HEAD(, BdrvOpBlocker) op_blockers[BLOCK_OP_TYPE_MAX]; + /* long-running background operation */ BlockJob *job;