xref: /openbmc/qemu/include/block/graph-lock.h (revision 68ff2eeb299d562e437b49e9bb98f9d6f62fbf06)
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_wrlock_drained:
117  * Similar to bdrv_graph_wrlock, but will begin a drained section before
118  * locking.
119  */
120 void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
121 bdrv_graph_wrlock_drained(void);
122 
123 /*
124  * bdrv_graph_wrunlock:
125  * Write finished, reset global has_writer to 0 and restart
126  * all readers that are waiting.
127  *
128  * Also ends the drained section if bdrv_graph_wrlock_drained() was used to lock
129  * the graph.
130  */
131 void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA
132 bdrv_graph_wrunlock(void);
133 
134 /*
135  * bdrv_graph_co_rdlock:
136  * Read the bs graph. This usually means traversing all nodes in
137  * the graph, therefore it can't happen while another thread is
138  * modifying it.
139  * Increases the reader counter of the current aiocontext,
140  * and if has_writer is set, it means that the writer is modifying
141  * the graph, therefore wait in a coroutine queue.
142  * The writer will then wake this coroutine once it is done.
143  *
144  * This lock should be taken from Iothreads (IO_CODE() class of functions)
145  * because it signals the writer that there are some
146  * readers currently running, or waits until the current
147  * write is finished before continuing.
148  * Calling this function from the Main Loop with BQL held
149  * is not necessary, since the Main Loop itself is the only
150  * writer, thus won't be able to read and write at the same time.
151  * The only exception to that is when we can't take the lock in the
152  * function/coroutine itself, and need to delegate the caller (usually main
153  * loop) to take it and wait that the coroutine ends, so that
154  * we always signal that a reader is running.
155  */
156 void coroutine_fn TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
157 bdrv_graph_co_rdlock(void);
158 
159 /*
160  * bdrv_graph_rdunlock:
161  * Read terminated, decrease the count of readers in the current aiocontext.
162  * If the writer is waiting for reads to finish (has_writer == 1), signal
163  * the writer that we are done via aio_wait_kick() to let it continue.
164  */
165 void coroutine_fn TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
166 bdrv_graph_co_rdunlock(void);
167 
168 /*
169  * bdrv_graph_rd{un}lock_main_loop:
170  * Just a placeholder to mark where the graph rdlock should be taken
171  * in the main loop. It is just asserting that we are not
172  * in a coroutine and in GLOBAL_STATE_CODE.
173  */
174 void TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
175 bdrv_graph_rdlock_main_loop(void);
176 
177 void TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
178 bdrv_graph_rdunlock_main_loop(void);
179 
180 /*
181  * assert_bdrv_graph_readable:
182  * Make sure that the reader is either the main loop,
183  * or there is at least a reader helding the rdlock.
184  * In this way an incoming writer is aware of the read and waits.
185  */
186 void GRAPH_RDLOCK assert_bdrv_graph_readable(void);
187 
188 /*
189  * assert_bdrv_graph_writable:
190  * Make sure that the writer is the main loop and has set @has_writer,
191  * so that incoming readers will pause.
192  */
193 void GRAPH_WRLOCK assert_bdrv_graph_writable(void);
194 
195 /*
196  * Calling this function tells TSA that we know that the lock is effectively
197  * taken even though we cannot prove it (yet) with GRAPH_RDLOCK. This can be
198  * useful in intermediate stages of a conversion to using the GRAPH_RDLOCK
199  * macro.
200  */
TSA_ASSERT_SHARED(graph_lock)201 static inline void TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
202 assume_graph_lock(void)
203 {
204 }
205 
206 typedef struct GraphLockable { } GraphLockable;
207 
208 /*
209  * In C, compound literals have the lifetime of an automatic variable.
210  * In C++ it would be different, but then C++ wouldn't need QemuLockable
211  * either...
212  */
213 #define GML_OBJ_() (&(GraphLockable) { })
214 
215 /*
216  * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
217  * cleanup attribute and would therefore complain that the graph is never
218  * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
219  * we hold the lock while unlocking is left unchecked.
220  */
TSA_ACQUIRE_SHARED(graph_lock)221 static inline GraphLockable * TSA_ACQUIRE_SHARED(graph_lock) coroutine_fn
222 graph_lockable_auto_lock(GraphLockable *x)
223 {
224     bdrv_graph_co_rdlock();
225     return x;
226 }
227 
TSA_RELEASE_SHARED(graph_lock)228 static inline void TSA_RELEASE_SHARED(graph_lock) coroutine_fn
229 graph_lockable_auto_unlock(GraphLockable **x)
230 {
231     bdrv_graph_co_rdunlock();
232 }
233 
234 #define GRAPH_AUTO_UNLOCK __attribute__((cleanup(graph_lockable_auto_unlock)))
235 
236 /*
237  * @var is only used to break the loop after the first iteration.
238  * @unlock_var can't be unlocked and then set to NULL because TSA wants the lock
239  * to be held at the start of every iteration of the loop.
240  */
241 #define WITH_GRAPH_RDLOCK_GUARD_(var)                                         \
242     for (GraphLockable *unlock_var GRAPH_AUTO_UNLOCK =                        \
243             graph_lockable_auto_lock(GML_OBJ_()),                             \
244             *var = unlock_var;                                                \
245          var;                                                                 \
246          var = NULL)
247 
248 #define WITH_GRAPH_RDLOCK_GUARD() \
249     WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__))
250 
251 #define GRAPH_RDLOCK_GUARD(x)                                       \
252     GraphLockable * GRAPH_AUTO_UNLOCK                               \
253     glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED =          \
254             graph_lockable_auto_lock(GML_OBJ_())
255 
256 
257 typedef struct GraphLockableMainloop { } GraphLockableMainloop;
258 
259 /*
260  * In C, compound literals have the lifetime of an automatic variable.
261  * In C++ it would be different, but then C++ wouldn't need QemuLockable
262  * either...
263  */
264 #define GMLML_OBJ_() (&(GraphLockableMainloop) { })
265 
266 /*
267  * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
268  * cleanup attribute and would therefore complain that the graph is never
269  * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
270  * we hold the lock while unlocking is left unchecked.
271  */
TSA_ASSERT_SHARED(graph_lock)272 static inline GraphLockableMainloop * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
273 graph_lockable_auto_lock_mainloop(GraphLockableMainloop *x)
274 {
275     bdrv_graph_rdlock_main_loop();
276     return x;
277 }
278 
279 static inline void TSA_NO_TSA
graph_lockable_auto_unlock_mainloop(GraphLockableMainloop * x)280 graph_lockable_auto_unlock_mainloop(GraphLockableMainloop *x)
281 {
282     bdrv_graph_rdunlock_main_loop();
283 }
284 
285 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockableMainloop,
286                               graph_lockable_auto_unlock_mainloop)
287 
288 #define GRAPH_RDLOCK_GUARD_MAINLOOP(x)                              \
289     g_autoptr(GraphLockableMainloop)                                \
290     glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED =          \
291             graph_lockable_auto_lock_mainloop(GMLML_OBJ_())
292 
293 #endif /* GRAPH_LOCK_H */
294 
295