~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/bcachefs/alloc_background.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef _BCACHEFS_ALLOC_BACKGROUND_H
  3 #define _BCACHEFS_ALLOC_BACKGROUND_H
  4 
  5 #include "bcachefs.h"
  6 #include "alloc_types.h"
  7 #include "buckets.h"
  8 #include "debug.h"
  9 #include "super.h"
 10 
 11 enum bch_validate_flags;
 12 
 13 /* How out of date a pointer gen is allowed to be: */
 14 #define BUCKET_GC_GEN_MAX       96U
 15 
 16 static inline bool bch2_dev_bucket_exists(struct bch_fs *c, struct bpos pos)
 17 {
 18         rcu_read_lock();
 19         struct bch_dev *ca = bch2_dev_rcu(c, pos.inode);
 20         bool ret = ca && bucket_valid(ca, pos.offset);
 21         rcu_read_unlock();
 22         return ret;
 23 }
 24 
 25 static inline u64 bucket_to_u64(struct bpos bucket)
 26 {
 27         return (bucket.inode << 48) | bucket.offset;
 28 }
 29 
 30 static inline struct bpos u64_to_bucket(u64 bucket)
 31 {
 32         return POS(bucket >> 48, bucket & ~(~0ULL << 48));
 33 }
 34 
 35 static inline u8 alloc_gc_gen(struct bch_alloc_v4 a)
 36 {
 37         return a.gen - a.oldest_gen;
 38 }
 39 
 40 static inline void alloc_to_bucket(struct bucket *dst, struct bch_alloc_v4 src)
 41 {
 42         dst->gen                = src.gen;
 43         dst->data_type          = src.data_type;
 44         dst->stripe_sectors     = src.stripe_sectors;
 45         dst->dirty_sectors      = src.dirty_sectors;
 46         dst->cached_sectors     = src.cached_sectors;
 47         dst->stripe             = src.stripe;
 48 }
 49 
 50 static inline void __bucket_m_to_alloc(struct bch_alloc_v4 *dst, struct bucket src)
 51 {
 52         dst->gen                = src.gen;
 53         dst->data_type          = src.data_type;
 54         dst->stripe_sectors     = src.stripe_sectors;
 55         dst->dirty_sectors      = src.dirty_sectors;
 56         dst->cached_sectors     = src.cached_sectors;
 57         dst->stripe             = src.stripe;
 58 }
 59 
 60 static inline struct bch_alloc_v4 bucket_m_to_alloc(struct bucket b)
 61 {
 62         struct bch_alloc_v4 ret = {};
 63         __bucket_m_to_alloc(&ret, b);
 64         return ret;
 65 }
 66 
 67 static inline enum bch_data_type bucket_data_type(enum bch_data_type data_type)
 68 {
 69         switch (data_type) {
 70         case BCH_DATA_cached:
 71         case BCH_DATA_stripe:
 72                 return BCH_DATA_user;
 73         default:
 74                 return data_type;
 75         }
 76 }
 77 
 78 static inline bool bucket_data_type_mismatch(enum bch_data_type bucket,
 79                                              enum bch_data_type ptr)
 80 {
 81         return !data_type_is_empty(bucket) &&
 82                 bucket_data_type(bucket) != bucket_data_type(ptr);
 83 }
 84 
 85 /*
 86  * It is my general preference to use unsigned types for unsigned quantities -
 87  * however, these helpers are used in disk accounting calculations run by
 88  * triggers where the output will be negated and added to an s64. unsigned is
 89  * right out even though all these quantities will fit in 32 bits, since it
 90  * won't be sign extended correctly; u64 will negate "correctly", but s64 is the
 91  * simpler option here.
 92  */
 93 static inline s64 bch2_bucket_sectors_total(struct bch_alloc_v4 a)
 94 {
 95         return a.stripe_sectors + a.dirty_sectors + a.cached_sectors;
 96 }
 97 
 98 static inline s64 bch2_bucket_sectors_dirty(struct bch_alloc_v4 a)
 99 {
100         return a.stripe_sectors + a.dirty_sectors;
101 }
102 
103 static inline s64 bch2_bucket_sectors(struct bch_alloc_v4 a)
104 {
105         return a.data_type == BCH_DATA_cached
106                 ? a.cached_sectors
107                 : bch2_bucket_sectors_dirty(a);
108 }
109 
110 static inline s64 bch2_bucket_sectors_fragmented(struct bch_dev *ca,
111                                                  struct bch_alloc_v4 a)
112 {
113         int d = bch2_bucket_sectors(a);
114 
115         return d ? max(0, ca->mi.bucket_size - d) : 0;
116 }
117 
118 static inline s64 bch2_gc_bucket_sectors_fragmented(struct bch_dev *ca, struct bucket a)
119 {
120         int d = a.stripe_sectors + a.dirty_sectors;
121 
122         return d ? max(0, ca->mi.bucket_size - d) : 0;
123 }
124 
125 static inline s64 bch2_bucket_sectors_unstriped(struct bch_alloc_v4 a)
126 {
127         return a.data_type == BCH_DATA_stripe ? a.dirty_sectors : 0;
128 }
129 
130 static inline enum bch_data_type alloc_data_type(struct bch_alloc_v4 a,
131                                                  enum bch_data_type data_type)
132 {
133         if (a.stripe)
134                 return data_type == BCH_DATA_parity ? data_type : BCH_DATA_stripe;
135         if (bch2_bucket_sectors_dirty(a))
136                 return data_type;
137         if (a.cached_sectors)
138                 return BCH_DATA_cached;
139         if (BCH_ALLOC_V4_NEED_DISCARD(&a))
140                 return BCH_DATA_need_discard;
141         if (alloc_gc_gen(a) >= BUCKET_GC_GEN_MAX)
142                 return BCH_DATA_need_gc_gens;
143         return BCH_DATA_free;
144 }
145 
146 static inline void alloc_data_type_set(struct bch_alloc_v4 *a, enum bch_data_type data_type)
147 {
148         a->data_type = alloc_data_type(*a, data_type);
149 }
150 
151 static inline u64 alloc_lru_idx_read(struct bch_alloc_v4 a)
152 {
153         return a.data_type == BCH_DATA_cached
154                 ? a.io_time[READ] & LRU_TIME_MAX
155                 : 0;
156 }
157 
158 #define DATA_TYPES_MOVABLE              \
159         ((1U << BCH_DATA_btree)|        \
160          (1U << BCH_DATA_user)|         \
161          (1U << BCH_DATA_stripe))
162 
163 static inline bool data_type_movable(enum bch_data_type type)
164 {
165         return (1U << type) & DATA_TYPES_MOVABLE;
166 }
167 
168 static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a,
169                                               struct bch_dev *ca)
170 {
171         if (!data_type_movable(a.data_type) ||
172             !bch2_bucket_sectors_fragmented(ca, a))
173                 return 0;
174 
175         /*
176          * avoid overflowing LRU_TIME_BITS on a corrupted fs, when
177          * bucket_sectors_dirty is (much) bigger than bucket_size
178          */
179         u64 d = min_t(s64, bch2_bucket_sectors_dirty(a),
180                       ca->mi.bucket_size);
181 
182         return div_u64(d * (1ULL << 31), ca->mi.bucket_size);
183 }
184 
185 static inline u64 alloc_freespace_genbits(struct bch_alloc_v4 a)
186 {
187         return ((u64) alloc_gc_gen(a) >> 4) << 56;
188 }
189 
190 static inline struct bpos alloc_freespace_pos(struct bpos pos, struct bch_alloc_v4 a)
191 {
192         pos.offset |= alloc_freespace_genbits(a);
193         return pos;
194 }
195 
196 static inline unsigned alloc_v4_u64s_noerror(const struct bch_alloc_v4 *a)
197 {
198         return (BCH_ALLOC_V4_BACKPOINTERS_START(a) ?:
199                         BCH_ALLOC_V4_U64s_V0) +
200                 BCH_ALLOC_V4_NR_BACKPOINTERS(a) *
201                 (sizeof(struct bch_backpointer) / sizeof(u64));
202 }
203 
204 static inline unsigned alloc_v4_u64s(const struct bch_alloc_v4 *a)
205 {
206         unsigned ret = alloc_v4_u64s_noerror(a);
207         BUG_ON(ret > U8_MAX - BKEY_U64s);
208         return ret;
209 }
210 
211 static inline void set_alloc_v4_u64s(struct bkey_i_alloc_v4 *a)
212 {
213         set_bkey_val_u64s(&a->k, alloc_v4_u64s(&a->v));
214 }
215 
216 struct bkey_i_alloc_v4 *
217 bch2_trans_start_alloc_update_noupdate(struct btree_trans *, struct btree_iter *, struct bpos);
218 struct bkey_i_alloc_v4 *
219 bch2_trans_start_alloc_update(struct btree_trans *, struct bpos,
220                               enum btree_iter_update_trigger_flags);
221 
222 void __bch2_alloc_to_v4(struct bkey_s_c, struct bch_alloc_v4 *);
223 
224 static inline const struct bch_alloc_v4 *bch2_alloc_to_v4(struct bkey_s_c k, struct bch_alloc_v4 *convert)
225 {
226         const struct bch_alloc_v4 *ret;
227 
228         if (unlikely(k.k->type != KEY_TYPE_alloc_v4))
229                 goto slowpath;
230 
231         ret = bkey_s_c_to_alloc_v4(k).v;
232         if (BCH_ALLOC_V4_BACKPOINTERS_START(ret) != BCH_ALLOC_V4_U64s)
233                 goto slowpath;
234 
235         return ret;
236 slowpath:
237         __bch2_alloc_to_v4(k, convert);
238         return convert;
239 }
240 
241 struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut(struct btree_trans *, struct bkey_s_c);
242 
243 int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
244 
245 int bch2_alloc_v1_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags);
246 int bch2_alloc_v2_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags);
247 int bch2_alloc_v3_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags);
248 int bch2_alloc_v4_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags);
249 void bch2_alloc_v4_swab(struct bkey_s);
250 void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
251 
252 #define bch2_bkey_ops_alloc ((struct bkey_ops) {        \
253         .key_validate   = bch2_alloc_v1_validate,       \
254         .val_to_text    = bch2_alloc_to_text,           \
255         .trigger        = bch2_trigger_alloc,           \
256         .min_val_size   = 8,                            \
257 })
258 
259 #define bch2_bkey_ops_alloc_v2 ((struct bkey_ops) {     \
260         .key_validate   = bch2_alloc_v2_validate,       \
261         .val_to_text    = bch2_alloc_to_text,           \
262         .trigger        = bch2_trigger_alloc,           \
263         .min_val_size   = 8,                            \
264 })
265 
266 #define bch2_bkey_ops_alloc_v3 ((struct bkey_ops) {     \
267         .key_validate   = bch2_alloc_v3_validate,       \
268         .val_to_text    = bch2_alloc_to_text,           \
269         .trigger        = bch2_trigger_alloc,           \
270         .min_val_size   = 16,                           \
271 })
272 
273 #define bch2_bkey_ops_alloc_v4 ((struct bkey_ops) {     \
274         .key_validate   = bch2_alloc_v4_validate,       \
275         .val_to_text    = bch2_alloc_to_text,           \
276         .swab           = bch2_alloc_v4_swab,           \
277         .trigger        = bch2_trigger_alloc,           \
278         .min_val_size   = 48,                           \
279 })
280 
281 int bch2_bucket_gens_validate(struct bch_fs *, struct bkey_s_c,
282                              enum bch_validate_flags);
283 void bch2_bucket_gens_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
284 
285 #define bch2_bkey_ops_bucket_gens ((struct bkey_ops) {  \
286         .key_validate   = bch2_bucket_gens_validate,    \
287         .val_to_text    = bch2_bucket_gens_to_text,     \
288 })
289 
290 int bch2_bucket_gens_init(struct bch_fs *);
291 
292 static inline bool bkey_is_alloc(const struct bkey *k)
293 {
294         return  k->type == KEY_TYPE_alloc ||
295                 k->type == KEY_TYPE_alloc_v2 ||
296                 k->type == KEY_TYPE_alloc_v3;
297 }
298 
299 int bch2_alloc_read(struct bch_fs *);
300 
301 int bch2_alloc_key_to_dev_counters(struct btree_trans *, struct bch_dev *,
302                                    const struct bch_alloc_v4 *,
303                                    const struct bch_alloc_v4 *, unsigned);
304 int bch2_trigger_alloc(struct btree_trans *, enum btree_id, unsigned,
305                        struct bkey_s_c, struct bkey_s,
306                        enum btree_iter_update_trigger_flags);
307 int bch2_check_alloc_info(struct bch_fs *);
308 int bch2_check_alloc_to_lru_refs(struct bch_fs *);
309 void bch2_dev_do_discards(struct bch_dev *);
310 void bch2_do_discards(struct bch_fs *);
311 
312 static inline u64 should_invalidate_buckets(struct bch_dev *ca,
313                                             struct bch_dev_usage u)
314 {
315         u64 want_free = ca->mi.nbuckets >> 7;
316         u64 free = max_t(s64, 0,
317                            u.d[BCH_DATA_free].buckets
318                          + u.d[BCH_DATA_need_discard].buckets
319                          - bch2_dev_buckets_reserved(ca, BCH_WATERMARK_stripe));
320 
321         return clamp_t(s64, want_free - free, 0, u.d[BCH_DATA_cached].buckets);
322 }
323 
324 void bch2_dev_do_invalidates(struct bch_dev *);
325 void bch2_do_invalidates(struct bch_fs *);
326 
327 static inline struct bch_backpointer *alloc_v4_backpointers(struct bch_alloc_v4 *a)
328 {
329         return (void *) ((u64 *) &a->v +
330                          (BCH_ALLOC_V4_BACKPOINTERS_START(a) ?:
331                           BCH_ALLOC_V4_U64s_V0));
332 }
333 
334 static inline const struct bch_backpointer *alloc_v4_backpointers_c(const struct bch_alloc_v4 *a)
335 {
336         return (void *) ((u64 *) &a->v + BCH_ALLOC_V4_BACKPOINTERS_START(a));
337 }
338 
339 int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64);
340 int bch2_fs_freespace_init(struct bch_fs *);
341 
342 void bch2_recalc_capacity(struct bch_fs *);
343 u64 bch2_min_rw_member_capacity(struct bch_fs *);
344 
345 void bch2_dev_allocator_remove(struct bch_fs *, struct bch_dev *);
346 void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *);
347 
348 void bch2_dev_allocator_background_exit(struct bch_dev *);
349 void bch2_dev_allocator_background_init(struct bch_dev *);
350 
351 void bch2_fs_allocator_background_init(struct bch_fs *);
352 
353 #endif /* _BCACHEFS_ALLOC_BACKGROUND_H */
354 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php