[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverS
From: |
Fam Zheng |
Subject: |
[Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState |
Date: |
Fri, 22 Nov 2013 13:24:49 +0800 |
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 <address@hidden>
---
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;
--
1.8.4.2
- [Qemu-devel] [PATCH v4 0/7] Drop in_use from BlockDriverState and enable point-in-time snapshot exporting over NBD, Fam Zheng, 2013/11/22
- [Qemu-devel] [PATCH v4 1/7] qapi: Add BlockOperationType enum, Fam Zheng, 2013/11/22
- [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState,
Fam Zheng <=
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Stefan Hajnoczi, 2013/11/22
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Kevin Wolf, 2013/11/25
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Kevin Wolf, 2013/11/25
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Paolo Bonzini, 2013/11/25
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Fam Zheng, 2013/11/25
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Paolo Bonzini, 2013/11/26
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Fam Zheng, 2013/11/26
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Paolo Bonzini, 2013/11/26
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Fam Zheng, 2013/11/26
- Re: [Qemu-devel] [PATCH v4 2/7] block: Introduce op_blockers to BlockDriverState, Paolo Bonzini, 2013/11/26