xref: /openbmc/qemu/include/block/graph-lock.h (revision 7a5951f6)
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 
281