qemu/block/reqlist.c
<<
>>
Prefs
   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
  20void 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
  33BlockReq *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
  47bool 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
  61void 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
  69void 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
  81void coroutine_fn reqlist_remove_req(BlockReq *req)
  82{
  83    QLIST_REMOVE(req, list);
  84    qemu_co_queue_restart_all(&req->wait_queue);
  85}
  86