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