diff options
author | Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 2022-03-03 20:43:39 +0100 |
---|---|---|
committer | Hanna Reitz <hreitz@redhat.com> | 2022-03-07 09:33:30 +0100 |
commit | d088e6a48aa437b2bf706a5f6cc4967f0eceba64 (patch) | |
tree | 884d04e53015646ced417434575b69c760ac95ee /block/reqlist.c | |
parent | 177541e671b439c358f816f8d8b98031a7e93540 (diff) | |
download | qemu-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.c | 76 |
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); +} |