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