xref: /qemu/block/reqlist.c (revision 3b7ca26b)
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     assert(!reqlist_find_conflict(reqs, offset, bytes));
24d088e6a4SVladimir Sementsov-Ogievskiy 
25d088e6a4SVladimir Sementsov-Ogievskiy     *req = (BlockReq) {
26d088e6a4SVladimir Sementsov-Ogievskiy         .offset = offset,
27d088e6a4SVladimir Sementsov-Ogievskiy         .bytes = bytes,
28d088e6a4SVladimir Sementsov-Ogievskiy     };
29d088e6a4SVladimir Sementsov-Ogievskiy     qemu_co_queue_init(&req->wait_queue);
30d088e6a4SVladimir Sementsov-Ogievskiy     QLIST_INSERT_HEAD(reqs, req, list);
31d088e6a4SVladimir Sementsov-Ogievskiy }
32d088e6a4SVladimir Sementsov-Ogievskiy 
reqlist_find_conflict(BlockReqList * reqs,int64_t offset,int64_t bytes)33d088e6a4SVladimir Sementsov-Ogievskiy BlockReq *reqlist_find_conflict(BlockReqList *reqs, int64_t offset,
34d088e6a4SVladimir Sementsov-Ogievskiy                                 int64_t bytes)
35d088e6a4SVladimir Sementsov-Ogievskiy {
36d088e6a4SVladimir Sementsov-Ogievskiy     BlockReq *r;
37d088e6a4SVladimir Sementsov-Ogievskiy 
38d088e6a4SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(r, reqs, list) {
3984b1e80fSVladimir Sementsov-Ogievskiy         if (ranges_overlap(offset, bytes, r->offset, r->bytes)) {
40d088e6a4SVladimir Sementsov-Ogievskiy             return r;
41d088e6a4SVladimir Sementsov-Ogievskiy         }
42d088e6a4SVladimir Sementsov-Ogievskiy     }
43d088e6a4SVladimir Sementsov-Ogievskiy 
44d088e6a4SVladimir Sementsov-Ogievskiy     return NULL;
45d088e6a4SVladimir Sementsov-Ogievskiy }
46d088e6a4SVladimir Sementsov-Ogievskiy 
reqlist_wait_one(BlockReqList * reqs,int64_t offset,int64_t bytes,CoMutex * lock)47d088e6a4SVladimir Sementsov-Ogievskiy bool coroutine_fn reqlist_wait_one(BlockReqList *reqs, int64_t offset,
48d088e6a4SVladimir Sementsov-Ogievskiy                                    int64_t bytes, CoMutex *lock)
49d088e6a4SVladimir Sementsov-Ogievskiy {
50d088e6a4SVladimir Sementsov-Ogievskiy     BlockReq *r = reqlist_find_conflict(reqs, offset, bytes);
51d088e6a4SVladimir Sementsov-Ogievskiy 
52d088e6a4SVladimir Sementsov-Ogievskiy     if (!r) {
53d088e6a4SVladimir Sementsov-Ogievskiy         return false;
54d088e6a4SVladimir Sementsov-Ogievskiy     }
55d088e6a4SVladimir Sementsov-Ogievskiy 
56d088e6a4SVladimir Sementsov-Ogievskiy     qemu_co_queue_wait(&r->wait_queue, lock);
57d088e6a4SVladimir Sementsov-Ogievskiy 
58d088e6a4SVladimir Sementsov-Ogievskiy     return true;
59d088e6a4SVladimir Sementsov-Ogievskiy }
60d088e6a4SVladimir Sementsov-Ogievskiy 
reqlist_wait_all(BlockReqList * reqs,int64_t offset,int64_t bytes,CoMutex * lock)61*3b7ca26bSVladimir Sementsov-Ogievskiy void coroutine_fn reqlist_wait_all(BlockReqList *reqs, int64_t offset,
62*3b7ca26bSVladimir Sementsov-Ogievskiy                                    int64_t bytes, CoMutex *lock)
63*3b7ca26bSVladimir Sementsov-Ogievskiy {
64*3b7ca26bSVladimir Sementsov-Ogievskiy     while (reqlist_wait_one(reqs, offset, bytes, lock)) {
65*3b7ca26bSVladimir Sementsov-Ogievskiy         /* continue */
66*3b7ca26bSVladimir Sementsov-Ogievskiy     }
67*3b7ca26bSVladimir Sementsov-Ogievskiy }
68*3b7ca26bSVladimir Sementsov-Ogievskiy 
reqlist_shrink_req(BlockReq * req,int64_t new_bytes)69d088e6a4SVladimir Sementsov-Ogievskiy void coroutine_fn reqlist_shrink_req(BlockReq *req, int64_t new_bytes)
70d088e6a4SVladimir Sementsov-Ogievskiy {
71d088e6a4SVladimir Sementsov-Ogievskiy     if (new_bytes == req->bytes) {
72d088e6a4SVladimir Sementsov-Ogievskiy         return;
73d088e6a4SVladimir Sementsov-Ogievskiy     }
74d088e6a4SVladimir Sementsov-Ogievskiy 
75d088e6a4SVladimir Sementsov-Ogievskiy     assert(new_bytes > 0 && new_bytes < req->bytes);
76d088e6a4SVladimir Sementsov-Ogievskiy 
77d088e6a4SVladimir Sementsov-Ogievskiy     req->bytes = new_bytes;
78d088e6a4SVladimir Sementsov-Ogievskiy     qemu_co_queue_restart_all(&req->wait_queue);
79d088e6a4SVladimir Sementsov-Ogievskiy }
80d088e6a4SVladimir Sementsov-Ogievskiy 
reqlist_remove_req(BlockReq * req)81d088e6a4SVladimir Sementsov-Ogievskiy void coroutine_fn reqlist_remove_req(BlockReq *req)
82d088e6a4SVladimir Sementsov-Ogievskiy {
83d088e6a4SVladimir Sementsov-Ogievskiy     QLIST_REMOVE(req, list);
84d088e6a4SVladimir Sementsov-Ogievskiy     qemu_co_queue_restart_all(&req->wait_queue);
85d088e6a4SVladimir Sementsov-Ogievskiy }
86