]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/btree_locking.h
Rename from bcache-tools to bcachefs-tools
[bcachefs-tools-debian] / libbcachefs / btree_locking.h
1 #ifndef _BCACHE_BTREE_LOCKING_H
2 #define _BCACHE_BTREE_LOCKING_H
3
4 /*
5  * Only for internal btree use:
6  *
7  * The btree iterator tracks what locks it wants to take, and what locks it
8  * currently has - here we have wrappers for locking/unlocking btree nodes and
9  * updating the iterator state
10  */
11
12 #include "btree_iter.h"
13 #include "six.h"
14
15 /* matches six lock types */
16 enum btree_node_locked_type {
17         BTREE_NODE_UNLOCKED             = -1,
18         BTREE_NODE_READ_LOCKED          = SIX_LOCK_read,
19         BTREE_NODE_INTENT_LOCKED        = SIX_LOCK_intent,
20 };
21
22 static inline int btree_node_locked_type(struct btree_iter *iter,
23                                          unsigned level)
24 {
25         /*
26          * We're relying on the fact that if nodes_intent_locked is set
27          * nodes_locked must be set as well, so that we can compute without
28          * branches:
29          */
30         return BTREE_NODE_UNLOCKED +
31                 ((iter->nodes_locked >> level) & 1) +
32                 ((iter->nodes_intent_locked >> level) & 1);
33 }
34
35 static inline bool btree_node_intent_locked(struct btree_iter *iter,
36                                             unsigned level)
37 {
38         return btree_node_locked_type(iter, level) == BTREE_NODE_INTENT_LOCKED;
39 }
40
41 static inline bool btree_node_read_locked(struct btree_iter *iter,
42                                           unsigned level)
43 {
44         return btree_node_locked_type(iter, level) == BTREE_NODE_READ_LOCKED;
45 }
46
47 static inline bool btree_node_locked(struct btree_iter *iter, unsigned level)
48 {
49         return iter->nodes_locked & (1 << level);
50 }
51
52 static inline void mark_btree_node_unlocked(struct btree_iter *iter,
53                                             unsigned level)
54 {
55         iter->nodes_locked &= ~(1 << level);
56         iter->nodes_intent_locked &= ~(1 << level);
57 }
58
59 static inline void mark_btree_node_locked(struct btree_iter *iter,
60                                           unsigned level,
61                                           enum six_lock_type type)
62 {
63         /* relying on this to avoid a branch */
64         BUILD_BUG_ON(SIX_LOCK_read   != 0);
65         BUILD_BUG_ON(SIX_LOCK_intent != 1);
66
67         iter->nodes_locked |= 1 << level;
68         iter->nodes_intent_locked |= type << level;
69 }
70
71 static inline void mark_btree_node_intent_locked(struct btree_iter *iter,
72                                                  unsigned level)
73 {
74         mark_btree_node_locked(iter, level, SIX_LOCK_intent);
75 }
76
77 static inline enum six_lock_type
78 btree_lock_want(struct btree_iter *iter, int level)
79 {
80         return level < iter->locks_want
81                 ? SIX_LOCK_intent
82                 : SIX_LOCK_read;
83 }
84
85 static inline bool btree_want_intent(struct btree_iter *iter, int level)
86 {
87         return btree_lock_want(iter, level) == SIX_LOCK_intent;
88 }
89
90 static inline void btree_node_unlock(struct btree_iter *iter, unsigned level)
91 {
92         int lock_type = btree_node_locked_type(iter, level);
93
94         if (lock_type != BTREE_NODE_UNLOCKED)
95                 six_unlock_type(&iter->nodes[level]->lock, lock_type);
96         mark_btree_node_unlocked(iter, level);
97 }
98
99 bool __bch2_btree_node_lock(struct btree *, struct bpos, unsigned,
100                            struct btree_iter *, enum six_lock_type);
101
102 static inline bool btree_node_lock(struct btree *b, struct bpos pos,
103                                    unsigned level,
104                                    struct btree_iter *iter,
105                                    enum six_lock_type type)
106 {
107         return likely(six_trylock_type(&b->lock, type)) ||
108                 __bch2_btree_node_lock(b, pos, level, iter, type);
109 }
110
111 bool bch2_btree_node_relock(struct btree_iter *, unsigned);
112
113 void bch2_btree_node_unlock_write(struct btree *, struct btree_iter *);
114 void bch2_btree_node_lock_write(struct btree *, struct btree_iter *);
115
116 #endif /* _BCACHE_BTREE_LOCKING_H */