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 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 33 BlockReq *reqlist_find_conflict(BlockReqList *reqs, int64_t offset, 34 int64_t bytes) 35 { 36 BlockReq *r; 37 38 QLIST_FOREACH(r, reqs, list) { 39 if (ranges_overlap(offset, bytes, r->offset, r->bytes)) { 40 return r; 41 } 42 } 43 44 return NULL; 45 } 46 47 bool 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 61 void 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 69 void 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 81 void coroutine_fn reqlist_remove_req(BlockReq *req) 82 { 83 QLIST_REMOVE(req, list); 84 qemu_co_queue_restart_all(&req->wait_queue); 85 } 86