xref: /openbmc/linux/fs/btrfs/locking.c (revision 1a1b0e72)
1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0
2925baeddSChris Mason /*
3925baeddSChris Mason  * Copyright (C) 2008 Oracle.  All rights reserved.
4925baeddSChris Mason  */
5c1d7c514SDavid Sterba 
6925baeddSChris Mason #include <linux/sched.h>
7925baeddSChris Mason #include <linux/pagemap.h>
8925baeddSChris Mason #include <linux/spinlock.h>
9925baeddSChris Mason #include <linux/page-flags.h>
104881ee5aSChris Mason #include <asm/bug.h>
11602cbe91SDavid Sterba #include "misc.h"
12925baeddSChris Mason #include "ctree.h"
13925baeddSChris Mason #include "extent_io.h"
14925baeddSChris Mason #include "locking.h"
1507e81dc9SJosef Bacik #include "accessors.h"
16925baeddSChris Mason 
17d4e253bbSDavid Sterba /*
180a27a047SJosef Bacik  * Lockdep class keys for extent_buffer->lock's in this root.  For a given
190a27a047SJosef Bacik  * eb, the lockdep key is determined by the btrfs_root it belongs to and
200a27a047SJosef Bacik  * the level the eb occupies in the tree.
210a27a047SJosef Bacik  *
220a27a047SJosef Bacik  * Different roots are used for different purposes and may nest inside each
230a27a047SJosef Bacik  * other and they require separate keysets.  As lockdep keys should be
240a27a047SJosef Bacik  * static, assign keysets according to the purpose of the root as indicated
250a27a047SJosef Bacik  * by btrfs_root->root_key.objectid.  This ensures that all special purpose
260a27a047SJosef Bacik  * roots have separate keysets.
270a27a047SJosef Bacik  *
280a27a047SJosef Bacik  * Lock-nesting across peer nodes is always done with the immediate parent
290a27a047SJosef Bacik  * node locked thus preventing deadlock.  As lockdep doesn't know this, use
300a27a047SJosef Bacik  * subclass to avoid triggering lockdep warning in such cases.
310a27a047SJosef Bacik  *
320a27a047SJosef Bacik  * The key is set by the readpage_end_io_hook after the buffer has passed
330a27a047SJosef Bacik  * csum validation but before the pages are unlocked.  It is also set by
340a27a047SJosef Bacik  * btrfs_init_new_buffer on freshly allocated blocks.
350a27a047SJosef Bacik  *
360a27a047SJosef Bacik  * We also add a check to make sure the highest level of the tree is the
370a27a047SJosef Bacik  * same as our lockdep setup here.  If BTRFS_MAX_LEVEL changes, this code
380a27a047SJosef Bacik  * needs update as well.
390a27a047SJosef Bacik  */
400a27a047SJosef Bacik #ifdef CONFIG_DEBUG_LOCK_ALLOC
410a27a047SJosef Bacik #if BTRFS_MAX_LEVEL != 8
420a27a047SJosef Bacik #error
430a27a047SJosef Bacik #endif
440a27a047SJosef Bacik 
450a27a047SJosef Bacik #define DEFINE_LEVEL(stem, level)					\
460a27a047SJosef Bacik 	.names[level] = "btrfs-" stem "-0" #level,
470a27a047SJosef Bacik 
480a27a047SJosef Bacik #define DEFINE_NAME(stem)						\
490a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 0)						\
500a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 1)						\
510a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 2)						\
520a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 3)						\
530a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 4)						\
540a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 5)						\
550a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 6)						\
560a27a047SJosef Bacik 	DEFINE_LEVEL(stem, 7)
570a27a047SJosef Bacik 
580a27a047SJosef Bacik static struct btrfs_lockdep_keyset {
590a27a047SJosef Bacik 	u64			id;		/* root objectid */
60*1a1b0e72SDavid Sterba 	/* Longest entry: btrfs-block-group-00 */
61*1a1b0e72SDavid Sterba 	char			names[BTRFS_MAX_LEVEL][24];
620a27a047SJosef Bacik 	struct lock_class_key	keys[BTRFS_MAX_LEVEL];
630a27a047SJosef Bacik } btrfs_lockdep_keysets[] = {
640a27a047SJosef Bacik 	{ .id = BTRFS_ROOT_TREE_OBJECTID,	DEFINE_NAME("root")	},
650a27a047SJosef Bacik 	{ .id = BTRFS_EXTENT_TREE_OBJECTID,	DEFINE_NAME("extent")	},
660a27a047SJosef Bacik 	{ .id = BTRFS_CHUNK_TREE_OBJECTID,	DEFINE_NAME("chunk")	},
670a27a047SJosef Bacik 	{ .id = BTRFS_DEV_TREE_OBJECTID,	DEFINE_NAME("dev")	},
680a27a047SJosef Bacik 	{ .id = BTRFS_CSUM_TREE_OBJECTID,	DEFINE_NAME("csum")	},
690a27a047SJosef Bacik 	{ .id = BTRFS_QUOTA_TREE_OBJECTID,	DEFINE_NAME("quota")	},
700a27a047SJosef Bacik 	{ .id = BTRFS_TREE_LOG_OBJECTID,	DEFINE_NAME("log")	},
710a27a047SJosef Bacik 	{ .id = BTRFS_TREE_RELOC_OBJECTID,	DEFINE_NAME("treloc")	},
720a27a047SJosef Bacik 	{ .id = BTRFS_DATA_RELOC_TREE_OBJECTID,	DEFINE_NAME("dreloc")	},
730a27a047SJosef Bacik 	{ .id = BTRFS_UUID_TREE_OBJECTID,	DEFINE_NAME("uuid")	},
740a27a047SJosef Bacik 	{ .id = BTRFS_FREE_SPACE_TREE_OBJECTID,	DEFINE_NAME("free-space") },
75*1a1b0e72SDavid Sterba 	{ .id = BTRFS_BLOCK_GROUP_TREE_OBJECTID, DEFINE_NAME("block-group") },
760a27a047SJosef Bacik 	{ .id = 0,				DEFINE_NAME("tree")	},
770a27a047SJosef Bacik };
780a27a047SJosef Bacik 
790a27a047SJosef Bacik #undef DEFINE_LEVEL
800a27a047SJosef Bacik #undef DEFINE_NAME
810a27a047SJosef Bacik 
btrfs_set_buffer_lockdep_class(u64 objectid,struct extent_buffer * eb,int level)820a27a047SJosef Bacik void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int level)
830a27a047SJosef Bacik {
840a27a047SJosef Bacik 	struct btrfs_lockdep_keyset *ks;
850a27a047SJosef Bacik 
860a27a047SJosef Bacik 	BUG_ON(level >= ARRAY_SIZE(ks->keys));
870a27a047SJosef Bacik 
880a27a047SJosef Bacik 	/* Find the matching keyset, id 0 is the default entry */
890a27a047SJosef Bacik 	for (ks = btrfs_lockdep_keysets; ks->id; ks++)
900a27a047SJosef Bacik 		if (ks->id == objectid)
910a27a047SJosef Bacik 			break;
920a27a047SJosef Bacik 
930a27a047SJosef Bacik 	lockdep_set_class_and_name(&eb->lock, &ks->keys[level], ks->names[level]);
940a27a047SJosef Bacik }
950a27a047SJosef Bacik 
btrfs_maybe_reset_lockdep_class(struct btrfs_root * root,struct extent_buffer * eb)96b40130b2SJosef Bacik void btrfs_maybe_reset_lockdep_class(struct btrfs_root *root, struct extent_buffer *eb)
97b40130b2SJosef Bacik {
98b40130b2SJosef Bacik 	if (test_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &root->state))
99b40130b2SJosef Bacik 		btrfs_set_buffer_lockdep_class(root->root_key.objectid,
100b40130b2SJosef Bacik 					       eb, btrfs_header_level(eb));
101b40130b2SJosef Bacik }
102b40130b2SJosef Bacik 
1030a27a047SJosef Bacik #endif
1040a27a047SJosef Bacik 
1050a27a047SJosef Bacik /*
106d4e253bbSDavid Sterba  * Extent buffer locking
107d4e253bbSDavid Sterba  * =====================
108d4e253bbSDavid Sterba  *
109196d59abSJosef Bacik  * We use a rw_semaphore for tree locking, and the semantics are exactly the
110196d59abSJosef Bacik  * same:
111d4e253bbSDavid Sterba  *
112d4e253bbSDavid Sterba  * - reader/writer exclusion
113d4e253bbSDavid Sterba  * - writer/writer exclusion
114d4e253bbSDavid Sterba  * - reader/reader sharing
115d4e253bbSDavid Sterba  * - try-lock semantics for readers and writers
116d4e253bbSDavid Sterba  *
1174048daedSJosef Bacik  * The rwsem implementation does opportunistic spinning which reduces number of
1184048daedSJosef Bacik  * times the locking task needs to sleep.
119d4e253bbSDavid Sterba  */
120d4e253bbSDavid Sterba 
121d4e253bbSDavid Sterba /*
122196d59abSJosef Bacik  * __btrfs_tree_read_lock - lock extent buffer for read
123196d59abSJosef Bacik  * @eb:		the eb to be locked
124196d59abSJosef Bacik  * @nest:	the nesting level to be used for lockdep
125d4e253bbSDavid Sterba  *
126196d59abSJosef Bacik  * This takes the read lock on the extent buffer, using the specified nesting
127196d59abSJosef Bacik  * level for lockdep purposes.
128b4ce94deSChris Mason  */
__btrfs_tree_read_lock(struct extent_buffer * eb,enum btrfs_lock_nesting nest)1290ecae6ffSJosef Bacik void __btrfs_tree_read_lock(struct extent_buffer *eb, enum btrfs_lock_nesting nest)
130b4ce94deSChris Mason {
13134e73cc9SQu Wenruo 	u64 start_ns = 0;
13234e73cc9SQu Wenruo 
13334e73cc9SQu Wenruo 	if (trace_btrfs_tree_read_lock_enabled())
13434e73cc9SQu Wenruo 		start_ns = ktime_get_ns();
135196d59abSJosef Bacik 
136196d59abSJosef Bacik 	down_read_nested(&eb->lock, nest);
13734e73cc9SQu Wenruo 	trace_btrfs_tree_read_lock(eb, start_ns);
138b4ce94deSChris Mason }
139b4ce94deSChris Mason 
btrfs_tree_read_lock(struct extent_buffer * eb)14051899412SJosef Bacik void btrfs_tree_read_lock(struct extent_buffer *eb)
14151899412SJosef Bacik {
1420ecae6ffSJosef Bacik 	__btrfs_tree_read_lock(eb, BTRFS_NESTING_NORMAL);
14351899412SJosef Bacik }
14451899412SJosef Bacik 
145b4ce94deSChris Mason /*
146196d59abSJosef Bacik  * Try-lock for read.
147d4e253bbSDavid Sterba  *
1481a9fd417SDavid Sterba  * Return 1 if the rwlock has been taken, 0 otherwise
149b4ce94deSChris Mason  */
btrfs_try_tree_read_lock(struct extent_buffer * eb)150bd681513SChris Mason int btrfs_try_tree_read_lock(struct extent_buffer *eb)
151b4ce94deSChris Mason {
152196d59abSJosef Bacik 	if (down_read_trylock(&eb->lock)) {
15331aab402SQu Wenruo 		trace_btrfs_try_tree_read_lock(eb);
154bd681513SChris Mason 		return 1;
155bd681513SChris Mason 	}
156196d59abSJosef Bacik 	return 0;
157196d59abSJosef Bacik }
158b4ce94deSChris Mason 
159b4ce94deSChris Mason /*
160196d59abSJosef Bacik  * Try-lock for write.
161d4e253bbSDavid Sterba  *
1621a9fd417SDavid Sterba  * Return 1 if the rwlock has been taken, 0 otherwise
163b4ce94deSChris Mason  */
btrfs_try_tree_write_lock(struct extent_buffer * eb)164bd681513SChris Mason int btrfs_try_tree_write_lock(struct extent_buffer *eb)
165925baeddSChris Mason {
166196d59abSJosef Bacik 	if (down_write_trylock(&eb->lock)) {
1675b25f70fSArne Jansen 		eb->lock_owner = current->pid;
16831aab402SQu Wenruo 		trace_btrfs_try_tree_write_lock(eb);
169b4ce94deSChris Mason 		return 1;
170b4ce94deSChris Mason 	}
171196d59abSJosef Bacik 	return 0;
172196d59abSJosef Bacik }
173b4ce94deSChris Mason 
174b4ce94deSChris Mason /*
1754048daedSJosef Bacik  * Release read lock.
176bd681513SChris Mason  */
btrfs_tree_read_unlock(struct extent_buffer * eb)177bd681513SChris Mason void btrfs_tree_read_unlock(struct extent_buffer *eb)
178bd681513SChris Mason {
17931aab402SQu Wenruo 	trace_btrfs_tree_read_unlock(eb);
180196d59abSJosef Bacik 	up_read(&eb->lock);
181bd681513SChris Mason }
182bd681513SChris Mason 
183bd681513SChris Mason /*
184196d59abSJosef Bacik  * __btrfs_tree_lock - lock eb for write
185196d59abSJosef Bacik  * @eb:		the eb to lock
186196d59abSJosef Bacik  * @nest:	the nesting to use for the lock
187d4e253bbSDavid Sterba  *
188196d59abSJosef Bacik  * Returns with the eb->lock write locked.
189b4ce94deSChris Mason  */
__btrfs_tree_lock(struct extent_buffer * eb,enum btrfs_lock_nesting nest)190fd7ba1c1SJosef Bacik void __btrfs_tree_lock(struct extent_buffer *eb, enum btrfs_lock_nesting nest)
19178d933c7SJules Irenge 	__acquires(&eb->lock)
192b4ce94deSChris Mason {
19334e73cc9SQu Wenruo 	u64 start_ns = 0;
19434e73cc9SQu Wenruo 
19534e73cc9SQu Wenruo 	if (trace_btrfs_tree_lock_enabled())
19634e73cc9SQu Wenruo 		start_ns = ktime_get_ns();
19734e73cc9SQu Wenruo 
198196d59abSJosef Bacik 	down_write_nested(&eb->lock, nest);
1995b25f70fSArne Jansen 	eb->lock_owner = current->pid;
20034e73cc9SQu Wenruo 	trace_btrfs_tree_lock(eb, start_ns);
201b4ce94deSChris Mason }
202b4ce94deSChris Mason 
btrfs_tree_lock(struct extent_buffer * eb)203fd7ba1c1SJosef Bacik void btrfs_tree_lock(struct extent_buffer *eb)
204fd7ba1c1SJosef Bacik {
205fd7ba1c1SJosef Bacik 	__btrfs_tree_lock(eb, BTRFS_NESTING_NORMAL);
206fd7ba1c1SJosef Bacik }
207fd7ba1c1SJosef Bacik 
208bd681513SChris Mason /*
209196d59abSJosef Bacik  * Release the write lock.
210bd681513SChris Mason  */
btrfs_tree_unlock(struct extent_buffer * eb)211143bede5SJeff Mahoney void btrfs_tree_unlock(struct extent_buffer *eb)
212925baeddSChris Mason {
21331aab402SQu Wenruo 	trace_btrfs_tree_unlock(eb);
214ea4ebde0SChris Mason 	eb->lock_owner = 0;
215196d59abSJosef Bacik 	up_write(&eb->lock);
216925baeddSChris Mason }
217ed2b1d36SDavid Sterba 
218ed2b1d36SDavid Sterba /*
2191f95ec01SDavid Sterba  * This releases any locks held in the path starting at level and going all the
2201f95ec01SDavid Sterba  * way up to the root.
2211f95ec01SDavid Sterba  *
2221f95ec01SDavid Sterba  * btrfs_search_slot will keep the lock held on higher nodes in a few corner
2231f95ec01SDavid Sterba  * cases, such as COW of the block at slot zero in the node.  This ignores
2241f95ec01SDavid Sterba  * those rules, and it should only be called when there are no more updates to
2251f95ec01SDavid Sterba  * be done higher up in the tree.
2261f95ec01SDavid Sterba  */
btrfs_unlock_up_safe(struct btrfs_path * path,int level)2271f95ec01SDavid Sterba void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
2281f95ec01SDavid Sterba {
2291f95ec01SDavid Sterba 	int i;
2301f95ec01SDavid Sterba 
2311f95ec01SDavid Sterba 	if (path->keep_locks)
2321f95ec01SDavid Sterba 		return;
2331f95ec01SDavid Sterba 
2341f95ec01SDavid Sterba 	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
2351f95ec01SDavid Sterba 		if (!path->nodes[i])
2361f95ec01SDavid Sterba 			continue;
2371f95ec01SDavid Sterba 		if (!path->locks[i])
2381f95ec01SDavid Sterba 			continue;
2391f95ec01SDavid Sterba 		btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
2401f95ec01SDavid Sterba 		path->locks[i] = 0;
2411f95ec01SDavid Sterba 	}
2421f95ec01SDavid Sterba }
243b908c334SDavid Sterba 
244b908c334SDavid Sterba /*
245b908c334SDavid Sterba  * Loop around taking references on and locking the root node of the tree until
246b908c334SDavid Sterba  * we end up with a lock on the root node.
247b908c334SDavid Sterba  *
248b908c334SDavid Sterba  * Return: root extent buffer with write lock held
249b908c334SDavid Sterba  */
btrfs_lock_root_node(struct btrfs_root * root)250b908c334SDavid Sterba struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
251b908c334SDavid Sterba {
252b908c334SDavid Sterba 	struct extent_buffer *eb;
253b908c334SDavid Sterba 
254b908c334SDavid Sterba 	while (1) {
255b908c334SDavid Sterba 		eb = btrfs_root_node(root);
256b40130b2SJosef Bacik 
257b40130b2SJosef Bacik 		btrfs_maybe_reset_lockdep_class(root, eb);
258b908c334SDavid Sterba 		btrfs_tree_lock(eb);
259b908c334SDavid Sterba 		if (eb == root->node)
260b908c334SDavid Sterba 			break;
261b908c334SDavid Sterba 		btrfs_tree_unlock(eb);
262b908c334SDavid Sterba 		free_extent_buffer(eb);
263b908c334SDavid Sterba 	}
264b908c334SDavid Sterba 	return eb;
265b908c334SDavid Sterba }
266b908c334SDavid Sterba 
267b908c334SDavid Sterba /*
268b908c334SDavid Sterba  * Loop around taking references on and locking the root node of the tree until
269b908c334SDavid Sterba  * we end up with a lock on the root node.
270b908c334SDavid Sterba  *
271b908c334SDavid Sterba  * Return: root extent buffer with read lock held
272b908c334SDavid Sterba  */
btrfs_read_lock_root_node(struct btrfs_root * root)2731bb96598SJosef Bacik struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
274b908c334SDavid Sterba {
275b908c334SDavid Sterba 	struct extent_buffer *eb;
276b908c334SDavid Sterba 
277b908c334SDavid Sterba 	while (1) {
278b908c334SDavid Sterba 		eb = btrfs_root_node(root);
279b40130b2SJosef Bacik 
280b40130b2SJosef Bacik 		btrfs_maybe_reset_lockdep_class(root, eb);
2811bb96598SJosef Bacik 		btrfs_tree_read_lock(eb);
282b908c334SDavid Sterba 		if (eb == root->node)
283b908c334SDavid Sterba 			break;
284b908c334SDavid Sterba 		btrfs_tree_read_unlock(eb);
285b908c334SDavid Sterba 		free_extent_buffer(eb);
286b908c334SDavid Sterba 	}
287b908c334SDavid Sterba 	return eb;
288b908c334SDavid Sterba }
2892992df73SNikolay Borisov 
2902992df73SNikolay Borisov /*
291857bc13fSJosef Bacik  * Loop around taking references on and locking the root node of the tree in
292857bc13fSJosef Bacik  * nowait mode until we end up with a lock on the root node or returning to
293857bc13fSJosef Bacik  * avoid blocking.
294857bc13fSJosef Bacik  *
295857bc13fSJosef Bacik  * Return: root extent buffer with read lock held or -EAGAIN.
296857bc13fSJosef Bacik  */
btrfs_try_read_lock_root_node(struct btrfs_root * root)297857bc13fSJosef Bacik struct extent_buffer *btrfs_try_read_lock_root_node(struct btrfs_root *root)
298857bc13fSJosef Bacik {
299857bc13fSJosef Bacik 	struct extent_buffer *eb;
300857bc13fSJosef Bacik 
301857bc13fSJosef Bacik 	while (1) {
302857bc13fSJosef Bacik 		eb = btrfs_root_node(root);
303857bc13fSJosef Bacik 		if (!btrfs_try_tree_read_lock(eb)) {
304857bc13fSJosef Bacik 			free_extent_buffer(eb);
305857bc13fSJosef Bacik 			return ERR_PTR(-EAGAIN);
306857bc13fSJosef Bacik 		}
307857bc13fSJosef Bacik 		if (eb == root->node)
308857bc13fSJosef Bacik 			break;
309857bc13fSJosef Bacik 		btrfs_tree_read_unlock(eb);
310857bc13fSJosef Bacik 		free_extent_buffer(eb);
311857bc13fSJosef Bacik 	}
312857bc13fSJosef Bacik 	return eb;
313857bc13fSJosef Bacik }
314857bc13fSJosef Bacik 
315857bc13fSJosef Bacik /*
3162992df73SNikolay Borisov  * DREW locks
3172992df73SNikolay Borisov  * ==========
3182992df73SNikolay Borisov  *
3192992df73SNikolay Borisov  * DREW stands for double-reader-writer-exclusion lock. It's used in situation
3202992df73SNikolay Borisov  * where you want to provide A-B exclusion but not AA or BB.
3212992df73SNikolay Borisov  *
3222992df73SNikolay Borisov  * Currently implementation gives more priority to reader. If a reader and a
3232992df73SNikolay Borisov  * writer both race to acquire their respective sides of the lock the writer
3242992df73SNikolay Borisov  * would yield its lock as soon as it detects a concurrent reader. Additionally
3252992df73SNikolay Borisov  * if there are pending readers no new writers would be allowed to come in and
3262992df73SNikolay Borisov  * acquire the lock.
3272992df73SNikolay Borisov  */
3282992df73SNikolay Borisov 
btrfs_drew_lock_init(struct btrfs_drew_lock * lock)3290b548539SDavid Sterba void btrfs_drew_lock_init(struct btrfs_drew_lock *lock)
3302992df73SNikolay Borisov {
3312992df73SNikolay Borisov 	atomic_set(&lock->readers, 0);
3320b548539SDavid Sterba 	atomic_set(&lock->writers, 0);
3332992df73SNikolay Borisov 	init_waitqueue_head(&lock->pending_readers);
3342992df73SNikolay Borisov 	init_waitqueue_head(&lock->pending_writers);
3352992df73SNikolay Borisov }
3362992df73SNikolay Borisov 
3372992df73SNikolay Borisov /* Return true if acquisition is successful, false otherwise */
btrfs_drew_try_write_lock(struct btrfs_drew_lock * lock)3382992df73SNikolay Borisov bool btrfs_drew_try_write_lock(struct btrfs_drew_lock *lock)
3392992df73SNikolay Borisov {
3402992df73SNikolay Borisov 	if (atomic_read(&lock->readers))
3412992df73SNikolay Borisov 		return false;
3422992df73SNikolay Borisov 
3430b548539SDavid Sterba 	atomic_inc(&lock->writers);
3442992df73SNikolay Borisov 
3452992df73SNikolay Borisov 	/* Ensure writers count is updated before we check for pending readers */
3460b548539SDavid Sterba 	smp_mb__after_atomic();
3472992df73SNikolay Borisov 	if (atomic_read(&lock->readers)) {
3482992df73SNikolay Borisov 		btrfs_drew_write_unlock(lock);
3492992df73SNikolay Borisov 		return false;
3502992df73SNikolay Borisov 	}
3512992df73SNikolay Borisov 
3522992df73SNikolay Borisov 	return true;
3532992df73SNikolay Borisov }
3542992df73SNikolay Borisov 
btrfs_drew_write_lock(struct btrfs_drew_lock * lock)3552992df73SNikolay Borisov void btrfs_drew_write_lock(struct btrfs_drew_lock *lock)
3562992df73SNikolay Borisov {
3572992df73SNikolay Borisov 	while (true) {
3582992df73SNikolay Borisov 		if (btrfs_drew_try_write_lock(lock))
3592992df73SNikolay Borisov 			return;
3602992df73SNikolay Borisov 		wait_event(lock->pending_writers, !atomic_read(&lock->readers));
3612992df73SNikolay Borisov 	}
3622992df73SNikolay Borisov }
3632992df73SNikolay Borisov 
btrfs_drew_write_unlock(struct btrfs_drew_lock * lock)3642992df73SNikolay Borisov void btrfs_drew_write_unlock(struct btrfs_drew_lock *lock)
3652992df73SNikolay Borisov {
3660b548539SDavid Sterba 	atomic_dec(&lock->writers);
3672992df73SNikolay Borisov 	cond_wake_up(&lock->pending_readers);
3682992df73SNikolay Borisov }
3692992df73SNikolay Borisov 
btrfs_drew_read_lock(struct btrfs_drew_lock * lock)3702992df73SNikolay Borisov void btrfs_drew_read_lock(struct btrfs_drew_lock *lock)
3712992df73SNikolay Borisov {
3722992df73SNikolay Borisov 	atomic_inc(&lock->readers);
3732992df73SNikolay Borisov 
3742992df73SNikolay Borisov 	/*
3752992df73SNikolay Borisov 	 * Ensure the pending reader count is perceieved BEFORE this reader
3762992df73SNikolay Borisov 	 * goes to sleep in case of active writers. This guarantees new writers
3772992df73SNikolay Borisov 	 * won't be allowed and that the current reader will be woken up when
3782992df73SNikolay Borisov 	 * the last active writer finishes its jobs.
3792992df73SNikolay Borisov 	 */
3802992df73SNikolay Borisov 	smp_mb__after_atomic();
3812992df73SNikolay Borisov 
3820b548539SDavid Sterba 	wait_event(lock->pending_readers, atomic_read(&lock->writers) == 0);
3832992df73SNikolay Borisov }
3842992df73SNikolay Borisov 
btrfs_drew_read_unlock(struct btrfs_drew_lock * lock)3852992df73SNikolay Borisov void btrfs_drew_read_unlock(struct btrfs_drew_lock *lock)
3862992df73SNikolay Borisov {
3872992df73SNikolay Borisov 	/*
3882992df73SNikolay Borisov 	 * atomic_dec_and_test implies a full barrier, so woken up writers
3892992df73SNikolay Borisov 	 * are guaranteed to see the decrement
3902992df73SNikolay Borisov 	 */
3912992df73SNikolay Borisov 	if (atomic_dec_and_test(&lock->readers))
3922992df73SNikolay Borisov 		wake_up(&lock->pending_writers);
3932992df73SNikolay Borisov }
394