]> git.proxmox.com Git - mirror_qemu.git/blob - include/block/graph-lock.h
Mark assert_bdrv_graph_readable/writable() GRAPH_RD/WRLOCK
[mirror_qemu.git] / include / block / graph-lock.h
1 /*
2 * Graph lock: rwlock to protect block layer graph manipulations (add/remove
3 * edges and nodes)
4 *
5 * Copyright (c) 2022 Red Hat
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20 #ifndef GRAPH_LOCK_H
21 #define GRAPH_LOCK_H
22
23 #include "qemu/osdep.h"
24 #include "qemu/clang-tsa.h"
25
26 #include "qemu/coroutine.h"
27
28 /**
29 * Graph Lock API
30 * This API provides a rwlock used to protect block layer
31 * graph modifications like edge (BdrvChild) and node (BlockDriverState)
32 * addition and removal.
33 * Currently we have 1 writer only, the Main loop, and many
34 * readers, mostly coroutines running in other AioContext thus other threads.
35 *
36 * We distinguish between writer (main loop, under BQL) that modifies the
37 * graph, and readers (all other coroutines running in various AioContext),
38 * that go through the graph edges, reading
39 * BlockDriverState ->parents and->children.
40 *
41 * The writer (main loop) has an "exclusive" access, so it first waits for
42 * current read to finish, and then prevents incoming ones from
43 * entering while it has the exclusive access.
44 *
45 * The readers (coroutines in multiple AioContext) are free to
46 * access the graph as long the writer is not modifying the graph.
47 * In case it is, they go in a CoQueue and sleep until the writer
48 * is done.
49 *
50 * If a coroutine changes AioContext, the counter in the original and new
51 * AioContext are left intact, since the writer does not care where is the
52 * reader, but only if there is one.
53 * As a result, some AioContexts might have a negative reader count, to
54 * balance the positive count of the AioContext that took the lock.
55 * This also means that when an AioContext is deleted it may have a nonzero
56 * reader count. In that case we transfer the count to a global shared counter
57 * so that the writer is always aware of all readers.
58 */
59 typedef struct BdrvGraphRWlock BdrvGraphRWlock;
60
61 /* Dummy lock object to use for Thread Safety Analysis (TSA) */
62 typedef struct TSA_CAPABILITY("mutex") BdrvGraphLock {
63 } BdrvGraphLock;
64
65 extern BdrvGraphLock graph_lock;
66
67 /*
68 * clang doesn't check consistency in locking annotations between forward
69 * declarations and the function definition. Having the annotation on the
70 * definition, but not the declaration in a header file, may give the reader
71 * a false sense of security because the condition actually remains unchecked
72 * for callers in other source files.
73 *
74 * Therefore, as a convention, for public functions, GRAPH_RDLOCK and
75 * GRAPH_WRLOCK annotations should be present only in the header file.
76 */
77 #define GRAPH_WRLOCK TSA_REQUIRES(graph_lock)
78 #define GRAPH_RDLOCK TSA_REQUIRES_SHARED(graph_lock)
79
80 /*
81 * TSA annotations are not part of function types, so checks are defeated when
82 * using a function pointer. As a workaround, annotate function pointers with
83 * this macro that will require that the lock is at least taken while reading
84 * the pointer. In most cases this is equivalent to actually protecting the
85 * function call.
86 */
87 #define GRAPH_RDLOCK_PTR TSA_GUARDED_BY(graph_lock)
88 #define GRAPH_WRLOCK_PTR TSA_GUARDED_BY(graph_lock)
89
90 /*
91 * register_aiocontext:
92 * Add AioContext @ctx to the list of AioContext.
93 * This list is used to obtain the total number of readers
94 * currently running the graph.
95 */
96 void register_aiocontext(AioContext *ctx);
97
98 /*
99 * unregister_aiocontext:
100 * Removes AioContext @ctx to the list of AioContext.
101 */
102 void unregister_aiocontext(AioContext *ctx);
103
104 /*
105 * bdrv_graph_wrlock:
106 * Start an exclusive write operation to modify the graph. This means we are
107 * adding or removing an edge or a node in the block layer graph. Nobody else
108 * is allowed to access the graph.
109 *
110 * Must only be called from outside bdrv_graph_co_rdlock.
111 *
112 * The wrlock can only be taken from the main loop, with BQL held, as only the
113 * main loop is allowed to modify the graph.
114 *
115 * This function polls. Callers must not hold the lock of any AioContext other
116 * than the current one.
117 */
118 void bdrv_graph_wrlock(void) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
119
120 /*
121 * bdrv_graph_wrunlock:
122 * Write finished, reset global has_writer to 0 and restart
123 * all readers that are waiting.
124 */
125 void bdrv_graph_wrunlock(void) TSA_RELEASE(graph_lock) TSA_NO_TSA;
126
127 /*
128 * bdrv_graph_co_rdlock:
129 * Read the bs graph. This usually means traversing all nodes in
130 * the graph, therefore it can't happen while another thread is
131 * modifying it.
132 * Increases the reader counter of the current aiocontext,
133 * and if has_writer is set, it means that the writer is modifying
134 * the graph, therefore wait in a coroutine queue.
135 * The writer will then wake this coroutine once it is done.
136 *
137 * This lock should be taken from Iothreads (IO_CODE() class of functions)
138 * because it signals the writer that there are some
139 * readers currently running, or waits until the current
140 * write is finished before continuing.
141 * Calling this function from the Main Loop with BQL held
142 * is not necessary, since the Main Loop itself is the only
143 * writer, thus won't be able to read and write at the same time.
144 * The only exception to that is when we can't take the lock in the
145 * function/coroutine itself, and need to delegate the caller (usually main
146 * loop) to take it and wait that the coroutine ends, so that
147 * we always signal that a reader is running.
148 */
149 void coroutine_fn TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
150 bdrv_graph_co_rdlock(void);
151
152 /*
153 * bdrv_graph_rdunlock:
154 * Read terminated, decrease the count of readers in the current aiocontext.
155 * If the writer is waiting for reads to finish (has_writer == 1), signal
156 * the writer that we are done via aio_wait_kick() to let it continue.
157 */
158 void coroutine_fn TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
159 bdrv_graph_co_rdunlock(void);
160
161 /*
162 * bdrv_graph_rd{un}lock_main_loop:
163 * Just a placeholder to mark where the graph rdlock should be taken
164 * in the main loop. It is just asserting that we are not
165 * in a coroutine and in GLOBAL_STATE_CODE.
166 */
167 void TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
168 bdrv_graph_rdlock_main_loop(void);
169
170 void TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
171 bdrv_graph_rdunlock_main_loop(void);
172
173 /*
174 * assert_bdrv_graph_readable:
175 * Make sure that the reader is either the main loop,
176 * or there is at least a reader helding the rdlock.
177 * In this way an incoming writer is aware of the read and waits.
178 */
179 void GRAPH_RDLOCK assert_bdrv_graph_readable(void);
180
181 /*
182 * assert_bdrv_graph_writable:
183 * Make sure that the writer is the main loop and has set @has_writer,
184 * so that incoming readers will pause.
185 */
186 void GRAPH_WRLOCK assert_bdrv_graph_writable(void);
187
188 /*
189 * Calling this function tells TSA that we know that the lock is effectively
190 * taken even though we cannot prove it (yet) with GRAPH_RDLOCK. This can be
191 * useful in intermediate stages of a conversion to using the GRAPH_RDLOCK
192 * macro.
193 */
194 static inline void TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
195 assume_graph_lock(void)
196 {
197 }
198
199 typedef struct GraphLockable { } GraphLockable;
200
201 /*
202 * In C, compound literals have the lifetime of an automatic variable.
203 * In C++ it would be different, but then C++ wouldn't need QemuLockable
204 * either...
205 */
206 #define GML_OBJ_() (&(GraphLockable) { })
207
208 /*
209 * This is not marked as TSA_ACQUIRE() because TSA doesn't understand the
210 * cleanup attribute and would therefore complain that the graph is never
211 * unlocked. TSA_ASSERT() makes sure that the following calls know that we
212 * hold the lock while unlocking is left unchecked.
213 */
214 static inline GraphLockable * TSA_ASSERT(graph_lock) TSA_NO_TSA
215 graph_lockable_auto_lock(GraphLockable *x)
216 {
217 bdrv_graph_co_rdlock();
218 return x;
219 }
220
221 static inline void TSA_NO_TSA
222 graph_lockable_auto_unlock(GraphLockable *x)
223 {
224 bdrv_graph_co_rdunlock();
225 }
226
227 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockable, graph_lockable_auto_unlock)
228
229 #define WITH_GRAPH_RDLOCK_GUARD_(var) \
230 for (g_autoptr(GraphLockable) var = graph_lockable_auto_lock(GML_OBJ_()); \
231 var; \
232 graph_lockable_auto_unlock(var), var = NULL)
233
234 #define WITH_GRAPH_RDLOCK_GUARD() \
235 WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__))
236
237 #define GRAPH_RDLOCK_GUARD(x) \
238 g_autoptr(GraphLockable) \
239 glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
240 graph_lockable_auto_lock(GML_OBJ_())
241
242
243 typedef struct GraphLockableMainloop { } GraphLockableMainloop;
244
245 /*
246 * In C, compound literals have the lifetime of an automatic variable.
247 * In C++ it would be different, but then C++ wouldn't need QemuLockable
248 * either...
249 */
250 #define GMLML_OBJ_() (&(GraphLockableMainloop) { })
251
252 /*
253 * This is not marked as TSA_ACQUIRE() because TSA doesn't understand the
254 * cleanup attribute and would therefore complain that the graph is never
255 * unlocked. TSA_ASSERT() makes sure that the following calls know that we
256 * hold the lock while unlocking is left unchecked.
257 */
258 static inline GraphLockableMainloop * TSA_ASSERT(graph_lock) TSA_NO_TSA
259 graph_lockable_auto_lock_mainloop(GraphLockableMainloop *x)
260 {
261 bdrv_graph_rdlock_main_loop();
262 return x;
263 }
264
265 static inline void TSA_NO_TSA
266 graph_lockable_auto_unlock_mainloop(GraphLockableMainloop *x)
267 {
268 bdrv_graph_rdunlock_main_loop();
269 }
270
271 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockableMainloop,
272 graph_lockable_auto_unlock_mainloop)
273
274 #define GRAPH_RDLOCK_GUARD_MAINLOOP(x) \
275 g_autoptr(GraphLockableMainloop) \
276 glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
277 graph_lockable_auto_lock_mainloop(GMLML_OBJ_())
278
279 #endif /* GRAPH_LOCK_H */
280