xref: /aosp_15_r20/external/ublksrv/qcow2/utils.cpp (revision 94c4a1e103eb1715230460aab379dff275992c20)
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