Commit | Line | Data |
---|---|---|
c1d7c514 | 1 | // SPDX-License-Identifier: GPL-2.0 |
925baedd CM |
2 | /* |
3 | * Copyright (C) 2008 Oracle. All rights reserved. | |
925baedd | 4 | */ |
c1d7c514 | 5 | |
925baedd | 6 | #include <linux/sched.h> |
925baedd CM |
7 | #include <linux/pagemap.h> |
8 | #include <linux/spinlock.h> | |
9 | #include <linux/page-flags.h> | |
4881ee5a | 10 | #include <asm/bug.h> |
602cbe91 | 11 | #include "misc.h" |
925baedd CM |
12 | #include "ctree.h" |
13 | #include "extent_io.h" | |
14 | #include "locking.h" | |
15 | ||
d4e253bb DS |
16 | /* |
17 | * Extent buffer locking | |
18 | * ===================== | |
19 | * | |
20 | * The locks use a custom scheme that allows to do more operations than are | |
21 | * available fromt current locking primitives. The building blocks are still | |
22 | * rwlock and wait queues. | |
23 | * | |
24 | * Required semantics: | |
25 | * | |
26 | * - reader/writer exclusion | |
27 | * - writer/writer exclusion | |
28 | * - reader/reader sharing | |
29 | * - spinning lock semantics | |
30 | * - blocking lock semantics | |
31 | * - try-lock semantics for readers and writers | |
32 | * - one level nesting, allowing read lock to be taken by the same thread that | |
33 | * already has write lock | |
34 | * | |
35 | * The extent buffer locks (also called tree locks) manage access to eb data | |
36 | * related to the storage in the b-tree (keys, items, but not the individual | |
37 | * members of eb). | |
38 | * We want concurrency of many readers and safe updates. The underlying locking | |
39 | * is done by read-write spinlock and the blocking part is implemented using | |
40 | * counters and wait queues. | |
41 | * | |
42 | * spinning semantics - the low-level rwlock is held so all other threads that | |
43 | * want to take it are spinning on it. | |
44 | * | |
45 | * blocking semantics - the low-level rwlock is not held but the counter | |
46 | * denotes how many times the blocking lock was held; | |
47 | * sleeping is possible | |
48 | * | |
49 | * Write lock always allows only one thread to access the data. | |
50 | * | |
51 | * | |
52 | * Debugging | |
53 | * --------- | |
54 | * | |
55 | * There are additional state counters that are asserted in various contexts, | |
56 | * removed from non-debug build to reduce extent_buffer size and for | |
57 | * performance reasons. | |
58 | * | |
59 | * | |
60 | * Lock nesting | |
61 | * ------------ | |
62 | * | |
63 | * A write operation on a tree might indirectly start a look up on the same | |
64 | * tree. This can happen when btrfs_cow_block locks the tree and needs to | |
65 | * lookup free extents. | |
66 | * | |
67 | * btrfs_cow_block | |
68 | * .. | |
69 | * alloc_tree_block_no_bg_flush | |
70 | * btrfs_alloc_tree_block | |
71 | * btrfs_reserve_extent | |
72 | * .. | |
73 | * load_free_space_cache | |
74 | * .. | |
75 | * btrfs_lookup_file_extent | |
76 | * btrfs_search_slot | |
77 | * | |
78 | * | |
79 | * Locking pattern - spinning | |
80 | * -------------------------- | |
81 | * | |
82 | * The simple locking scenario, the +--+ denotes the spinning section. | |
83 | * | |
84 | * +- btrfs_tree_lock | |
85 | * | - extent_buffer::rwlock is held | |
86 | * | - no heavy operations should happen, eg. IO, memory allocations, large | |
87 | * | structure traversals | |
88 | * +- btrfs_tree_unock | |
89 | * | |
90 | * | |
91 | * Locking pattern - blocking | |
92 | * -------------------------- | |
93 | * | |
94 | * The blocking write uses the following scheme. The +--+ denotes the spinning | |
95 | * section. | |
96 | * | |
97 | * +- btrfs_tree_lock | |
98 | * | | |
99 | * +- btrfs_set_lock_blocking_write | |
100 | * | |
101 | * - allowed: IO, memory allocations, etc. | |
102 | * | |
103 | * -- btrfs_tree_unlock - note, no explicit unblocking necessary | |
104 | * | |
105 | * | |
106 | * Blocking read is similar. | |
107 | * | |
108 | * +- btrfs_tree_read_lock | |
109 | * | | |
110 | * +- btrfs_set_lock_blocking_read | |
111 | * | |
112 | * - heavy operations allowed | |
113 | * | |
114 | * +- btrfs_tree_read_unlock_blocking | |
115 | * | | |
116 | * +- btrfs_tree_read_unlock | |
117 | * | |
118 | */ | |
119 | ||
e4e9fd0f | 120 | #ifdef CONFIG_BTRFS_DEBUG |
d6156218 | 121 | static inline void btrfs_assert_spinning_writers_get(struct extent_buffer *eb) |
e4e9fd0f | 122 | { |
f3dc24c5 DS |
123 | WARN_ON(eb->spinning_writers); |
124 | eb->spinning_writers++; | |
e4e9fd0f DS |
125 | } |
126 | ||
d6156218 | 127 | static inline void btrfs_assert_spinning_writers_put(struct extent_buffer *eb) |
e4e9fd0f | 128 | { |
f3dc24c5 DS |
129 | WARN_ON(eb->spinning_writers != 1); |
130 | eb->spinning_writers--; | |
e4e9fd0f DS |
131 | } |
132 | ||
d6156218 | 133 | static inline void btrfs_assert_no_spinning_writers(struct extent_buffer *eb) |
e4e9fd0f | 134 | { |
f3dc24c5 | 135 | WARN_ON(eb->spinning_writers); |
e4e9fd0f DS |
136 | } |
137 | ||
d6156218 | 138 | static inline void btrfs_assert_spinning_readers_get(struct extent_buffer *eb) |
225948de DS |
139 | { |
140 | atomic_inc(&eb->spinning_readers); | |
141 | } | |
142 | ||
d6156218 | 143 | static inline void btrfs_assert_spinning_readers_put(struct extent_buffer *eb) |
225948de DS |
144 | { |
145 | WARN_ON(atomic_read(&eb->spinning_readers) == 0); | |
146 | atomic_dec(&eb->spinning_readers); | |
147 | } | |
148 | ||
d6156218 | 149 | static inline void btrfs_assert_tree_read_locks_get(struct extent_buffer *eb) |
58a2ddae DS |
150 | { |
151 | atomic_inc(&eb->read_locks); | |
152 | } | |
153 | ||
d6156218 | 154 | static inline void btrfs_assert_tree_read_locks_put(struct extent_buffer *eb) |
58a2ddae DS |
155 | { |
156 | atomic_dec(&eb->read_locks); | |
157 | } | |
158 | ||
d6156218 | 159 | static inline void btrfs_assert_tree_read_locked(struct extent_buffer *eb) |
58a2ddae DS |
160 | { |
161 | BUG_ON(!atomic_read(&eb->read_locks)); | |
162 | } | |
163 | ||
d6156218 | 164 | static inline void btrfs_assert_tree_write_locks_get(struct extent_buffer *eb) |
e3f15388 | 165 | { |
00801ae4 | 166 | eb->write_locks++; |
e3f15388 DS |
167 | } |
168 | ||
d6156218 | 169 | static inline void btrfs_assert_tree_write_locks_put(struct extent_buffer *eb) |
e3f15388 | 170 | { |
00801ae4 | 171 | eb->write_locks--; |
e3f15388 DS |
172 | } |
173 | ||
e4e9fd0f DS |
174 | #else |
175 | static void btrfs_assert_spinning_writers_get(struct extent_buffer *eb) { } | |
176 | static void btrfs_assert_spinning_writers_put(struct extent_buffer *eb) { } | |
177 | static void btrfs_assert_no_spinning_writers(struct extent_buffer *eb) { } | |
225948de DS |
178 | static void btrfs_assert_spinning_readers_put(struct extent_buffer *eb) { } |
179 | static void btrfs_assert_spinning_readers_get(struct extent_buffer *eb) { } | |
58a2ddae DS |
180 | static void btrfs_assert_tree_read_locked(struct extent_buffer *eb) { } |
181 | static void btrfs_assert_tree_read_locks_get(struct extent_buffer *eb) { } | |
182 | static void btrfs_assert_tree_read_locks_put(struct extent_buffer *eb) { } | |
e3f15388 DS |
183 | static void btrfs_assert_tree_write_locks_get(struct extent_buffer *eb) { } |
184 | static void btrfs_assert_tree_write_locks_put(struct extent_buffer *eb) { } | |
e4e9fd0f DS |
185 | #endif |
186 | ||
d4e253bb DS |
187 | /* |
188 | * Mark already held read lock as blocking. Can be nested in write lock by the | |
189 | * same thread. | |
190 | * | |
191 | * Use when there are potentially long operations ahead so other thread waiting | |
192 | * on the lock will not actively spin but sleep instead. | |
193 | * | |
194 | * The rwlock is released and blocking reader counter is increased. | |
195 | */ | |
b95be2d9 DS |
196 | void btrfs_set_lock_blocking_read(struct extent_buffer *eb) |
197 | { | |
31aab402 | 198 | trace_btrfs_set_lock_blocking_read(eb); |
b95be2d9 DS |
199 | /* |
200 | * No lock is required. The lock owner may change if we have a read | |
201 | * lock, but it won't change to or away from us. If we have the write | |
202 | * lock, we are the owner and it'll never change. | |
203 | */ | |
204 | if (eb->lock_nested && current->pid == eb->lock_owner) | |
205 | return; | |
206 | btrfs_assert_tree_read_locked(eb); | |
207 | atomic_inc(&eb->blocking_readers); | |
afd495a8 | 208 | btrfs_assert_spinning_readers_put(eb); |
b95be2d9 DS |
209 | read_unlock(&eb->lock); |
210 | } | |
211 | ||
d4e253bb DS |
212 | /* |
213 | * Mark already held write lock as blocking. | |
214 | * | |
215 | * Use when there are potentially long operations ahead so other threads | |
216 | * waiting on the lock will not actively spin but sleep instead. | |
217 | * | |
218 | * The rwlock is released and blocking writers is set. | |
219 | */ | |
b95be2d9 | 220 | void btrfs_set_lock_blocking_write(struct extent_buffer *eb) |
925baedd | 221 | { |
31aab402 | 222 | trace_btrfs_set_lock_blocking_write(eb); |
ea4ebde0 | 223 | /* |
b95be2d9 DS |
224 | * No lock is required. The lock owner may change if we have a read |
225 | * lock, but it won't change to or away from us. If we have the write | |
226 | * lock, we are the owner and it'll never change. | |
ea4ebde0 CM |
227 | */ |
228 | if (eb->lock_nested && current->pid == eb->lock_owner) | |
229 | return; | |
06297d8c | 230 | if (eb->blocking_writers == 0) { |
843ccf9f | 231 | btrfs_assert_spinning_writers_put(eb); |
b95be2d9 | 232 | btrfs_assert_tree_locked(eb); |
a4477988 | 233 | WRITE_ONCE(eb->blocking_writers, 1); |
b95be2d9 | 234 | write_unlock(&eb->lock); |
b4ce94de | 235 | } |
b4ce94de | 236 | } |
f9efa9c7 | 237 | |
b4ce94de | 238 | /* |
d4e253bb DS |
239 | * Lock the extent buffer for read. Wait for any writers (spinning or blocking). |
240 | * Can be nested in write lock by the same thread. | |
241 | * | |
242 | * Use when the locked section does only lightweight actions and busy waiting | |
243 | * would be cheaper than making other threads do the wait/wake loop. | |
244 | * | |
245 | * The rwlock is held upon exit. | |
b4ce94de | 246 | */ |
bd681513 | 247 | void btrfs_tree_read_lock(struct extent_buffer *eb) |
b4ce94de | 248 | { |
34e73cc9 QW |
249 | u64 start_ns = 0; |
250 | ||
251 | if (trace_btrfs_tree_read_lock_enabled()) | |
252 | start_ns = ktime_get_ns(); | |
bd681513 | 253 | again: |
5b25f70f | 254 | read_lock(&eb->lock); |
06297d8c DS |
255 | BUG_ON(eb->blocking_writers == 0 && |
256 | current->pid == eb->lock_owner); | |
06297d8c | 257 | if (eb->blocking_writers) { |
f5c2a525 DS |
258 | if (current->pid == eb->lock_owner) { |
259 | /* | |
260 | * This extent is already write-locked by our thread. | |
261 | * We allow an additional read lock to be added because | |
262 | * it's for the same thread. btrfs_find_all_roots() | |
263 | * depends on this as it may be called on a partly | |
264 | * (write-)locked tree. | |
265 | */ | |
266 | BUG_ON(eb->lock_nested); | |
267 | eb->lock_nested = true; | |
268 | read_unlock(&eb->lock); | |
269 | trace_btrfs_tree_read_lock(eb, start_ns); | |
270 | return; | |
271 | } | |
bd681513 | 272 | read_unlock(&eb->lock); |
39f9d028 | 273 | wait_event(eb->write_lock_wq, |
a4477988 | 274 | READ_ONCE(eb->blocking_writers) == 0); |
bd681513 | 275 | goto again; |
b4ce94de | 276 | } |
5c9c799a | 277 | btrfs_assert_tree_read_locks_get(eb); |
afd495a8 | 278 | btrfs_assert_spinning_readers_get(eb); |
34e73cc9 | 279 | trace_btrfs_tree_read_lock(eb, start_ns); |
b4ce94de CM |
280 | } |
281 | ||
f82c458a | 282 | /* |
d4e253bb DS |
283 | * Lock extent buffer for read, optimistically expecting that there are no |
284 | * contending blocking writers. If there are, don't wait. | |
285 | * | |
286 | * Return 1 if the rwlock has been taken, 0 otherwise | |
f82c458a CM |
287 | */ |
288 | int btrfs_tree_read_lock_atomic(struct extent_buffer *eb) | |
289 | { | |
a4477988 | 290 | if (READ_ONCE(eb->blocking_writers)) |
f82c458a CM |
291 | return 0; |
292 | ||
293 | read_lock(&eb->lock); | |
a4477988 DS |
294 | /* Refetch value after lock */ |
295 | if (READ_ONCE(eb->blocking_writers)) { | |
f82c458a CM |
296 | read_unlock(&eb->lock); |
297 | return 0; | |
298 | } | |
5c9c799a | 299 | btrfs_assert_tree_read_locks_get(eb); |
afd495a8 | 300 | btrfs_assert_spinning_readers_get(eb); |
31aab402 | 301 | trace_btrfs_tree_read_lock_atomic(eb); |
f82c458a CM |
302 | return 1; |
303 | } | |
304 | ||
b4ce94de | 305 | /* |
d4e253bb DS |
306 | * Try-lock for read. Don't block or wait for contending writers. |
307 | * | |
308 | * Retrun 1 if the rwlock has been taken, 0 otherwise | |
b4ce94de | 309 | */ |
bd681513 | 310 | int btrfs_try_tree_read_lock(struct extent_buffer *eb) |
b4ce94de | 311 | { |
a4477988 | 312 | if (READ_ONCE(eb->blocking_writers)) |
bd681513 | 313 | return 0; |
b4ce94de | 314 | |
ea4ebde0 CM |
315 | if (!read_trylock(&eb->lock)) |
316 | return 0; | |
317 | ||
a4477988 DS |
318 | /* Refetch value after lock */ |
319 | if (READ_ONCE(eb->blocking_writers)) { | |
bd681513 CM |
320 | read_unlock(&eb->lock); |
321 | return 0; | |
b9473439 | 322 | } |
5c9c799a | 323 | btrfs_assert_tree_read_locks_get(eb); |
afd495a8 | 324 | btrfs_assert_spinning_readers_get(eb); |
31aab402 | 325 | trace_btrfs_try_tree_read_lock(eb); |
bd681513 | 326 | return 1; |
b4ce94de CM |
327 | } |
328 | ||
329 | /* | |
d4e253bb DS |
330 | * Try-lock for write. May block until the lock is uncontended, but does not |
331 | * wait until it is free. | |
332 | * | |
333 | * Retrun 1 if the rwlock has been taken, 0 otherwise | |
b4ce94de | 334 | */ |
bd681513 | 335 | int btrfs_try_tree_write_lock(struct extent_buffer *eb) |
b4ce94de | 336 | { |
a4477988 | 337 | if (READ_ONCE(eb->blocking_writers) || atomic_read(&eb->blocking_readers)) |
bd681513 | 338 | return 0; |
ea4ebde0 | 339 | |
f82c458a | 340 | write_lock(&eb->lock); |
a4477988 DS |
341 | /* Refetch value after lock */ |
342 | if (READ_ONCE(eb->blocking_writers) || atomic_read(&eb->blocking_readers)) { | |
bd681513 CM |
343 | write_unlock(&eb->lock); |
344 | return 0; | |
345 | } | |
c79adfc0 | 346 | btrfs_assert_tree_write_locks_get(eb); |
843ccf9f | 347 | btrfs_assert_spinning_writers_get(eb); |
5b25f70f | 348 | eb->lock_owner = current->pid; |
31aab402 | 349 | trace_btrfs_try_tree_write_lock(eb); |
b4ce94de CM |
350 | return 1; |
351 | } | |
352 | ||
353 | /* | |
d4e253bb DS |
354 | * Release read lock. Must be used only if the lock is in spinning mode. If |
355 | * the read lock is nested, must pair with read lock before the write unlock. | |
356 | * | |
357 | * The rwlock is not held upon exit. | |
bd681513 CM |
358 | */ |
359 | void btrfs_tree_read_unlock(struct extent_buffer *eb) | |
360 | { | |
31aab402 | 361 | trace_btrfs_tree_read_unlock(eb); |
ea4ebde0 CM |
362 | /* |
363 | * if we're nested, we have the write lock. No new locking | |
364 | * is needed as long as we are the lock owner. | |
365 | * The write unlock will do a barrier for us, and the lock_nested | |
366 | * field only matters to the lock owner. | |
367 | */ | |
368 | if (eb->lock_nested && current->pid == eb->lock_owner) { | |
ed1b4ed7 | 369 | eb->lock_nested = false; |
ea4ebde0 | 370 | return; |
5b25f70f | 371 | } |
bd681513 | 372 | btrfs_assert_tree_read_locked(eb); |
afd495a8 | 373 | btrfs_assert_spinning_readers_put(eb); |
5c9c799a | 374 | btrfs_assert_tree_read_locks_put(eb); |
bd681513 CM |
375 | read_unlock(&eb->lock); |
376 | } | |
377 | ||
378 | /* | |
d4e253bb DS |
379 | * Release read lock, previously set to blocking by a pairing call to |
380 | * btrfs_set_lock_blocking_read(). Can be nested in write lock by the same | |
381 | * thread. | |
382 | * | |
383 | * State of rwlock is unchanged, last reader wakes waiting threads. | |
bd681513 CM |
384 | */ |
385 | void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb) | |
386 | { | |
31aab402 | 387 | trace_btrfs_tree_read_unlock_blocking(eb); |
ea4ebde0 CM |
388 | /* |
389 | * if we're nested, we have the write lock. No new locking | |
390 | * is needed as long as we are the lock owner. | |
391 | * The write unlock will do a barrier for us, and the lock_nested | |
392 | * field only matters to the lock owner. | |
393 | */ | |
394 | if (eb->lock_nested && current->pid == eb->lock_owner) { | |
ed1b4ed7 | 395 | eb->lock_nested = false; |
ea4ebde0 | 396 | return; |
5b25f70f | 397 | } |
bd681513 CM |
398 | btrfs_assert_tree_read_locked(eb); |
399 | WARN_ON(atomic_read(&eb->blocking_readers) == 0); | |
093258e6 DS |
400 | /* atomic_dec_and_test implies a barrier */ |
401 | if (atomic_dec_and_test(&eb->blocking_readers)) | |
402 | cond_wake_up_nomb(&eb->read_lock_wq); | |
5c9c799a | 403 | btrfs_assert_tree_read_locks_put(eb); |
bd681513 CM |
404 | } |
405 | ||
406 | /* | |
d4e253bb DS |
407 | * Lock for write. Wait for all blocking and spinning readers and writers. This |
408 | * starts context where reader lock could be nested by the same thread. | |
409 | * | |
410 | * The rwlock is held for write upon exit. | |
b4ce94de | 411 | */ |
143bede5 | 412 | void btrfs_tree_lock(struct extent_buffer *eb) |
b4ce94de | 413 | { |
34e73cc9 QW |
414 | u64 start_ns = 0; |
415 | ||
416 | if (trace_btrfs_tree_lock_enabled()) | |
417 | start_ns = ktime_get_ns(); | |
418 | ||
166f66d0 | 419 | WARN_ON(eb->lock_owner == current->pid); |
bd681513 CM |
420 | again: |
421 | wait_event(eb->read_lock_wq, atomic_read(&eb->blocking_readers) == 0); | |
a4477988 | 422 | wait_event(eb->write_lock_wq, READ_ONCE(eb->blocking_writers) == 0); |
bd681513 | 423 | write_lock(&eb->lock); |
a4477988 DS |
424 | /* Refetch value after lock */ |
425 | if (atomic_read(&eb->blocking_readers) || | |
426 | READ_ONCE(eb->blocking_writers)) { | |
bd681513 | 427 | write_unlock(&eb->lock); |
bd681513 CM |
428 | goto again; |
429 | } | |
843ccf9f | 430 | btrfs_assert_spinning_writers_get(eb); |
c79adfc0 | 431 | btrfs_assert_tree_write_locks_get(eb); |
5b25f70f | 432 | eb->lock_owner = current->pid; |
34e73cc9 | 433 | trace_btrfs_tree_lock(eb, start_ns); |
925baedd CM |
434 | } |
435 | ||
bd681513 | 436 | /* |
d4e253bb DS |
437 | * Release the write lock, either blocking or spinning (ie. there's no need |
438 | * for an explicit blocking unlock, like btrfs_tree_read_unlock_blocking). | |
439 | * This also ends the context for nesting, the read lock must have been | |
440 | * released already. | |
441 | * | |
442 | * Tasks blocked and waiting are woken, rwlock is not held upon exit. | |
bd681513 | 443 | */ |
143bede5 | 444 | void btrfs_tree_unlock(struct extent_buffer *eb) |
925baedd | 445 | { |
a4477988 DS |
446 | /* |
447 | * This is read both locked and unlocked but always by the same thread | |
448 | * that already owns the lock so we don't need to use READ_ONCE | |
449 | */ | |
06297d8c | 450 | int blockers = eb->blocking_writers; |
bd681513 CM |
451 | |
452 | BUG_ON(blockers > 1); | |
453 | ||
454 | btrfs_assert_tree_locked(eb); | |
31aab402 | 455 | trace_btrfs_tree_unlock(eb); |
ea4ebde0 | 456 | eb->lock_owner = 0; |
c79adfc0 | 457 | btrfs_assert_tree_write_locks_put(eb); |
bd681513 CM |
458 | |
459 | if (blockers) { | |
843ccf9f | 460 | btrfs_assert_no_spinning_writers(eb); |
a4477988 DS |
461 | /* Unlocked write */ |
462 | WRITE_ONCE(eb->blocking_writers, 0); | |
6e7ca09b NB |
463 | /* |
464 | * We need to order modifying blocking_writers above with | |
465 | * actually waking up the sleepers to ensure they see the | |
466 | * updated value of blocking_writers | |
467 | */ | |
468 | cond_wake_up(&eb->write_lock_wq); | |
bd681513 | 469 | } else { |
843ccf9f | 470 | btrfs_assert_spinning_writers_put(eb); |
bd681513 CM |
471 | write_unlock(&eb->lock); |
472 | } | |
925baedd | 473 | } |
ed2b1d36 DS |
474 | |
475 | /* | |
476 | * Set all locked nodes in the path to blocking locks. This should be done | |
477 | * before scheduling | |
478 | */ | |
479 | void btrfs_set_path_blocking(struct btrfs_path *p) | |
480 | { | |
481 | int i; | |
482 | ||
483 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | |
484 | if (!p->nodes[i] || !p->locks[i]) | |
485 | continue; | |
486 | /* | |
487 | * If we currently have a spinning reader or writer lock this | |
488 | * will bump the count of blocking holders and drop the | |
489 | * spinlock. | |
490 | */ | |
491 | if (p->locks[i] == BTRFS_READ_LOCK) { | |
492 | btrfs_set_lock_blocking_read(p->nodes[i]); | |
493 | p->locks[i] = BTRFS_READ_LOCK_BLOCKING; | |
494 | } else if (p->locks[i] == BTRFS_WRITE_LOCK) { | |
495 | btrfs_set_lock_blocking_write(p->nodes[i]); | |
496 | p->locks[i] = BTRFS_WRITE_LOCK_BLOCKING; | |
497 | } | |
498 | } | |
499 | } | |
1f95ec01 DS |
500 | |
501 | /* | |
502 | * This releases any locks held in the path starting at level and going all the | |
503 | * way up to the root. | |
504 | * | |
505 | * btrfs_search_slot will keep the lock held on higher nodes in a few corner | |
506 | * cases, such as COW of the block at slot zero in the node. This ignores | |
507 | * those rules, and it should only be called when there are no more updates to | |
508 | * be done higher up in the tree. | |
509 | */ | |
510 | void btrfs_unlock_up_safe(struct btrfs_path *path, int level) | |
511 | { | |
512 | int i; | |
513 | ||
514 | if (path->keep_locks) | |
515 | return; | |
516 | ||
517 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | |
518 | if (!path->nodes[i]) | |
519 | continue; | |
520 | if (!path->locks[i]) | |
521 | continue; | |
522 | btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]); | |
523 | path->locks[i] = 0; | |
524 | } | |
525 | } | |
b908c334 DS |
526 | |
527 | /* | |
528 | * Loop around taking references on and locking the root node of the tree until | |
529 | * we end up with a lock on the root node. | |
530 | * | |
531 | * Return: root extent buffer with write lock held | |
532 | */ | |
533 | struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) | |
534 | { | |
535 | struct extent_buffer *eb; | |
536 | ||
537 | while (1) { | |
538 | eb = btrfs_root_node(root); | |
539 | btrfs_tree_lock(eb); | |
540 | if (eb == root->node) | |
541 | break; | |
542 | btrfs_tree_unlock(eb); | |
543 | free_extent_buffer(eb); | |
544 | } | |
545 | return eb; | |
546 | } | |
547 | ||
548 | /* | |
549 | * Loop around taking references on and locking the root node of the tree until | |
550 | * we end up with a lock on the root node. | |
551 | * | |
552 | * Return: root extent buffer with read lock held | |
553 | */ | |
554 | struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) | |
555 | { | |
556 | struct extent_buffer *eb; | |
557 | ||
558 | while (1) { | |
559 | eb = btrfs_root_node(root); | |
560 | btrfs_tree_read_lock(eb); | |
561 | if (eb == root->node) | |
562 | break; | |
563 | btrfs_tree_read_unlock(eb); | |
564 | free_extent_buffer(eb); | |
565 | } | |
566 | return eb; | |
567 | } |