]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/tier.c
Update bcachefs sources to e57b5958cf bcachefs: fix for building in userspace
[bcachefs-tools-debian] / libbcachefs / tier.c
1
2 #include "bcachefs.h"
3 #include "alloc.h"
4 #include "btree_iter.h"
5 #include "buckets.h"
6 #include "clock.h"
7 #include "extents.h"
8 #include "io.h"
9 #include "keylist.h"
10 #include "move.h"
11 #include "super-io.h"
12 #include "tier.h"
13
14 #include <linux/freezer.h>
15 #include <linux/kthread.h>
16 #include <trace/events/bcachefs.h>
17
18 static bool tiering_pred(void *arg, struct bkey_s_c_extent e)
19 {
20         struct bch_tier *tier = arg;
21         struct bch_fs *c = container_of(tier, struct bch_fs, tiers[tier->idx]);
22         const struct bch_extent_ptr *ptr;
23         unsigned replicas = 0;
24
25         /* Make sure we have room to add a new pointer: */
26         if (bkey_val_u64s(e.k) + BKEY_EXTENT_PTR_U64s_MAX >
27             BKEY_EXTENT_VAL_U64s_MAX)
28                 return false;
29
30         extent_for_each_ptr(e, ptr)
31                 if (c->devs[ptr->dev]->mi.tier >= tier->idx)
32                         replicas++;
33
34         return replicas < c->opts.data_replicas;
35 }
36
37 static int bch2_tiering_thread(void *arg)
38 {
39         struct bch_tier *tier = arg;
40         struct bch_fs *c = container_of(tier, struct bch_fs, tiers[tier->idx]);
41         struct io_clock *clock = &c->io_clock[WRITE];
42         struct bch_dev *ca;
43         u64 tier_capacity, available_sectors, keys_moved, sectors_moved;
44         unsigned long last;
45         unsigned i, nr_devices;
46
47         set_freezable();
48
49         while (!kthread_should_stop()) {
50                 if (kthread_wait_freezable(c->tiering_enabled &&
51                                            (nr_devices = dev_mask_nr(&tier->devs))))
52                         break;
53
54                 while (1) {
55                         struct bch_tier *faster_tier;
56
57                         last = atomic_long_read(&clock->now);
58
59                         tier_capacity = available_sectors = 0;
60                         for (faster_tier = c->tiers;
61                              faster_tier != tier;
62                              faster_tier++) {
63                                 rcu_read_lock();
64                                 for_each_member_device_rcu(ca, c, i,
65                                                 &faster_tier->devs) {
66                                         tier_capacity +=
67                                                 bucket_to_sector(ca,
68                                                         ca->mi.nbuckets -
69                                                         ca->mi.first_bucket);
70                                         available_sectors +=
71                                                 bucket_to_sector(ca,
72                                                         dev_buckets_available(c, ca));
73                                 }
74                                 rcu_read_unlock();
75                         }
76
77                         if (available_sectors < (tier_capacity >> 1))
78                                 break;
79
80                         bch2_kthread_io_clock_wait(clock,
81                                                   last +
82                                                   available_sectors -
83                                                   (tier_capacity >> 1));
84                         if (kthread_should_stop())
85                                 return 0;
86                 }
87
88                 bch2_move_data(c, &tier->pd.rate,
89                                SECTORS_IN_FLIGHT_PER_DEVICE * nr_devices,
90                                &tier->devs,
91                                writepoint_ptr(&tier->wp),
92                                0,
93                                -1,
94                                tiering_pred, tier,
95                                &keys_moved,
96                                &sectors_moved);
97         }
98
99         return 0;
100 }
101
102 static void __bch2_tiering_stop(struct bch_tier *tier)
103 {
104         tier->pd.rate.rate = UINT_MAX;
105         bch2_ratelimit_reset(&tier->pd.rate);
106
107         if (tier->migrate)
108                 kthread_stop(tier->migrate);
109
110         tier->migrate = NULL;
111 }
112
113 void bch2_tiering_stop(struct bch_fs *c)
114 {
115         struct bch_tier *tier;
116
117         for (tier = c->tiers; tier < c->tiers + ARRAY_SIZE(c->tiers); tier++)
118                 __bch2_tiering_stop(tier);
119 }
120
121 static int __bch2_tiering_start(struct bch_tier *tier)
122 {
123         if (!tier->migrate) {
124                 struct task_struct *p =
125                         kthread_create(bch2_tiering_thread, tier,
126                                        "bch_tier[%u]", tier->idx);
127                 if (IS_ERR(p))
128                         return PTR_ERR(p);
129
130                 tier->migrate = p;
131         }
132
133         wake_up_process(tier->migrate);
134         return 0;
135 }
136
137 int bch2_tiering_start(struct bch_fs *c)
138 {
139         struct bch_tier *tier;
140         bool have_faster_tier = false;
141
142         if (c->opts.nochanges)
143                 return 0;
144
145         for (tier = c->tiers; tier < c->tiers + ARRAY_SIZE(c->tiers); tier++) {
146                 if (!dev_mask_nr(&tier->devs))
147                         continue;
148
149                 if (have_faster_tier) {
150                         int ret = __bch2_tiering_start(tier);
151                         if (ret)
152                                 return ret;
153                 } else {
154                         __bch2_tiering_stop(tier);
155                 }
156
157                 have_faster_tier = true;
158         }
159
160         return 0;
161 }
162
163 void bch2_fs_tiering_init(struct bch_fs *c)
164 {
165         unsigned i;
166
167         for (i = 0; i < ARRAY_SIZE(c->tiers); i++) {
168                 c->tiers[i].idx = i;
169                 bch2_pd_controller_init(&c->tiers[i].pd);
170         }
171 }