]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/alloc_background.h
New upstream release
[bcachefs-tools-debian] / libbcachefs / alloc_background.h
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 "debug.h"
8
9 extern const char * const bch2_allocator_states[];
10
11 struct bkey_alloc_unpacked {
12         u64             bucket;
13         u8              dev;
14         u8              gen;
15         u8              oldest_gen;
16         u8              data_type;
17 #define x(_name, _bits) u##_bits _name;
18         BCH_ALLOC_FIELDS_V2()
19 #undef  x
20 };
21
22 struct bkey_alloc_buf {
23         struct bkey_i   k;
24
25         union {
26         struct {
27 #define x(_name,  _bits)                + _bits / 8
28         u8              _pad[8 + BCH_ALLOC_FIELDS_V1()];
29 #undef  x
30         } _v1;
31         struct {
32 #define x(_name,  _bits)                + 8 + _bits / 8
33         u8              _pad[8 + BCH_ALLOC_FIELDS_V2()];
34 #undef  x
35         } _v2;
36         };
37 } __attribute__((packed, aligned(8)));
38
39 /* How out of date a pointer gen is allowed to be: */
40 #define BUCKET_GC_GEN_MAX       96U
41
42 /* returns true if not equal */
43 static inline bool bkey_alloc_unpacked_cmp(struct bkey_alloc_unpacked l,
44                                            struct bkey_alloc_unpacked r)
45 {
46         return  l.gen != r.gen                  ||
47                 l.oldest_gen != r.oldest_gen    ||
48                 l.data_type != r.data_type
49 #define x(_name, ...)   || l._name != r._name
50         BCH_ALLOC_FIELDS_V2()
51 #undef  x
52         ;
53 }
54
55 struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c);
56 void bch2_alloc_pack(struct bch_fs *, struct bkey_alloc_buf *,
57                      const struct bkey_alloc_unpacked);
58
59 int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
60
61 static inline struct bkey_alloc_unpacked
62 alloc_mem_to_key(struct btree_iter *iter,
63                  struct bucket *g, struct bucket_mark m)
64 {
65         return (struct bkey_alloc_unpacked) {
66                 .dev            = iter->pos.inode,
67                 .bucket         = iter->pos.offset,
68                 .gen            = m.gen,
69                 .oldest_gen     = g->oldest_gen,
70                 .data_type      = m.data_type,
71                 .dirty_sectors  = m.dirty_sectors,
72                 .cached_sectors = m.cached_sectors,
73                 .read_time      = g->io_time[READ],
74                 .write_time     = g->io_time[WRITE],
75         };
76 }
77
78 #define ALLOC_SCAN_BATCH(ca)            max_t(size_t, 1, (ca)->mi.nbuckets >> 9)
79
80 const char *bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c);
81 const char *bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c);
82 void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
83
84 #define bch2_bkey_ops_alloc (struct bkey_ops) {         \
85         .key_invalid    = bch2_alloc_v1_invalid,        \
86         .val_to_text    = bch2_alloc_to_text,           \
87 }
88
89 #define bch2_bkey_ops_alloc_v2 (struct bkey_ops) {      \
90         .key_invalid    = bch2_alloc_v2_invalid,        \
91         .val_to_text    = bch2_alloc_to_text,           \
92 }
93
94 int bch2_alloc_read(struct bch_fs *);
95
96 static inline void bch2_wake_allocator(struct bch_dev *ca)
97 {
98         struct task_struct *p;
99
100         rcu_read_lock();
101         p = rcu_dereference(ca->alloc_thread);
102         if (p)
103                 wake_up_process(p);
104         rcu_read_unlock();
105 }
106
107 static inline void verify_not_on_freelist(struct bch_fs *c, struct bch_dev *ca,
108                                           size_t bucket)
109 {
110         if (bch2_expensive_debug_checks) {
111                 size_t iter;
112                 long i;
113                 unsigned j;
114
115                 for (j = 0; j < RESERVE_NR; j++)
116                         fifo_for_each_entry(i, &ca->free[j], iter)
117                                 BUG_ON(i == bucket);
118                 fifo_for_each_entry(i, &ca->free_inc, iter)
119                         BUG_ON(i == bucket);
120         }
121 }
122
123 void bch2_recalc_capacity(struct bch_fs *);
124
125 void bch2_dev_allocator_remove(struct bch_fs *, struct bch_dev *);
126 void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *);
127
128 void bch2_dev_allocator_quiesce(struct bch_fs *, struct bch_dev *);
129 void bch2_dev_allocator_stop(struct bch_dev *);
130 int bch2_dev_allocator_start(struct bch_dev *);
131
132 int bch2_alloc_write(struct bch_fs *, unsigned);
133 void bch2_fs_allocator_background_init(struct bch_fs *);
134
135 void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *);
136
137 #endif /* _BCACHEFS_ALLOC_BACKGROUND_H */