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