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