From: "Benoît Canet" <benoit.canet@irqsave.net>
To: Fam Zheng <famz@redhat.com>
Cc: kwolf@redhat.com, rjones@redhat.com, armbru@redhat.com,
qemu-devel@nongnu.org, imain@redhat.com, stefanha@redhat.com,
pbonzini@redhat.com
Subject: Re: [Qemu-devel] [PATCH v13 02/14] block: Introduce op_blockers to BlockDriverState
Date: Thu, 13 Feb 2014 13:24:00 +0100 [thread overview]
Message-ID: <20140213122400.GA4547@irqsave.net> (raw)
In-Reply-To: <1390972061-26560-3-git-send-email-famz@redhat.com>
The Wednesday 29 Jan 2014 à 13:07:29 (+0800), Fam Zheng wrote :
> BlockDriverState.op_blockers is an array of lists with BLOCK_OP_TYPE_MAX
> elements. Each list is a list of blockers of an operation type
> (BlockOpType), that marks this BDS as currently blocked for a 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 the existing bdrv_set_in_use()).
>
> * 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 <famz@redhat.com>
> ---
> block.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++
> include/block/block.h | 7 +++++
> include/block/block_int.h | 5 ++++
> 3 files changed, 83 insertions(+)
>
> diff --git a/block.c b/block.c
> index cb21a5f..967de98 100644
> --- a/block.c
> +++ b/block.c
> @@ -1838,6 +1838,8 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
> * We do want to swap name but don't want to swap linked list entries
> */
> bs_dest->node_list = bs_src->node_list;
> + memcpy(bs_dest->op_blockers, bs_src->op_blockers,
> + sizeof(bs_dest->op_blockers));
> }
>
> /*
> @@ -5119,6 +5121,75 @@ 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((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
> + if (!QLIST_EMPTY(&bs->op_blockers[op])) {
> + blocker = QLIST_FIRST(&bs->op_blockers[op]);
> + if (errp) {
> + *errp = error_copy(blocker->reason);
When an operation is blocked the first reason found is returned as **errp.
I think that this could lead to some randomization of the error messages
depending on the bdrv_op_block call order.
> + }
> + return true;
> + }
> + return false;
> +}
> +
> +void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason)
> +{
> + BdrvOpBlocker *blocker;
> + assert((int) 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((int) 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);
> + }
> +}
> +
> +bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
> +{
> + int i;
> +
> + for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
> + if (!QLIST_EMPTY(&bs->op_blockers[i])) {
> + return false;
> + }
> + }
> + return true;
> +}
> +
> 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 9626650..f4a70c9 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -473,6 +473,13 @@ 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);
> +bool bdrv_op_blocker_is_empty(BlockDriverState *bs);
> +
> #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 0bcf1c9..4e558d0 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -270,6 +270,8 @@ typedef struct BlockLimits {
> size_t opt_mem_alignment;
> } BlockLimits;
>
> +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
> @@ -361,6 +363,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.5.3
>
>
next prev parent reply other threads:[~2014-02-13 12:24 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-29 5:07 [Qemu-devel] [PATCH v13 00/14] Drop in_use from BlockDriverState and enable point-in-time snapshot exporting over NBD Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 01/14] block: Add BlockOpType enum Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 02/14] block: Introduce op_blockers to BlockDriverState Fam Zheng
2014-02-13 12:24 ` Benoît Canet [this message]
2014-02-17 13:30 ` Fam Zheng
2014-02-13 12:37 ` Benoît Canet
2014-02-17 13:30 ` Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 03/14] block: Replace in_use with operation blocker Fam Zheng
2014-02-13 12:34 ` Benoît Canet
2014-02-17 13:21 ` Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 04/14] block: Move op_blocker check from block_job_create to its caller Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 05/14] block: Add bdrv_set_backing_hd() Fam Zheng
2014-02-13 12:49 ` Benoît Canet
2014-02-17 13:31 ` Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 06/14] block: Add backing_blocker in BlockDriverState Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 07/14] block: Parse "backing" option to reference existing BDS Fam Zheng
2014-02-13 13:17 ` Benoît Canet
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 08/14] block: Support dropping active in bdrv_drop_intermediate Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 09/14] stream: Use bdrv_drop_intermediate and drop close_unused_images Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 10/14] qmp: Add command 'blockdev-backup' Fam Zheng
2014-02-13 13:48 ` Benoît Canet
2014-02-17 13:32 ` Fam Zheng
2014-02-17 14:23 ` Benoît Canet
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 11/14] block: Allow backup on referenced named BlockDriverState Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 12/14] block: Add blockdev-backup to transaction Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 13/14] qemu-iotests: Test blockdev-backup in 055 Fam Zheng
2014-01-29 5:07 ` [Qemu-devel] [PATCH v13 14/14] qemu-iotests: Image fleecing test case 081 Fam Zheng
2014-02-01 3:00 ` [Qemu-devel] [PATCH v13 00/14] Drop in_use from BlockDriverState and enable point-in-time snapshot exporting over NBD Ian Main
2014-02-01 15:21 ` Fam Zheng
2014-02-02 1:13 ` Ian Main
2014-02-12 17:22 ` Ian Main
2014-02-12 18:27 ` Richard W.M. Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140213122400.GA4547@irqsave.net \
--to=benoit.canet@irqsave.net \
--cc=armbru@redhat.com \
--cc=famz@redhat.com \
--cc=imain@redhat.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rjones@redhat.com \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.