]> git.proxmox.com Git - mirror_qemu.git/blame - include/block/graph-lock.h
Merge tag 'pull-ufs-20231013' of https://gitlab.com/jeuk20.kim/qemu into staging
[mirror_qemu.git] / include / block / graph-lock.h
CommitLineData
aead9dc9
PB
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
4002ffdc 23#include "qemu/clang-tsa.h"
aead9dc9 24
aead9dc9
PB
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 */
56typedef struct BdrvGraphRWlock BdrvGraphRWlock;
57
4002ffdc
KW
58/* Dummy lock object to use for Thread Safety Analysis (TSA) */
59typedef struct TSA_CAPABILITY("mutex") BdrvGraphLock {
60} BdrvGraphLock;
61
62extern 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)
d51c349b 76#define GRAPH_UNLOCKED TSA_EXCLUDES(graph_lock)
4002ffdc
KW
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)
d51c349b 87#define GRAPH_UNLOCKED_PTR
4002ffdc 88
aead9dc9
PB
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 */
95void register_aiocontext(AioContext *ctx);
96
97/*
98 * unregister_aiocontext:
99 * Removes AioContext @ctx to the list of AioContext.
100 */
101void 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 *
31b2ddfe
KW
114 * If @bs is non-NULL, its AioContext is temporarily released.
115 *
aead9dc9 116 * This function polls. Callers must not hold the lock of any AioContext other
31b2ddfe 117 * than the current one and the one of @bs.
aead9dc9 118 */
e6e964b8
KW
119void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
120bdrv_graph_wrlock(BlockDriverState *bs);
aead9dc9
PB
121
122/*
123 * bdrv_graph_wrunlock:
124 * Write finished, reset global has_writer to 0 and restart
125 * all readers that are waiting.
126 */
4002ffdc 127void bdrv_graph_wrunlock(void) TSA_RELEASE(graph_lock) TSA_NO_TSA;
aead9dc9
PB
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 */
4002ffdc
KW
151void coroutine_fn TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
152bdrv_graph_co_rdlock(void);
aead9dc9
PB
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 */
4002ffdc
KW
160void coroutine_fn TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
161bdrv_graph_co_rdunlock(void);
aead9dc9
PB
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 */
4002ffdc
KW
169void TSA_ACQUIRE_SHARED(graph_lock) TSA_NO_TSA
170bdrv_graph_rdlock_main_loop(void);
171
172void TSA_RELEASE_SHARED(graph_lock) TSA_NO_TSA
173bdrv_graph_rdunlock_main_loop(void);
aead9dc9 174
3f35f82e
EGE
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 */
303de47b 181void GRAPH_RDLOCK assert_bdrv_graph_readable(void);
3f35f82e
EGE
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 */
303de47b 188void GRAPH_WRLOCK assert_bdrv_graph_writable(void);
3f35f82e 189
4002ffdc
KW
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 */
196static inline void TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
197assume_graph_lock(void)
198{
199}
200
8aa77000
EGE
201typedef 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
4002ffdc 210/*
4ee1f854 211 * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
4002ffdc 212 * cleanup attribute and would therefore complain that the graph is never
4ee1f854
KW
213 * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
214 * we hold the lock while unlocking is left unchecked.
4002ffdc 215 */
4ee1f854 216static inline GraphLockable * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA coroutine_fn
4002ffdc 217graph_lockable_auto_lock(GraphLockable *x)
8aa77000
EGE
218{
219 bdrv_graph_co_rdlock();
220 return x;
221}
222
17ac39c3 223static inline void TSA_NO_TSA coroutine_fn
4002ffdc 224graph_lockable_auto_unlock(GraphLockable *x)
8aa77000
EGE
225{
226 bdrv_graph_co_rdunlock();
227}
228
229G_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
245typedef 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
4002ffdc 254/*
4ee1f854 255 * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
4002ffdc 256 * cleanup attribute and would therefore complain that the graph is never
4ee1f854
KW
257 * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
258 * we hold the lock while unlocking is left unchecked.
4002ffdc 259 */
4ee1f854 260static inline GraphLockableMainloop * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
8aa77000
EGE
261graph_lockable_auto_lock_mainloop(GraphLockableMainloop *x)
262{
263 bdrv_graph_rdlock_main_loop();
264 return x;
265}
266
4002ffdc 267static inline void TSA_NO_TSA
8aa77000
EGE
268graph_lockable_auto_unlock_mainloop(GraphLockableMainloop *x)
269{
270 bdrv_graph_rdunlock_main_loop();
271}
272
273G_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
aead9dc9
PB
281#endif /* GRAPH_LOCK_H */
282