qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

reqlist.c (2019B)


      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 }