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