aboutsummaryrefslogtreecommitdiff
path: root/block/file-posix.c
diff options
context:
space:
mode:
authorVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>2021-04-28 18:17:58 +0300
committerKevin Wolf <kwolf@redhat.com>2021-04-30 12:27:48 +0200
commit72373e40fbc7e4218061a8211384db362d3e7348 (patch)
tree4ce1e028249dff7b973c2e3b2c06e1e40af7bcbb /block/file-posix.c
parenta2aabf88958119ec7d3022287eff6bcc924c90a8 (diff)
block: bdrv_reopen_multiple: refresh permissions on updated graph
Move bdrv_reopen_multiple to new paradigm of permission update: first update graph relations, then do refresh the permissions. We have to modify reopen process in file-posix driver: with new scheme we don't have prepared permissions in raw_reopen_prepare(), so we should reconfigure fd in raw_check_perm(). Still this seems more native and simple anyway. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <20210428151804.439460-31-vsementsov@virtuozzo.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/file-posix.c')
-rw-r--r--block/file-posix.c91
1 files changed, 29 insertions, 62 deletions
diff --git a/block/file-posix.c b/block/file-posix.c
index 20e14f8e96..10b71d9a13 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -175,7 +175,6 @@ typedef struct BDRVRawState {
} BDRVRawState;
typedef struct BDRVRawReopenState {
- int fd;
int open_flags;
bool drop_cache;
bool check_cache_dropped;
@@ -1075,7 +1074,6 @@ static int raw_reopen_prepare(BDRVReopenState *state,
BDRVRawReopenState *rs;
QemuOpts *opts;
int ret;
- Error *local_err = NULL;
assert(state != NULL);
assert(state->bs != NULL);
@@ -1101,32 +1099,18 @@ static int raw_reopen_prepare(BDRVReopenState *state,
* bdrv_reopen_prepare() will detect changes and complain. */
qemu_opts_to_qdict(opts, state->options);
- rs->fd = raw_reconfigure_getfd(state->bs, state->flags, &rs->open_flags,
- state->perm, true, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- ret = -1;
- goto out;
- }
-
- /* Fail already reopen_prepare() if we can't get a working O_DIRECT
- * alignment with the new fd. */
- if (rs->fd != -1) {
- raw_probe_alignment(state->bs, rs->fd, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- ret = -EINVAL;
- goto out_fd;
- }
- }
+ /*
+ * As part of reopen prepare we also want to create new fd by
+ * raw_reconfigure_getfd(). But it wants updated "perm", when in
+ * bdrv_reopen_multiple() .bdrv_reopen_prepare() callback called prior to
+ * permission update. Happily, permission update is always a part (a seprate
+ * stage) of bdrv_reopen_multiple() so we can rely on this fact and
+ * reconfigure fd in raw_check_perm().
+ */
s->reopen_state = state;
ret = 0;
-out_fd:
- if (ret < 0) {
- qemu_close(rs->fd);
- rs->fd = -1;
- }
+
out:
qemu_opts_del(opts);
return ret;
@@ -1140,10 +1124,6 @@ static void raw_reopen_commit(BDRVReopenState *state)
s->drop_cache = rs->drop_cache;
s->check_cache_dropped = rs->check_cache_dropped;
s->open_flags = rs->open_flags;
-
- qemu_close(s->fd);
- s->fd = rs->fd;
-
g_free(state->opaque);
state->opaque = NULL;
@@ -1162,10 +1142,6 @@ static void raw_reopen_abort(BDRVReopenState *state)
return;
}
- if (rs->fd >= 0) {
- qemu_close(rs->fd);
- rs->fd = -1;
- }
g_free(state->opaque);
state->opaque = NULL;
@@ -3073,39 +3049,30 @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
Error **errp)
{
BDRVRawState *s = bs->opaque;
- BDRVRawReopenState *rs = NULL;
+ int input_flags = s->reopen_state ? s->reopen_state->flags : bs->open_flags;
int open_flags;
int ret;
- if (s->perm_change_fd) {
+ /* We may need a new fd if auto-read-only switches the mode */
+ ret = raw_reconfigure_getfd(bs, input_flags, &open_flags, perm,
+ false, errp);
+ if (ret < 0) {
+ return ret;
+ } else if (ret != s->fd) {
+ Error *local_err = NULL;
+
/*
- * In the context of reopen, this function may be called several times
- * (directly and recursively while change permissions of the parent).
- * This is even true for children that don't inherit from the original
- * reopen node, so s->reopen_state is not set.
- *
- * Ignore all but the first call.
+ * Fail already check_perm() if we can't get a working O_DIRECT
+ * alignment with the new fd.
*/
- return 0;
- }
-
- if (s->reopen_state) {
- /* We already have a new file descriptor to set permissions for */
- assert(s->reopen_state->perm == perm);
- assert(s->reopen_state->shared_perm == shared);
- rs = s->reopen_state->opaque;
- s->perm_change_fd = rs->fd;
- s->perm_change_flags = rs->open_flags;
- } else {
- /* We may need a new fd if auto-read-only switches the mode */
- ret = raw_reconfigure_getfd(bs, bs->open_flags, &open_flags, perm,
- false, errp);
- if (ret < 0) {
- return ret;
- } else if (ret != s->fd) {
- s->perm_change_fd = ret;
- s->perm_change_flags = open_flags;
+ raw_probe_alignment(bs, ret, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return -EINVAL;
}
+
+ s->perm_change_fd = ret;
+ s->perm_change_flags = open_flags;
}
/* Prepare permissions on old fd to avoid conflicts between old and new,
@@ -3127,7 +3094,7 @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
return 0;
fail:
- if (s->perm_change_fd && !s->reopen_state) {
+ if (s->perm_change_fd) {
qemu_close(s->perm_change_fd);
}
s->perm_change_fd = 0;
@@ -3158,7 +3125,7 @@ static void raw_abort_perm_update(BlockDriverState *bs)
/* For reopen, .bdrv_reopen_abort is called afterwards and will close
* the file descriptor. */
- if (s->perm_change_fd && !s->reopen_state) {
+ if (s->perm_change_fd) {
qemu_close(s->perm_change_fd);
}
s->perm_change_fd = 0;