]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/alloc_foreground.h
6de63a351fa881f2547bb01e0f5ee593bfbb8410
[bcachefs-tools-debian] / libbcachefs / alloc_foreground.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_ALLOC_FOREGROUND_H
3 #define _BCACHEFS_ALLOC_FOREGROUND_H
4
5 #include "bcachefs.h"
6 #include "alloc_types.h"
7
8 #include <linux/hash.h>
9
10 struct bkey;
11 struct bch_dev;
12 struct bch_fs;
13 struct bch_devs_List;
14
15 extern const char * const bch2_alloc_reserves[];
16
17 struct dev_alloc_list {
18         unsigned        nr;
19         u8              devs[BCH_SB_MEMBERS_MAX];
20 };
21
22 struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *,
23                                           struct dev_stripe_state *,
24                                           struct bch_devs_mask *);
25 void bch2_dev_stripe_increment(struct bch_dev *, struct dev_stripe_state *);
26
27 long bch2_bucket_alloc_new_fs(struct bch_dev *);
28
29 struct open_bucket *bch2_bucket_alloc(struct bch_fs *, struct bch_dev *,
30                                       enum alloc_reserve, bool,
31                                       struct closure *);
32
33 static inline void ob_push(struct bch_fs *c, struct open_buckets *obs,
34                            struct open_bucket *ob)
35 {
36         BUG_ON(obs->nr >= ARRAY_SIZE(obs->v));
37
38         obs->v[obs->nr++] = ob - c->open_buckets;
39 }
40
41 #define open_bucket_for_each(_c, _obs, _ob, _i)                         \
42         for ((_i) = 0;                                                  \
43              (_i) < (_obs)->nr &&                                       \
44              ((_ob) = (_c)->open_buckets + (_obs)->v[_i], true);        \
45              (_i)++)
46
47 static inline struct open_bucket *ec_open_bucket(struct bch_fs *c,
48                                                  struct open_buckets *obs)
49 {
50         struct open_bucket *ob;
51         unsigned i;
52
53         open_bucket_for_each(c, obs, ob, i)
54                 if (ob->ec)
55                         return ob;
56
57         return NULL;
58 }
59
60 void bch2_open_bucket_write_error(struct bch_fs *,
61                         struct open_buckets *, unsigned);
62
63 void __bch2_open_bucket_put(struct bch_fs *, struct open_bucket *);
64
65 static inline void bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
66 {
67         if (atomic_dec_and_test(&ob->pin))
68                 __bch2_open_bucket_put(c, ob);
69 }
70
71 static inline void bch2_open_buckets_put(struct bch_fs *c,
72                                          struct open_buckets *ptrs)
73 {
74         struct open_bucket *ob;
75         unsigned i;
76
77         open_bucket_for_each(c, ptrs, ob, i)
78                 bch2_open_bucket_put(c, ob);
79         ptrs->nr = 0;
80 }
81
82 static inline void bch2_open_bucket_get(struct bch_fs *c,
83                                         struct write_point *wp,
84                                         struct open_buckets *ptrs)
85 {
86         struct open_bucket *ob;
87         unsigned i;
88
89         open_bucket_for_each(c, &wp->ptrs, ob, i) {
90                 ob->data_type = wp->data_type;
91                 atomic_inc(&ob->pin);
92                 ob_push(c, ptrs, ob);
93         }
94 }
95
96 static inline open_bucket_idx_t *open_bucket_hashslot(struct bch_fs *c,
97                                                   unsigned dev, u64 bucket)
98 {
99         return c->open_buckets_hash +
100                 (jhash_3words(dev, bucket, bucket >> 32, 0) &
101                  (OPEN_BUCKETS_COUNT - 1));
102 }
103
104 static inline bool bch2_bucket_is_open(struct bch_fs *c, unsigned dev, u64 bucket)
105 {
106         open_bucket_idx_t slot = *open_bucket_hashslot(c, dev, bucket);
107
108         while (slot) {
109                 struct open_bucket *ob = &c->open_buckets[slot];
110
111                 if (ob->dev == dev && ob->bucket == bucket)
112                         return true;
113
114                 slot = ob->hash;
115         }
116
117         return false;
118 }
119
120 static inline bool bch2_bucket_is_open_safe(struct bch_fs *c, unsigned dev, u64 bucket)
121 {
122         bool ret;
123
124         if (bch2_bucket_is_open(c, dev, bucket))
125                 return true;
126
127         spin_lock(&c->freelist_lock);
128         ret = bch2_bucket_is_open(c, dev, bucket);
129         spin_unlock(&c->freelist_lock);
130
131         return ret;
132 }
133
134 int bch2_bucket_alloc_set(struct bch_fs *, struct open_buckets *,
135                       struct dev_stripe_state *, struct bch_devs_mask *,
136                       unsigned, unsigned *, bool *, enum alloc_reserve,
137                       unsigned, struct closure *);
138
139 struct write_point *bch2_alloc_sectors_start_trans(struct btree_trans *,
140                                              unsigned, unsigned,
141                                              struct write_point_specifier,
142                                              struct bch_devs_list *,
143                                              unsigned, unsigned,
144                                              enum alloc_reserve,
145                                              unsigned,
146                                              struct closure *);
147 struct write_point *bch2_alloc_sectors_start(struct bch_fs *,
148                                              unsigned, unsigned,
149                                              struct write_point_specifier,
150                                              struct bch_devs_list *,
151                                              unsigned, unsigned,
152                                              enum alloc_reserve,
153                                              unsigned,
154                                              struct closure *);
155
156 struct bch_extent_ptr bch2_ob_ptr(struct bch_fs *, struct open_bucket *);
157 void bch2_alloc_sectors_append_ptrs(struct bch_fs *, struct write_point *,
158                                     struct bkey_i *, unsigned, bool);
159 void bch2_alloc_sectors_done(struct bch_fs *, struct write_point *);
160
161 void bch2_open_buckets_stop_dev(struct bch_fs *, struct bch_dev *,
162                                 struct open_buckets *);
163
164 void bch2_writepoint_stop(struct bch_fs *, struct bch_dev *,
165                           struct write_point *);
166
167 static inline struct write_point_specifier writepoint_hashed(unsigned long v)
168 {
169         return (struct write_point_specifier) { .v = v | 1 };
170 }
171
172 static inline struct write_point_specifier writepoint_ptr(struct write_point *wp)
173 {
174         return (struct write_point_specifier) { .v = (unsigned long) wp };
175 }
176
177 void bch2_fs_allocator_foreground_init(struct bch_fs *);
178
179 void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *);
180
181 #endif /* _BCACHEFS_ALLOC_FOREGROUND_H */