aboutsummaryrefslogtreecommitdiff
path: root/block/reqlist.c
diff options
context:
space:
mode:
authorVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>2022-03-03 20:43:39 +0100
committerHanna Reitz <hreitz@redhat.com>2022-03-07 09:33:30 +0100
commitd088e6a48aa437b2bf706a5f6cc4967f0eceba64 (patch)
tree884d04e53015646ced417434575b69c760ac95ee /block/reqlist.c
parent177541e671b439c358f816f8d8b98031a7e93540 (diff)
downloadqemu-d088e6a48aa437b2bf706a5f6cc4967f0eceba64.zip
qemu-d088e6a48aa437b2bf706a5f6cc4967f0eceba64.tar.gz
qemu-d088e6a48aa437b2bf706a5f6cc4967f0eceba64.tar.bz2
block: intoduce reqlist
Split intersecting-requests functionality out of block-copy to be reused in copy-before-write filter. Note: while being here, fix tiny typo in MAINTAINERS. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Message-Id: <20220303194349.2304213-7-vsementsov@virtuozzo.com> Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Diffstat (limited to 'block/reqlist.c')
-rw-r--r--block/reqlist.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/block/reqlist.c b/block/reqlist.c
new file mode 100644
index 0000000..5e320ba
--- /dev/null
+++ b/block/reqlist.c
@@ -0,0 +1,76 @@
+/*
+ * reqlist API
+ *
+ * Copyright (C) 2013 Proxmox Server Solutions
+ * Copyright (c) 2021 Virtuozzo International GmbH.
+ *
+ * Authors:
+ * Dietmar Maurer (dietmar@proxmox.com)
+ * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "block/reqlist.h"
+
+void reqlist_init_req(BlockReqList *reqs, BlockReq *req, int64_t offset,
+ int64_t bytes)
+{
+ assert(!reqlist_find_conflict(reqs, offset, bytes));
+
+ *req = (BlockReq) {
+ .offset = offset,
+ .bytes = bytes,
+ };
+ qemu_co_queue_init(&req->wait_queue);
+ QLIST_INSERT_HEAD(reqs, req, list);
+}
+
+BlockReq *reqlist_find_conflict(BlockReqList *reqs, int64_t offset,
+ int64_t bytes)
+{
+ BlockReq *r;
+
+ QLIST_FOREACH(r, reqs, list) {
+ if (offset + bytes > r->offset && offset < r->offset + r->bytes) {
+ return r;
+ }
+ }
+
+ return NULL;
+}
+
+bool coroutine_fn reqlist_wait_one(BlockReqList *reqs, int64_t offset,
+ int64_t bytes, CoMutex *lock)
+{
+ BlockReq *r = reqlist_find_conflict(reqs, offset, bytes);
+
+ if (!r) {
+ return false;
+ }
+
+ qemu_co_queue_wait(&r->wait_queue, lock);
+
+ return true;
+}
+
+void coroutine_fn reqlist_shrink_req(BlockReq *req, int64_t new_bytes)
+{
+ if (new_bytes == req->bytes) {
+ return;
+ }
+
+ assert(new_bytes > 0 && new_bytes < req->bytes);
+
+ req->bytes = new_bytes;
+ qemu_co_queue_restart_all(&req->wait_queue);
+}
+
+void coroutine_fn reqlist_remove_req(BlockReq *req)
+{
+ QLIST_REMOVE(req, list);
+ qemu_co_queue_restart_all(&req->wait_queue);
+}