]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/btree_locking.h
Update bcachefs sources to 6a25f7a00d bcachefs: fix ioctl code
[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 "btree_io.h"
14 #include "six.h"
15
16 /* matches six lock types */
17 enum btree_node_locked_type {
18         BTREE_NODE_UNLOCKED             = -1,
19         BTREE_NODE_READ_LOCKED          = SIX_LOCK_read,
20         BTREE_NODE_INTENT_LOCKED        = SIX_LOCK_intent,
21 };
22
23 static inline int btree_node_locked_type(struct btree_iter *iter,
24                                          unsigned level)
25 {
26         /*
27          * We're relying on the fact that if nodes_intent_locked is set
28          * nodes_locked must be set as well, so that we can compute without
29          * branches:
30          */
31         return BTREE_NODE_UNLOCKED +
32                 ((iter->nodes_locked >> level) & 1) +
33                 ((iter->nodes_intent_locked >> level) & 1);
34 }
35
36 static inline bool btree_node_intent_locked(struct btree_iter *iter,
37                                             unsigned level)
38 {
39         return btree_node_locked_type(iter, level) == BTREE_NODE_INTENT_LOCKED;
40 }
41
42 static inline bool btree_node_read_locked(struct btree_iter *iter,
43                                           unsigned level)
44 {
45         return btree_node_locked_type(iter, level) == BTREE_NODE_READ_LOCKED;
46 }
47
48 static inline bool btree_node_locked(struct btree_iter *iter, unsigned level)
49 {
50         return iter->nodes_locked & (1 << level);
51 }
52
53 static inline void mark_btree_node_unlocked(struct btree_iter *iter,
54                                             unsigned level)
55 {
56         iter->nodes_locked &= ~(1 << level);
57         iter->nodes_intent_locked &= ~(1 << level);
58 }
59
60 static inline void mark_btree_node_locked(struct btree_iter *iter,
61                                           unsigned level,
62                                           enum six_lock_type type)
63 {
64         /* relying on this to avoid a branch */
65         BUILD_BUG_ON(SIX_LOCK_read   != 0);
66         BUILD_BUG_ON(SIX_LOCK_intent != 1);
67
68         iter->nodes_locked |= 1 << level;
69         iter->nodes_intent_locked |= type << level;
70 }
71
72 static inline void mark_btree_node_intent_locked(struct btree_iter *iter,
73                                                  unsigned level)
74 {
75         mark_btree_node_locked(iter, level, SIX_LOCK_intent);
76 }
77
78 static inline int 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 */