bcachefs: Initial commit
[linux-block.git] / fs / bcachefs / btree_io.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_BTREE_IO_H
3 #define _BCACHEFS_BTREE_IO_H
4
5 #include "bset.h"
6 #include "extents.h"
7 #include "io_types.h"
8
9 struct bch_fs;
10 struct btree_write;
11 struct btree;
12 struct btree_iter;
13
14 struct btree_read_bio {
15         struct bch_fs           *c;
16         u64                     start_time;
17         unsigned                have_ioref:1;
18         struct extent_pick_ptr  pick;
19         struct work_struct      work;
20         struct bio              bio;
21 };
22
23 struct btree_write_bio {
24         void                    *data;
25         struct work_struct      work;
26         struct bch_write_bio    wbio;
27 };
28
29 static inline void btree_node_io_unlock(struct btree *b)
30 {
31         EBUG_ON(!btree_node_write_in_flight(b));
32         clear_btree_node_write_in_flight(b);
33         wake_up_bit(&b->flags, BTREE_NODE_write_in_flight);
34 }
35
36 static inline void btree_node_io_lock(struct btree *b)
37 {
38         wait_on_bit_lock_io(&b->flags, BTREE_NODE_write_in_flight,
39                             TASK_UNINTERRUPTIBLE);
40 }
41
42 static inline void btree_node_wait_on_io(struct btree *b)
43 {
44         wait_on_bit_io(&b->flags, BTREE_NODE_write_in_flight,
45                        TASK_UNINTERRUPTIBLE);
46 }
47
48 static inline bool btree_node_may_write(struct btree *b)
49 {
50         return list_empty_careful(&b->write_blocked) &&
51                 !b->will_make_reachable;
52 }
53
54 enum compact_mode {
55         COMPACT_LAZY,
56         COMPACT_WRITTEN,
57         COMPACT_WRITTEN_NO_WRITE_LOCK,
58 };
59
60 bool __bch2_compact_whiteouts(struct bch_fs *, struct btree *, enum compact_mode);
61
62 static inline unsigned should_compact_bset_lazy(struct btree *b, struct bset_tree *t)
63 {
64         unsigned bset_u64s = le16_to_cpu(bset(b, t)->u64s);
65         unsigned dead_u64s = bset_u64s - b->nr.bset_u64s[t - b->set];
66
67         return dead_u64s > 128 && dead_u64s * 3 > bset_u64s;
68 }
69
70 static inline bool bch2_maybe_compact_whiteouts(struct bch_fs *c, struct btree *b)
71 {
72         struct bset_tree *t;
73
74         for_each_bset(b, t)
75                 if (should_compact_bset_lazy(b, t))
76                         return __bch2_compact_whiteouts(c, b, COMPACT_LAZY);
77
78         return false;
79 }
80
81 void bch2_btree_sort_into(struct bch_fs *, struct btree *, struct btree *);
82
83 void bch2_btree_build_aux_trees(struct btree *);
84 void bch2_btree_init_next(struct bch_fs *, struct btree *,
85                          struct btree_iter *);
86
87 int bch2_btree_node_read_done(struct bch_fs *, struct btree *, bool);
88 void bch2_btree_node_read(struct bch_fs *, struct btree *, bool);
89 int bch2_btree_root_read(struct bch_fs *, enum btree_id,
90                          const struct bkey_i *, unsigned);
91
92 void bch2_btree_complete_write(struct bch_fs *, struct btree *,
93                               struct btree_write *);
94 void bch2_btree_write_error_work(struct work_struct *);
95
96 void __bch2_btree_node_write(struct bch_fs *, struct btree *,
97                             enum six_lock_type);
98 bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *);
99
100 void bch2_btree_node_write(struct bch_fs *, struct btree *,
101                           enum six_lock_type);
102
103 /*
104  * btree_node_dirty() can be cleared with only a read lock,
105  * and for bch2_btree_node_write_cond() we want to set need_write iff it's
106  * still dirty:
107  */
108 static inline void set_btree_node_need_write_if_dirty(struct btree *b)
109 {
110         unsigned long old, new, v = READ_ONCE(b->flags);
111
112         do {
113                 old = new = v;
114
115                 if (!(old & (1 << BTREE_NODE_dirty)))
116                         return;
117
118                 new |= (1 << BTREE_NODE_need_write);
119         } while ((v = cmpxchg(&b->flags, old, new)) != old);
120 }
121
122 #define bch2_btree_node_write_cond(_c, _b, cond)                        \
123 do {                                                                    \
124         while ((_b)->written && btree_node_dirty(_b) && (cond)) {       \
125                 if (!btree_node_may_write(_b)) {                        \
126                         set_btree_node_need_write_if_dirty(_b);         \
127                         break;                                          \
128                 }                                                       \
129                                                                         \
130                 if (!btree_node_write_in_flight(_b)) {                  \
131                         bch2_btree_node_write(_c, _b, SIX_LOCK_read);   \
132                         break;                                          \
133                 }                                                       \
134                                                                         \
135                 six_unlock_read(&(_b)->lock);                           \
136                 btree_node_wait_on_io(_b);                              \
137                 btree_node_lock_type(c, b, SIX_LOCK_read);              \
138         }                                                               \
139 } while (0)
140
141 void bch2_btree_flush_all_reads(struct bch_fs *);
142 void bch2_btree_flush_all_writes(struct bch_fs *);
143 void bch2_btree_verify_flushed(struct bch_fs *);
144 ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *, char *);
145
146 /* Sorting */
147
148 struct btree_node_iter_large {
149         u8              is_extents;
150         u16             used;
151
152         struct btree_node_iter_set data[MAX_BSETS];
153 };
154
155 static inline void
156 __bch2_btree_node_iter_large_init(struct btree_node_iter_large *iter,
157                                   bool is_extents)
158 {
159         iter->used = 0;
160         iter->is_extents = is_extents;
161 }
162
163 void bch2_btree_node_iter_large_advance(struct btree_node_iter_large *,
164                                         struct btree *);
165
166 void bch2_btree_node_iter_large_push(struct btree_node_iter_large *,
167                                      struct btree *,
168                                      const struct bkey_packed *,
169                                      const struct bkey_packed *);
170
171 static inline bool bch2_btree_node_iter_large_end(struct btree_node_iter_large *iter)
172 {
173         return !iter->used;
174 }
175
176 static inline struct bkey_packed *
177 bch2_btree_node_iter_large_peek_all(struct btree_node_iter_large *iter,
178                                     struct btree *b)
179 {
180         return bch2_btree_node_iter_large_end(iter)
181                 ? NULL
182                 : __btree_node_offset_to_key(b, iter->data->k);
183 }
184
185 static inline struct bkey_packed *
186 bch2_btree_node_iter_large_next_all(struct btree_node_iter_large *iter,
187                                     struct btree *b)
188 {
189         struct bkey_packed *ret = bch2_btree_node_iter_large_peek_all(iter, b);
190
191         if (ret)
192                 bch2_btree_node_iter_large_advance(iter, b);
193
194         return ret;
195 }
196
197 #endif /* _BCACHEFS_BTREE_IO_H */