1 // SPDX-License-Identifier: GPL-2.0
2 #ifndef UBLK_QCOW2_COMMON_H_
3 #define UBLK_QCOW2_COMMON_H_
4
5 #include "ublksrv_tgt.h"
6
7 #define qcow2_assert(x) ublk_assert(x)
8
9 #ifdef DEBUG
10 #define QCOW2_DEBUG DEBUG
11 #else
12 #undef QCOW2_DEBUG
13 #endif
14
15 #define UBLK_DBG_QCOW2_FLUSH (1U << 16)
16 #define UBLK_DBG_QCOW2_META_L2 (1U << 17)
17 #define UBLK_DBG_QCOW2_META_L1 (1U << 18)
18 #define UBLK_DBG_QCOW2_META_RB (1U << 19)
19 #define UBLK_DBG_QCOW2_IO_WAITER (1U << 20)
20 #define UBLK_DBG_QCOW2_ALLOCATOR (1U << 21)
21
22 #define UBLK_DBG_QCOW2_META (UBLK_DBG_QCOW2_META_L2 | UBLK_DBG_QCOW2_META_RB)
23
24 enum QCOW2_PARA {
25 #ifdef DEBUG_QCOW2_META_STRESS
26 REFCOUNT_BLK_MAX_CACHE_BYTES = 8U << 10,
27 #else
28 REFCOUNT_BLK_MAX_CACHE_BYTES = 256U << 10,
29 #endif
30 REFCOUNT_BLK_SLICE_BITS = 12,
31 REFCOUNT_BLK_SLICE_BYTES = 1U << REFCOUNT_BLK_SLICE_BITS,
32
33 #ifdef DEBUG_QCOW2_META_STRESS
34 L2_TABLE_MAX_CACHE_BYTES = 1U << 13,
35 #else
36 L2_TABLE_MAX_CACHE_BYTES = 1U << 20,
37 #endif
38 L2_TABLE_SLICE_BITS = 12,
39 L2_TABLE_SLICE_BYTES = 1U << L2_TABLE_SLICE_BITS,
40
41 #ifdef DEBUG_QCOW2_META_STRESS
42 META_MAX_TAGS = 1,
43 #else
44 META_MAX_TAGS = 16,
45 #endif
46 //at most 500ms delay if not any slice is running of
47 //lru cache, otherwise the flush is started immediately
48 MAX_META_FLUSH_DELAY_MS = 500,
49 };
50
51 #define qcow2_log ublk_log
52
53 //be careful
54 //#DEBUG_QCOW2_META_OBJ, still required for some meta debug
55
56 #ifdef QCOW2_DEBUG
alloc_log(const char * fmt,...)57 static inline void alloc_log(const char *fmt, ...)
58 {
59 va_list ap;
60
61 va_start(ap, fmt);
62 ublk_dbg(UBLK_DBG_QCOW2_ALLOCATOR, fmt, ap);
63 }
64
flush_log(const char * fmt,...)65 static inline void flush_log(const char *fmt, ...)
66 {
67 va_list ap;
68
69 va_start(ap, fmt);
70 ublk_dbg(UBLK_DBG_QCOW2_FLUSH, fmt, ap);
71 }
72
qcow2_io_log(const char * fmt,...)73 static inline void qcow2_io_log(const char *fmt, ...)
74 {
75 va_list ap;
76
77 va_start(ap, fmt);
78 ublk_dbg(UBLK_DBG_IO, fmt, ap);
79 }
80
81 #else
82 #define alloc_log(...) do {}while(0)
83 #define flush_log(...) do {}while(0)
84 #define qcow2_io_log(...) do {}while(0)
85 #endif
86
87 /*
88 * 00 ~ 11: tag
89 * 12 ~ 23: qid
90 * 24 ~ 31: type_id, 0 ~ 254: meta, 255: data,
91 * so which meta data can be looked up via this type_id in each io
92 */
93 class qcow2_io_ctx_t {
94 public:
95 u32 data;
96
get_tag()97 u32 get_tag() const {
98 return data & 0xfff;
99 }
100
get_qid()101 u32 get_qid() const {
102 return (data >> 12) & 0xfff;
103 }
104
get_type()105 u32 get_type() const {
106 return (data >> 24) & 0xff;
107 }
108
set_type(u8 type)109 void set_type(u8 type) {
110 data &= 0x00ffffff;
111 data |= type << 24;
112 }
113
qcow2_io_ctx_t()114 qcow2_io_ctx_t() {
115 data = 255U << 24;
116 }
qcow2_io_ctx_t(u32 val)117 qcow2_io_ctx_t(u32 val) {
118 data = val;
119 }
qcow2_io_ctx_t(u32 tag,u32 qid)120 qcow2_io_ctx_t(u32 tag, u32 qid) {
121 data = (qid << 12) | tag;
122 }
qcow2_io_ctx_t(u32 tag,u32 qid,u8 type)123 qcow2_io_ctx_t(u32 tag, u32 qid, u8 type) {
124 data = (type << 24) | (qid << 12) | tag;
125 }
126 qcow2_io_ctx_t operator=(const u32 val) {
127 return qcow2_io_ctx_t(val);
128 }
129 };
130
131
132 //L1 max size is 32MB which can have 4M entries, so at most 22 bits
133 //needed, so define QCOW2_TAG_BITS as 10, so the upper 22 bits can
134 //hold entry index.
135 #define QCOW2_TAG_BITS 10
136 #define QCOW2_MAX_QUEUE_DEPTH (1U<<10)
137
138 class IOWaiters {
139 private:
140 //io waiters for this meta data, once this meta is updated,
141 //call resume() on each io in io_waiters, so before io ctx
142 //is waiting, it has to be added to io_waiters.
143 //
144 //Support to wait on single entry update, and the entry index
145 //is stored in bit 31~12, tag is stored in bit 11~0. All one
146 //entry index means that waitting on whole meta data.
147 //
148 std::unordered_set<unsigned int> io_waiters;
149
__mapping_meta_add_waiter(unsigned tag,unsigned entry_idx)150 void __mapping_meta_add_waiter(unsigned tag, unsigned entry_idx) {
151 unsigned val;
152
153 qcow2_assert(!(tag & ~(QCOW2_MAX_QUEUE_DEPTH - 1)));
154 qcow2_assert(!(entry_idx & ~((1U << (32 - QCOW2_TAG_BITS)) - 1)));
155
156 val = tag | (entry_idx << QCOW2_TAG_BITS);
157 io_waiters.insert(val);
158 }
159 void __mapping_meta_wakeup_all(const struct ublksrv_queue *q,
160 unsigned my_tag, unsigned entry_idx, bool all);
161 public:
162 IOWaiters();
163 void add_waiter(unsigned tag);
164 void add_waiter_idx(unsigned tag, unsigned entry_idx);
165 void wakeup_all(const struct ublksrv_queue *q, unsigned my_tag);
166 void wakeup_all_idx(const struct ublksrv_queue *q,
167 unsigned my_tag, unsigned entry_idx);
168 };
169
170 #endif
171