xref: /openbmc/qemu/block/reqlist.c (revision 7eefbf8bb72c1bec0972ca19901207dc6d2acf5a)
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