[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 07/15] commit: Deal with filters when blocking intermediate no
From: |
Andrey Shinkevich |
Subject: |
[PATCH v4 07/15] commit: Deal with filters when blocking intermediate nodes |
Date: |
Tue, 12 May 2020 19:50:37 +0300 |
From: Max Reitz <address@hidden>
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 <address@hidden>
Signed-off-by: Andrey Shinkevich <address@hidden>
---
block/commit.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 60 insertions(+), 15 deletions(-)
diff --git a/block/commit.c b/block/commit.c
index e1f45a4..4df145d 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;
@@ -153,7 +154,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);
@@ -253,15 +254,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) {
@@ -301,17 +322,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;
}
@@ -328,9 +375,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);
--
1.8.3.1
- [PATCH v4 00/15] Apply COR-filter to the block-stream permanently, Andrey Shinkevich, 2020/05/12
- [PATCH v4 12/15] copy-on-read: add filter append/drop functions, Andrey Shinkevich, 2020/05/12
- [PATCH v4 14/15] iotests: prepare 245 for using filter in block-stream, Andrey Shinkevich, 2020/05/12
- [PATCH v4 10/15] copy-on-read: Support change filename functions, Andrey Shinkevich, 2020/05/12
- [PATCH v4 11/15] copy-on-read: Support preadv/pwritev_part functions, Andrey Shinkevich, 2020/05/12
- [PATCH v4 06/15] block: Use CAFs in block status functions, Andrey Shinkevich, 2020/05/12
- [PATCH v4 13/15] qapi: add filter-node-name to block-stream, Andrey Shinkevich, 2020/05/12
- [PATCH v4 05/15] block: Include filters when freezing backing chain, Andrey Shinkevich, 2020/05/12
- [PATCH v4 07/15] commit: Deal with filters when blocking intermediate nodes,
Andrey Shinkevich <=
- [PATCH v4 15/15] block: apply COR-filter to block-stream jobs, Andrey Shinkevich, 2020/05/12
- [PATCH v4 01/15] block: Mark commit and mirror as filter drivers, Andrey Shinkevich, 2020/05/12
- [PATCH v4 02/15] copy-on-read: Support compressed writes, Andrey Shinkevich, 2020/05/12
- [PATCH v4 09/15] block: prepare block-stream for using COR-filter, Andrey Shinkevich, 2020/05/12
- [PATCH v4 08/15] block: Use CAFs when working with backing chains, Andrey Shinkevich, 2020/05/12
- [PATCH v4 04/15] block: Add chain helper functions, Andrey Shinkevich, 2020/05/12
- [PATCH v4 03/15] block: Add child access functions, Andrey Shinkevich, 2020/05/12
- Re: [PATCH v4 00/15] Apply COR-filter to the block-stream permanently, Vladimir Sementsov-Ogievskiy, 2020/05/12
- Re: [PATCH v4 00/15] Apply COR-filter to the block-stream permanently, no-reply, 2020/05/12