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