1*94c4a1e1SFrank Piva // SPDX-License-Identifier: GPL-2.0
2*94c4a1e1SFrank Piva #include <cassert>
3*94c4a1e1SFrank Piva
4*94c4a1e1SFrank Piva #include "qcow2.h"
5*94c4a1e1SFrank Piva #include "ublksrv_tgt.h"
6*94c4a1e1SFrank Piva
IOWaiters()7*94c4a1e1SFrank Piva IOWaiters::IOWaiters(): io_waiters({})
8*94c4a1e1SFrank Piva {
9*94c4a1e1SFrank Piva }
10*94c4a1e1SFrank Piva
add_waiter(unsigned tag)11*94c4a1e1SFrank Piva void IOWaiters::add_waiter(unsigned tag) {
12*94c4a1e1SFrank Piva __mapping_meta_add_waiter(tag, 0x3fffff);
13*94c4a1e1SFrank Piva }
14*94c4a1e1SFrank Piva
15*94c4a1e1SFrank Piva /* The caller is waiting on the specified entry update */
add_waiter_idx(unsigned tag,unsigned entry_idx)16*94c4a1e1SFrank Piva void IOWaiters::add_waiter_idx(unsigned tag, unsigned entry_idx) {
17*94c4a1e1SFrank Piva __mapping_meta_add_waiter(tag, entry_idx);
18*94c4a1e1SFrank Piva }
19*94c4a1e1SFrank Piva
20*94c4a1e1SFrank Piva /*
21*94c4a1e1SFrank Piva * For wakeup other IOs waiting for this meta.
22*94c4a1e1SFrank Piva *
23*94c4a1e1SFrank Piva * qcow2_tgt_io_done() will wakeup for current IO, that isn't covered
24*94c4a1e1SFrank Piva * by here.
25*94c4a1e1SFrank Piva */
__mapping_meta_wakeup_all(const struct ublksrv_queue * q,unsigned my_tag,unsigned entry_idx,bool all)26*94c4a1e1SFrank Piva void IOWaiters::__mapping_meta_wakeup_all(const struct ublksrv_queue *q,
27*94c4a1e1SFrank Piva unsigned my_tag, unsigned entry_idx, bool all) {
28*94c4a1e1SFrank Piva std::unordered_set<unsigned> tags(move(io_waiters));
29*94c4a1e1SFrank Piva std::unordered_set<unsigned>::const_iterator it = tags.cbegin();
30*94c4a1e1SFrank Piva
31*94c4a1e1SFrank Piva ublk_dbg(UBLK_DBG_QCOW2_IO_WAITER, "%s: %d %p my tag %d enter\n",
32*94c4a1e1SFrank Piva __func__, __LINE__, this, my_tag);
33*94c4a1e1SFrank Piva while (it != tags.cend()) {
34*94c4a1e1SFrank Piva unsigned t = *it;
35*94c4a1e1SFrank Piva unsigned tag = t & (QCOW2_MAX_QUEUE_DEPTH - 1);
36*94c4a1e1SFrank Piva unsigned idx = t >> QCOW2_TAG_BITS;
37*94c4a1e1SFrank Piva
38*94c4a1e1SFrank Piva /* can't wakeup me */
39*94c4a1e1SFrank Piva if (tag == my_tag) {
40*94c4a1e1SFrank Piva it = tags.erase(it);
41*94c4a1e1SFrank Piva continue;
42*94c4a1e1SFrank Piva }
43*94c4a1e1SFrank Piva
44*94c4a1e1SFrank Piva ublk_dbg(UBLK_DBG_QCOW2_IO_WAITER, "%s: %d my tag %d tag %d idx %x\n",
45*94c4a1e1SFrank Piva __func__, __LINE__, my_tag, tag, idx);
46*94c4a1e1SFrank Piva if (all || idx == entry_idx) {
47*94c4a1e1SFrank Piva struct ublk_io_tgt *__io =
48*94c4a1e1SFrank Piva ublk_get_io_tgt_data(q, tag);
49*94c4a1e1SFrank Piva
50*94c4a1e1SFrank Piva it = tags.erase(it);
51*94c4a1e1SFrank Piva __io->tgt_io_cqe = NULL;
52*94c4a1e1SFrank Piva
53*94c4a1e1SFrank Piva try {
54*94c4a1e1SFrank Piva ((struct ublk_io_tgt *)__io)->co.resume();
55*94c4a1e1SFrank Piva } catch (MetaIoException &meta_error) {
56*94c4a1e1SFrank Piva io_waiters.merge(tags);
57*94c4a1e1SFrank Piva throw MetaIoException();
58*94c4a1e1SFrank Piva } catch (MetaUpdateException &meta_update_error) {
59*94c4a1e1SFrank Piva io_waiters.merge(tags);
60*94c4a1e1SFrank Piva throw MetaUpdateException();
61*94c4a1e1SFrank Piva }
62*94c4a1e1SFrank Piva } else {
63*94c4a1e1SFrank Piva it++;
64*94c4a1e1SFrank Piva }
65*94c4a1e1SFrank Piva ublk_dbg(UBLK_DBG_QCOW2_IO_WAITER, "%s: %d %p my tag %d tag %d idx %x\n",
66*94c4a1e1SFrank Piva __func__, __LINE__, this, my_tag, tag, idx);
67*94c4a1e1SFrank Piva }
68*94c4a1e1SFrank Piva io_waiters.merge(tags);
69*94c4a1e1SFrank Piva ublk_dbg(UBLK_DBG_QCOW2_IO_WAITER, "%s: %d %p my tag %d exit\n",
70*94c4a1e1SFrank Piva __func__, __LINE__, this, my_tag);
71*94c4a1e1SFrank Piva }
72*94c4a1e1SFrank Piva
wakeup_all(const struct ublksrv_queue * q,unsigned my_tag)73*94c4a1e1SFrank Piva void IOWaiters::wakeup_all(const struct ublksrv_queue *q, unsigned my_tag) {
74*94c4a1e1SFrank Piva __mapping_meta_wakeup_all(q, my_tag, 0x3fffff, true);
75*94c4a1e1SFrank Piva }
76*94c4a1e1SFrank Piva
wakeup_all_idx(const struct ublksrv_queue * q,unsigned my_tag,unsigned entry_idx)77*94c4a1e1SFrank Piva void IOWaiters::wakeup_all_idx(const struct ublksrv_queue *q, unsigned my_tag,
78*94c4a1e1SFrank Piva unsigned entry_idx) {
79*94c4a1e1SFrank Piva __mapping_meta_wakeup_all(q, my_tag, entry_idx, false);
80*94c4a1e1SFrank Piva }
81