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: [Qemu-devel] [PATCH v6 27/42] commit: Deal with filters
Date: Fri, 9 Aug 2019 18:13:52 +0200 [thread overview]
Message-ID: <20190809161407.11920-28-mreitz@redhat.com> (raw)
In-Reply-To: <20190809161407.11920-1-mreitz@redhat.com>
This includes some permission limiting (for example, we only need to
take the RESIZE permission if the base is smaller than the top).
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/block-backend.c | 16 +++++---
block/commit.c | 96 +++++++++++++++++++++++++++++++------------
blockdev.c | 6 ++-
3 files changed, 85 insertions(+), 33 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index c13c5c83b0..0bc592d023 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2180,11 +2180,17 @@ int blk_commit_all(void)
AioContext *aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
- if (blk_is_inserted(blk) && blk->root->bs->backing) {
- int ret = bdrv_commit(blk->root->bs);
- if (ret < 0) {
- aio_context_release(aio_context);
- return ret;
+ if (blk_is_inserted(blk)) {
+ BlockDriverState *non_filter;
+
+ /* Legacy function, so skip implicit filters */
+ non_filter = bdrv_skip_implicit_filters(blk->root->bs);
+ if (bdrv_filtered_cow_child(non_filter)) {
+ int ret = bdrv_commit(non_filter);
+ if (ret < 0) {
+ aio_context_release(aio_context);
+ return ret;
+ }
}
}
aio_context_release(aio_context);
diff --git a/block/commit.c b/block/commit.c
index 5a7672c7c7..40d1c8eeac 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -37,6 +37,7 @@ typedef struct CommitBlockJob {
BlockBackend *top;
BlockBackend *base;
BlockDriverState *base_bs;
+ BlockDriverState *above_base;
BlockdevOnError on_error;
bool base_read_only;
bool chain_frozen;
@@ -110,7 +111,7 @@ static void commit_abort(Job *job)
* XXX Can (or should) we somehow keep 'consistent read' blocked even
* after the failed/cancelled commit job is gone? If we already wrote
* something to base, the intermediate images aren't valid any more. */
- bdrv_replace_node(s->commit_top_bs, backing_bs(s->commit_top_bs),
+ bdrv_replace_node(s->commit_top_bs, s->commit_top_bs->backing->bs,
&error_abort);
bdrv_unref(s->commit_top_bs);
@@ -174,7 +175,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
break;
}
/* Copy if allocated above the base */
- ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false,
+ ret = bdrv_is_allocated_above(blk_bs(s->top), s->above_base, true,
offset, COMMIT_BUFFER_SIZE, &n);
copy = (ret == 1);
trace_commit_one_iteration(s, offset, n, ret);
@@ -267,15 +268,35 @@ void commit_start(const char *job_id, BlockDriverState *bs,
CommitBlockJob *s;
BlockDriverState *iter;
BlockDriverState *commit_top_bs = NULL;
+ BlockDriverState *filtered_base;
Error *local_err = NULL;
+ int64_t base_size, top_size;
+ uint64_t perms, iter_shared_perms;
int ret;
assert(top != bs);
- if (top == base) {
+ if (bdrv_skip_rw_filters(top) == bdrv_skip_rw_filters(base)) {
error_setg(errp, "Invalid files for merge: top and base are the same");
return;
}
+ base_size = bdrv_getlength(base);
+ if (base_size < 0) {
+ error_setg_errno(errp, -base_size, "Could not inquire base image size");
+ return;
+ }
+
+ top_size = bdrv_getlength(top);
+ if (top_size < 0) {
+ error_setg_errno(errp, -top_size, "Could not inquire top image size");
+ return;
+ }
+
+ perms = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
+ if (base_size < top_size) {
+ perms |= BLK_PERM_RESIZE;
+ }
+
s = block_job_create(job_id, &commit_job_driver, NULL, bs, 0, BLK_PERM_ALL,
speed, creation_flags, NULL, NULL, errp);
if (!s) {
@@ -315,17 +336,43 @@ void commit_start(const char *job_id, BlockDriverState *bs,
s->commit_top_bs = commit_top_bs;
- /* Block all nodes between top and base, because they will
- * disappear from the chain after this operation. */
- assert(bdrv_chain_contains(top, base));
- for (iter = top; iter != base; iter = backing_bs(iter)) {
- /* XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves
- * at s->base (if writes are blocked for a node, they are also blocked
- * for its backing file). The other options would be a second filter
- * driver above s->base. */
+ /*
+ * Block all nodes between top and base, because they will
+ * disappear from the chain after this operation.
+ * Note that this assumes that the user is fine with removing all
+ * nodes (including R/W filters) between top and base. Assuring
+ * this is the responsibility of the interface (i.e. whoever calls
+ * commit_start()).
+ */
+ s->above_base = bdrv_find_overlay(top, base);
+ assert(s->above_base);
+
+ /*
+ * The topmost node with
+ * bdrv_skip_rw_filters(filtered_base) == bdrv_skip_rw_filters(base)
+ */
+ filtered_base = bdrv_filtered_cow_bs(s->above_base);
+ assert(bdrv_skip_rw_filters(filtered_base) == bdrv_skip_rw_filters(base));
+
+ /*
+ * XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves
+ * at s->base (if writes are blocked for a node, they are also blocked
+ * for its backing file). The other options would be a second filter
+ * driver above s->base.
+ */
+ iter_shared_perms = BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE;
+
+ for (iter = top; iter != base; iter = bdrv_filtered_bs(iter)) {
+ if (iter == filtered_base) {
+ /*
+ * From here on, all nodes are filters on the base. This
+ * allows us to share BLK_PERM_CONSISTENT_READ.
+ */
+ iter_shared_perms |= BLK_PERM_CONSISTENT_READ;
+ }
+
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE,
- errp);
+ iter_shared_perms, errp);
if (ret < 0) {
goto fail;
}
@@ -342,9 +389,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
}
s->base = blk_new(s->common.job.aio_context,
- BLK_PERM_CONSISTENT_READ
- | BLK_PERM_WRITE
- | BLK_PERM_RESIZE,
+ perms,
BLK_PERM_CONSISTENT_READ
| BLK_PERM_GRAPH_MOD
| BLK_PERM_WRITE_UNCHANGED);
@@ -412,19 +457,22 @@ int bdrv_commit(BlockDriverState *bs)
if (!drv)
return -ENOMEDIUM;
- if (!bs->backing) {
+ backing_file_bs = bdrv_filtered_cow_bs(bs);
+
+ if (!backing_file_bs) {
return -ENOTSUP;
}
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) ||
- bdrv_op_is_blocked(bs->backing->bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) {
+ bdrv_op_is_blocked(backing_file_bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL))
+ {
return -EBUSY;
}
- ro = bs->backing->bs->read_only;
+ ro = backing_file_bs->read_only;
if (ro) {
- if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) {
+ if (bdrv_reopen_set_read_only(backing_file_bs, false, NULL)) {
return -EACCES;
}
}
@@ -440,8 +488,6 @@ int bdrv_commit(BlockDriverState *bs)
}
/* Insert commit_top block node above backing, so we can write to it */
- backing_file_bs = backing_bs(bs);
-
commit_top_bs = bdrv_new_open_driver(&bdrv_commit_top, NULL, BDRV_O_RDWR,
&local_err);
if (commit_top_bs == NULL) {
@@ -526,15 +572,13 @@ ro_cleanup:
qemu_vfree(buf);
blk_unref(backing);
- if (backing_file_bs) {
- bdrv_set_backing_hd(bs, backing_file_bs, &error_abort);
- }
+ bdrv_set_backing_hd(bs, backing_file_bs, &error_abort);
bdrv_unref(commit_top_bs);
blk_unref(src);
if (ro) {
/* ignoring error return here */
- bdrv_reopen_set_read_only(bs->backing->bs, true, NULL);
+ bdrv_reopen_set_read_only(backing_file_bs, true, NULL);
}
return ret;
diff --git a/blockdev.c b/blockdev.c
index c6f79b4e0e..7bef41c0b0 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1094,7 +1094,7 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
return;
}
- bs = blk_bs(blk);
+ bs = bdrv_skip_implicit_filters(blk_bs(blk));
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
@@ -3454,7 +3454,9 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
assert(bdrv_get_aio_context(base_bs) == aio_context);
- for (iter = top_bs; iter != backing_bs(base_bs); iter = backing_bs(iter)) {
+ for (iter = top_bs; iter != bdrv_filtered_bs(base_bs);
+ iter = bdrv_filtered_bs(iter))
+ {
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_COMMIT_TARGET, errp)) {
goto out;
}
--
2.21.0
next prev parent reply other threads:[~2019-08-09 16:22 UTC|newest]
Thread overview: 136+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-09 16:13 [Qemu-devel] [PATCH v6 00/42] block: Deal with filters Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 01/42] block: Mark commit and mirror as filter drivers Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 02/42] copy-on-read: Support compressed writes Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 03/42] throttle: " Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 04/42] block: Add child access functions Max Reitz
2019-08-09 16:56 ` Eric Blake
2019-09-04 16:16 ` Kevin Wolf
2019-09-09 7:56 ` Max Reitz
2019-09-09 9:36 ` Kevin Wolf
2019-09-09 14:04 ` Max Reitz
2019-09-09 16:13 ` Kevin Wolf
2019-09-10 9:14 ` Max Reitz
2019-09-10 10:47 ` Kevin Wolf
2019-09-10 11:36 ` Max Reitz
2019-09-10 12:48 ` Kevin Wolf
2019-09-10 12:59 ` Max Reitz
2019-09-10 13:10 ` Kevin Wolf
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 05/42] block: Add chain helper functions Max Reitz
2019-08-09 17:01 ` Eric Blake
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 06/42] qcow2: Implement .bdrv_storage_child() Max Reitz
2019-08-09 17:07 ` Eric Blake
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 07/42] block: *filtered_cow_child() for *has_zero_init() Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 08/42] block: bdrv_set_backing_hd() is about bs->backing Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 09/42] block: Include filters when freezing backing chain Max Reitz
2019-08-10 13:32 ` Vladimir Sementsov-Ogievskiy
2019-08-12 12:56 ` Max Reitz
2019-09-05 13:05 ` Kevin Wolf
2019-09-09 8:02 ` Max Reitz
2019-09-09 9:40 ` Kevin Wolf
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 10/42] block: Drop bdrv_is_encrypted() Max Reitz
2019-08-10 13:42 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 11/42] block: Add bdrv_supports_compressed_writes() Max Reitz
2019-09-05 13:11 ` Kevin Wolf
2019-09-09 8:09 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 12/42] block: Use bdrv_filtered_rw* where obvious Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 13/42] block: Use CAFs in block status functions Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 14/42] block: Use CAFs when working with backing chains Max Reitz
2019-08-10 15:19 ` Vladimir Sementsov-Ogievskiy
2019-09-05 14:05 ` Kevin Wolf
2019-09-09 8:25 ` Max Reitz
2019-09-09 9:55 ` Kevin Wolf
2019-09-09 14:08 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 15/42] block: Re-evaluate backing file handling in reopen Max Reitz
2019-08-10 16:05 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 16/42] block: Flush all children in generic code Max Reitz
2019-08-10 15:36 ` Vladimir Sementsov-Ogievskiy
2019-08-12 12:58 ` Max Reitz
2019-09-05 16:24 ` Kevin Wolf
2019-09-09 8:31 ` Max Reitz
2019-09-09 10:01 ` Kevin Wolf
2019-09-09 14:15 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 17/42] block: Use CAFs in bdrv_refresh_limits() Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 18/42] block: Use CAFs in bdrv_refresh_filename() Max Reitz
2019-08-10 16:22 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 19/42] block: Use CAF in bdrv_co_rw_vmstate() Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 20/42] block/snapshot: Fix fallback Max Reitz
2019-08-10 16:34 ` Vladimir Sementsov-Ogievskiy
2019-08-12 13:06 ` Max Reitz
2019-09-10 11:56 ` Kevin Wolf
2019-09-10 12:04 ` Max Reitz
2019-09-10 12:49 ` Kevin Wolf
2019-09-10 13:06 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 21/42] block: Use CAFs for debug breakpoints Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 22/42] block: Fix bdrv_get_allocated_file_size's fallback Max Reitz
2019-08-10 16:41 ` Vladimir Sementsov-Ogievskiy
2019-08-12 13:09 ` Max Reitz
2019-08-12 17:14 ` Vladimir Sementsov-Ogievskiy
2019-08-12 19:15 ` Max Reitz
2019-09-10 14:52 ` Kevin Wolf
2019-09-11 6:20 ` Max Reitz
2019-09-11 6:55 ` Kevin Wolf
2019-09-11 7:37 ` Max Reitz
2019-09-11 8:27 ` Kevin Wolf
2019-09-11 10:00 ` Max Reitz
2019-09-11 10:31 ` Kevin Wolf
2019-09-11 11:00 ` Max Reitz
2019-09-12 10:34 ` Kevin Wolf
2019-11-14 13:11 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 23/42] blockdev: Use CAF in external_snapshot_prepare() Max Reitz
2019-09-10 15:02 ` Kevin Wolf
2019-09-11 6:21 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 24/42] block: Use child access functions for QAPI queries Max Reitz
2019-08-10 16:57 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 25/42] mirror: Deal with filters Max Reitz
2019-08-12 11:09 ` Vladimir Sementsov-Ogievskiy
2019-08-12 13:26 ` Max Reitz
2019-08-14 15:17 ` Vladimir Sementsov-Ogievskiy
2019-08-31 9:57 ` Vladimir Sementsov-Ogievskiy
2019-09-02 14:35 ` Max Reitz
2019-09-03 8:32 ` Vladimir Sementsov-Ogievskiy
2019-09-09 7:41 ` Max Reitz
2019-09-13 12:55 ` Kevin Wolf
2019-09-16 10:26 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 26/42] backup: " Max Reitz
2019-08-09 16:13 ` Max Reitz [this message]
2019-08-31 10:44 ` [Qemu-devel] [PATCH v6 27/42] commit: " Vladimir Sementsov-Ogievskiy
2019-09-02 14:55 ` Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 28/42] stream: " Max Reitz
2019-08-12 11:55 ` Vladimir Sementsov-Ogievskiy
2019-09-13 14:16 ` Kevin Wolf
2019-09-16 9:52 ` Max Reitz
2019-09-16 14:47 ` Kevin Wolf
2019-12-11 12:52 ` Max Reitz
2019-12-11 15:52 ` Kevin Wolf
2019-12-11 16:12 ` Max Reitz
2019-12-11 16:35 ` Kevin Wolf
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 29/42] nbd: Use CAF when looking for dirty bitmap Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 30/42] qemu-img: Use child access functions Max Reitz
2019-08-12 12:14 ` Vladimir Sementsov-Ogievskiy
2019-08-12 13:28 ` Max Reitz
2019-08-14 16:04 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 31/42] block: Drop backing_bs() Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 32/42] block: Make bdrv_get_cumulative_perm() public Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 33/42] blockdev: Fix active commit choice Max Reitz
2019-08-09 16:13 ` [Qemu-devel] [PATCH v6 34/42] block: Inline bdrv_co_block_status_from_*() Max Reitz
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 35/42] block: Fix check_to_replace_node() Max Reitz
2019-08-15 15:21 ` Vladimir Sementsov-Ogievskiy
2019-08-15 17:01 ` Max Reitz
2019-08-16 11:01 ` Vladimir Sementsov-Ogievskiy
2019-08-16 13:30 ` Max Reitz
2019-08-16 14:24 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 36/42] iotests: Add tests for mirror @replaces loops Max Reitz
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 37/42] block: Leave BDS.backing_file constant Max Reitz
2019-08-16 16:16 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 38/42] iotests: Let complete_and_wait() work with commit Max Reitz
2019-08-23 5:59 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 39/42] iotests: Add filter commit test cases Max Reitz
2019-08-31 11:41 ` Vladimir Sementsov-Ogievskiy
2019-09-02 15:06 ` Max Reitz
2019-08-31 12:35 ` Vladimir Sementsov-Ogievskiy
2019-09-02 15:09 ` Max Reitz
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 40/42] iotests: Add filter mirror " Max Reitz
2019-08-31 12:35 ` Vladimir Sementsov-Ogievskiy
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 41/42] iotests: Add test for commit in sub directory Max Reitz
2019-08-09 16:14 ` [Qemu-devel] [PATCH v6 42/42] iotests: Test committing to overridden backing Max Reitz
2019-09-03 9:18 ` Vladimir Sementsov-Ogievskiy
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=20190809161407.11920-28-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).