From: Max Reitz <mreitz@redhat.com>
To: qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
qemu-devel@nongnu.org, Max Reitz <mreitz@redhat.com>
Subject: [PATCH for-5.0 v4 3/5] blkdebug: Allow taking/unsharing permissions
Date: Fri, 8 Nov 2019 13:34:53 +0100 [thread overview]
Message-ID: <20191108123455.39445-4-mreitz@redhat.com> (raw)
In-Reply-To: <20191108123455.39445-1-mreitz@redhat.com>
Sometimes it is useful to be able to add a node to the block graph that
takes or unshare a certain set of permissions for debugging purposes.
This patch adds this capability to blkdebug.
(Note that you cannot make blkdebug release or share permissions that it
needs to take or cannot share, because this might result in assertion
failures in the block layer. But if the blkdebug node has no parents,
it will not take any permissions and share everything by default, so you
can then freely choose what permissions to take and share.)
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/blkdebug.c | 93 +++++++++++++++++++++++++++++++++++++++++++-
qapi/block-core.json | 14 ++++++-
2 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 5ae96c52b0..af44aa973f 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -28,10 +28,14 @@
#include "qemu/cutils.h"
#include "qemu/config-file.h"
#include "block/block_int.h"
+#include "block/qdict.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qapi/qapi-visit-block-core.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
+#include "qapi/qobject-input-visitor.h"
#include "sysemu/qtest.h"
typedef struct BDRVBlkdebugState {
@@ -44,6 +48,9 @@ typedef struct BDRVBlkdebugState {
uint64_t opt_discard;
uint64_t max_discard;
+ uint64_t take_child_perms;
+ uint64_t unshare_child_perms;
+
/* For blkdebug_refresh_filename() */
char *config_file;
@@ -344,6 +351,69 @@ static void blkdebug_parse_filename(const char *filename, QDict *options,
qdict_put_str(options, "x-image", filename);
}
+static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options,
+ const char *prefix, Error **errp)
+{
+ int ret = 0;
+ QDict *subqdict = NULL;
+ QObject *crumpled_subqdict = NULL;
+ Visitor *v = NULL;
+ BlockPermissionList *perm_list = NULL, *element;
+ Error *local_err = NULL;
+
+ *dest = 0;
+
+ qdict_extract_subqdict(options, &subqdict, prefix);
+ if (!qdict_size(subqdict)) {
+ goto out;
+ }
+
+ crumpled_subqdict = qdict_crumple(subqdict, errp);
+ if (!crumpled_subqdict) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ v = qobject_input_visitor_new(crumpled_subqdict);
+ visit_type_BlockPermissionList(v, NULL, &perm_list, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (element = perm_list; element; element = element->next) {
+ *dest |= bdrv_qapi_perm_to_blk_perm(element->value);
+ }
+
+out:
+ qapi_free_BlockPermissionList(perm_list);
+ visit_free(v);
+ qobject_unref(subqdict);
+ qobject_unref(crumpled_subqdict);
+ return ret;
+}
+
+static int blkdebug_parse_perms(BDRVBlkdebugState *s, QDict *options,
+ Error **errp)
+{
+ int ret;
+
+ ret = blkdebug_parse_perm_list(&s->take_child_perms, options,
+ "take-child-perms.", errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = blkdebug_parse_perm_list(&s->unshare_child_perms, options,
+ "unshare-child-perms.", errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
static QemuOptsList runtime_opts = {
.name = "blkdebug",
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
@@ -419,6 +489,12 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
/* Set initial state */
s->state = 1;
+ /* Parse permissions modifiers before opening the image file */
+ ret = blkdebug_parse_perms(s, options, errp);
+ if (ret < 0) {
+ goto out;
+ }
+
/* Open the image file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
bs, &child_file, false, &local_err);
@@ -916,6 +992,21 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
return 0;
}
+static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole *role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
+ nperm, nshared);
+
+ *nperm |= s->take_child_perms;
+ *nshared &= ~s->unshare_child_perms;
+}
+
static const char *const blkdebug_strong_runtime_opts[] = {
"config",
"inject-error.",
@@ -940,7 +1031,7 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_file_open = blkdebug_open,
.bdrv_close = blkdebug_close,
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = blkdebug_child_perm,
.bdrv_getlength = blkdebug_getlength,
.bdrv_refresh_filename = blkdebug_refresh_filename,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index aa97ee2641..46f3491878 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3450,6 +3450,16 @@
#
# @set-state: array of state-change descriptions
#
+# @take-child-perms: Permissions to take on @image in addition to what
+# is necessary anyway (which depends on how the
+# blkdebug node is used). Defaults to none.
+# (since 5.0)
+#
+# @unshare-child-perms: Permissions not to share on @image in addition
+# to what cannot be shared anyway (which depends
+# on how the blkdebug node is used). Defaults
+# to none. (since 5.0)
+#
# Since: 2.9
##
{ 'struct': 'BlockdevOptionsBlkdebug',
@@ -3459,7 +3469,9 @@
'*opt-write-zero': 'int32', '*max-write-zero': 'int32',
'*opt-discard': 'int32', '*max-discard': 'int32',
'*inject-error': ['BlkdebugInjectErrorOptions'],
- '*set-state': ['BlkdebugSetStateOptions'] } }
+ '*set-state': ['BlkdebugSetStateOptions'],
+ '*take-child-perms': ['BlockPermission'],
+ '*unshare-child-perms': ['BlockPermission'] } }
##
# @BlockdevOptionsBlklogwrites:
--
2.23.0
next prev parent reply other threads:[~2019-11-08 12:38 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-08 12:34 [PATCH for-5.0 v4 0/5] iotests: Test failing mirror complete Max Reitz
2019-11-08 12:34 ` [PATCH for-5.0 v4 1/5] block: Add bdrv_qapi_perm_to_blk_perm() Max Reitz
2019-11-08 14:05 ` Vladimir Sementsov-Ogievskiy
2019-11-08 12:34 ` [PATCH for-5.0 v4 2/5] block: Use bdrv_qapi_perm_to_blk_perm() Max Reitz
2019-11-08 14:11 ` Vladimir Sementsov-Ogievskiy
2019-11-08 12:34 ` Max Reitz [this message]
2019-11-08 15:19 ` [PATCH for-5.0 v4 3/5] blkdebug: Allow taking/unsharing permissions Vladimir Sementsov-Ogievskiy
2019-11-08 12:34 ` [PATCH for-5.0 v4 4/5] iotests: Add @error to wait_until_completed Max Reitz
2019-11-08 12:34 ` [PATCH for-5.0 v4 5/5] iotests: Add test for failing mirror complete Max Reitz
2019-11-26 8:27 ` [PATCH for-5.0 v4 0/5] iotests: Test " Max Reitz
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=20191108123455.39445-4-mreitz@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).