blob: 08cb57cfa45bad3fae316aafcfb4234dac2fff44 [file] [log] [blame]
Vladimir Sementsov-Ogievskiyd088e6a2022-03-03 20:43:39 +01001/*
2 * reqlist API
3 *
4 * Copyright (C) 2013 Proxmox Server Solutions
5 * Copyright (c) 2021 Virtuozzo International GmbH.
6 *
7 * Authors:
8 * Dietmar Maurer (dietmar@proxmox.com)
9 * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10 *
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
13 */
14
15#include "qemu/osdep.h"
Vladimir Sementsov-Ogievskiy84b1e802022-03-03 20:43:40 +010016#include "qemu/range.h"
Vladimir Sementsov-Ogievskiyd088e6a2022-03-03 20:43:39 +010017
18#include "block/reqlist.h"
19
20void reqlist_init_req(BlockReqList *reqs, BlockReq *req, int64_t offset,
21 int64_t bytes)
22{
23 assert(!reqlist_find_conflict(reqs, offset, bytes));
24
25 *req = (BlockReq) {
26 .offset = offset,
27 .bytes = bytes,
28 };
29 qemu_co_queue_init(&req->wait_queue);
30 QLIST_INSERT_HEAD(reqs, req, list);
31}
32
33BlockReq *reqlist_find_conflict(BlockReqList *reqs, int64_t offset,
34 int64_t bytes)
35{
36 BlockReq *r;
37
38 QLIST_FOREACH(r, reqs, list) {
Vladimir Sementsov-Ogievskiy84b1e802022-03-03 20:43:40 +010039 if (ranges_overlap(offset, bytes, r->offset, r->bytes)) {
Vladimir Sementsov-Ogievskiyd088e6a2022-03-03 20:43:39 +010040 return r;
41 }
42 }
43
44 return NULL;
45}
46
47bool coroutine_fn reqlist_wait_one(BlockReqList *reqs, int64_t offset,
48 int64_t bytes, CoMutex *lock)
49{
50 BlockReq *r = reqlist_find_conflict(reqs, offset, bytes);
51
52 if (!r) {
53 return false;
54 }
55
56 qemu_co_queue_wait(&r->wait_queue, lock);
57
58 return true;
59}
60
Vladimir Sementsov-Ogievskiy3b7ca262022-03-03 20:43:42 +010061void coroutine_fn reqlist_wait_all(BlockReqList *reqs, int64_t offset,
62 int64_t bytes, CoMutex *lock)
63{
64 while (reqlist_wait_one(reqs, offset, bytes, lock)) {
65 /* continue */
66 }
67}
68
Vladimir Sementsov-Ogievskiyd088e6a2022-03-03 20:43:39 +010069void coroutine_fn reqlist_shrink_req(BlockReq *req, int64_t new_bytes)
70{
71 if (new_bytes == req->bytes) {
72 return;
73 }
74
75 assert(new_bytes > 0 && new_bytes < req->bytes);
76
77 req->bytes = new_bytes;
78 qemu_co_queue_restart_all(&req->wait_queue);
79}
80
81void coroutine_fn reqlist_remove_req(BlockReq *req)
82{
83 QLIST_REMOVE(req, list);
84 qemu_co_queue_restart_all(&req->wait_queue);
85}