]> git.ipfire.org Git - thirdparty/linux.git/blame - fs/bcachefs/sb-members.c
Merge tag 'powerpc-6.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[thirdparty/linux.git] / fs / bcachefs / sb-members.c
CommitLineData
fb8e5b4c
KO
1// SPDX-License-Identifier: GPL-2.0
2
3#include "bcachefs.h"
27c15ed2 4#include "btree_cache.h"
fb8e5b4c 5#include "disk_groups.h"
23f308ae 6#include "error.h"
40f7914e 7#include "opts.h"
fb8e5b4c
KO
8#include "replicas.h"
9#include "sb-members.h"
10#include "super-io.h"
11
b07eb825
KO
12void bch2_dev_missing(struct bch_fs *c, unsigned dev)
13{
14 bch2_fs_inconsistent(c, "pointer to nonexistent device %u", dev);
15}
16
9b3059a1
KO
17void bch2_dev_bucket_missing(struct bch_fs *c, struct bpos bucket)
18{
19 bch2_fs_inconsistent(c, "pointer to nonexistent bucket %llu:%llu", bucket.inode, bucket.offset);
20}
21
94119eeb
KO
22#define x(t, n, ...) [n] = #t,
23static const char * const bch2_iops_measurements[] = {
24 BCH_IOPS_MEASUREMENTS()
25 NULL
26};
27
28char * const bch2_member_error_strs[] = {
29 BCH_MEMBER_ERROR_TYPES()
30 NULL
31};
32#undef x
33
9af26120 34/* Code for bch_sb_field_members_v1: */
3f7b9713 35
3f7b9713
HS
36struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i)
37{
0f0fc312 38 return __bch2_members_v2_get_mut(bch2_sb_field_get(sb, members_v2), i);
3f7b9713
HS
39}
40
41static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i)
42{
0f0fc312 43 struct bch_member ret, *p = __bch2_members_v2_get_mut(mi, i);
3f7b9713
HS
44 memset(&ret, 0, sizeof(ret));
45 memcpy(&ret, p, min_t(size_t, le16_to_cpu(mi->member_bytes), sizeof(ret)));
46 return ret;
47}
48
9af26120 49static struct bch_member *members_v1_get_mut(struct bch_sb_field_members_v1 *mi, int i)
1241df58 50{
3f7b9713 51 return (void *) mi->_members + (i * BCH_MEMBER_V1_BYTES);
1241df58
HS
52}
53
9af26120 54static struct bch_member members_v1_get(struct bch_sb_field_members_v1 *mi, int i)
1241df58
HS
55{
56 struct bch_member ret, *p = members_v1_get_mut(mi, i);
57 memset(&ret, 0, sizeof(ret));
5c1ab40e
KO
58 memcpy(&ret, p, min_t(size_t, BCH_MEMBER_V1_BYTES, sizeof(ret)));
59 return ret;
1241df58
HS
60}
61
62struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i)
63{
4637429e 64 struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(sb, members_v2);
3f7b9713
HS
65 if (mi2)
66 return members_v2_get(mi2, i);
4637429e 67 struct bch_sb_field_members_v1 *mi1 = bch2_sb_field_get(sb, members_v1);
1241df58
HS
68 return members_v1_get(mi1, i);
69}
fb8e5b4c 70
3f7b9713
HS
71static int sb_members_v2_resize_entries(struct bch_fs *c)
72{
4637429e 73 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
3f7b9713
HS
74
75 if (le16_to_cpu(mi->member_bytes) < sizeof(struct bch_member)) {
76 unsigned u64s = DIV_ROUND_UP((sizeof(*mi) + sizeof(mi->_members[0]) *
77 c->disk_sb.sb->nr_devices), 8);
78
4637429e 79 mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s);
3f7b9713
HS
80 if (!mi)
81 return -BCH_ERR_ENOSPC_sb_members_v2;
82
83 for (int i = c->disk_sb.sb->nr_devices - 1; i >= 0; --i) {
84 void *dst = (void *) mi->_members + (i * sizeof(struct bch_member));
0f0fc312 85 memmove(dst, __bch2_members_v2_get_mut(mi, i), le16_to_cpu(mi->member_bytes));
3f7b9713
HS
86 memset(dst + le16_to_cpu(mi->member_bytes),
87 0, (sizeof(struct bch_member) - le16_to_cpu(mi->member_bytes)));
88 }
89 mi->member_bytes = cpu_to_le16(sizeof(struct bch_member));
90 }
91 return 0;
92}
93
f5d26fa3 94int bch2_sb_members_v2_init(struct bch_fs *c)
3f7b9713 95{
9af26120 96 struct bch_sb_field_members_v1 *mi1;
3f7b9713
HS
97 struct bch_sb_field_members_v2 *mi2;
98
4637429e
KO
99 if (!bch2_sb_field_get(c->disk_sb.sb, members_v2)) {
100 mi2 = bch2_sb_field_resize(&c->disk_sb, members_v2,
3f7b9713
HS
101 DIV_ROUND_UP(sizeof(*mi2) +
102 sizeof(struct bch_member) * c->sb.nr_devices,
103 sizeof(u64)));
4637429e 104 mi1 = bch2_sb_field_get(c->disk_sb.sb, members_v1);
3f7b9713
HS
105 memcpy(&mi2->_members[0], &mi1->_members[0],
106 BCH_MEMBER_V1_BYTES * c->sb.nr_devices);
107 memset(&mi2->pad[0], 0, sizeof(mi2->pad));
108 mi2->member_bytes = cpu_to_le16(BCH_MEMBER_V1_BYTES);
109 }
110
111 return sb_members_v2_resize_entries(c);
112}
113
94119eeb 114int bch2_sb_members_cpy_v2_v1(struct bch_sb_handle *disk_sb)
3f7b9713 115{
9af26120 116 struct bch_sb_field_members_v1 *mi1;
3f7b9713
HS
117 struct bch_sb_field_members_v2 *mi2;
118
4637429e 119 mi1 = bch2_sb_field_resize(disk_sb, members_v1,
3f7b9713
HS
120 DIV_ROUND_UP(sizeof(*mi1) + BCH_MEMBER_V1_BYTES *
121 disk_sb->sb->nr_devices, sizeof(u64)));
122 if (!mi1)
123 return -BCH_ERR_ENOSPC_sb_members;
124
4637429e 125 mi2 = bch2_sb_field_get(disk_sb->sb, members_v2);
3f7b9713
HS
126
127 for (unsigned i = 0; i < disk_sb->sb->nr_devices; i++)
0f0fc312 128 memcpy(members_v1_get_mut(mi1, i), __bch2_members_v2_get_mut(mi2, i), BCH_MEMBER_V1_BYTES);
3f7b9713
HS
129
130 return 0;
131}
132
133static int validate_member(struct printbuf *err,
134 struct bch_member m,
135 struct bch_sb *sb,
136 int i)
137{
db42549d
KO
138 if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) {
139 prt_printf(err, "device %u: too many buckets (got %llu, max %u)",
140 i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX);
3f7b9713
HS
141 return -BCH_ERR_invalid_sb_members;
142 }
143
144 if (le64_to_cpu(m.nbuckets) -
145 le16_to_cpu(m.first_bucket) < BCH_MIN_NR_NBUCKETS) {
146 prt_printf(err, "device %u: not enough buckets (got %llu, max %u)",
147 i, le64_to_cpu(m.nbuckets), BCH_MIN_NR_NBUCKETS);
148 return -BCH_ERR_invalid_sb_members;
149 }
150
151 if (le16_to_cpu(m.bucket_size) <
152 le16_to_cpu(sb->block_size)) {
153 prt_printf(err, "device %u: bucket size %u smaller than block size %u",
154 i, le16_to_cpu(m.bucket_size), le16_to_cpu(sb->block_size));
155 return -BCH_ERR_invalid_sb_members;
156 }
157
158 if (le16_to_cpu(m.bucket_size) <
159 BCH_SB_BTREE_NODE_SIZE(sb)) {
160 prt_printf(err, "device %u: bucket size %u smaller than btree node size %llu",
161 i, le16_to_cpu(m.bucket_size), BCH_SB_BTREE_NODE_SIZE(sb));
162 return -BCH_ERR_invalid_sb_members;
163 }
164
165 return 0;
166}
167
168static void member_to_text(struct printbuf *out,
169 struct bch_member m,
170 struct bch_sb_field_disk_groups *gi,
171 struct bch_sb *sb,
172 int i)
173{
174 unsigned data_have = bch2_sb_dev_has_data(sb, i);
175 u64 bucket_size = le16_to_cpu(m.bucket_size);
176 u64 device_size = le64_to_cpu(m.nbuckets) * bucket_size;
177
2f724563 178 if (!bch2_member_alive(&m))
dc7a15fb
KO
179 return;
180
7423330e 181 prt_printf(out, "Device:\t%u\n", i);
3f7b9713
HS
182
183 printbuf_indent_add(out, 2);
184
7423330e 185 prt_printf(out, "Label:\t");
94119eeb
KO
186 if (BCH_MEMBER_GROUP(&m)) {
187 unsigned idx = BCH_MEMBER_GROUP(&m) - 1;
188
189 if (idx < disk_groups_nr(gi))
190 prt_printf(out, "%s (%u)",
191 gi->entries[idx].label, idx);
192 else
193 prt_printf(out, "(bad disk labels section)");
194 } else {
195 prt_printf(out, "(none)");
196 }
197 prt_newline(out);
198
7423330e 199 prt_printf(out, "UUID:\t");
3f7b9713
HS
200 pr_uuid(out, m.uuid.b);
201 prt_newline(out);
202
7423330e 203 prt_printf(out, "Size:\t");
3f7b9713
HS
204 prt_units_u64(out, device_size << 9);
205 prt_newline(out);
206
7423330e
KO
207 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++)
208 prt_printf(out, "%s errors:\t%llu\n", bch2_member_error_strs[i], le64_to_cpu(m.errors[i]));
94119eeb 209
7423330e
KO
210 for (unsigned i = 0; i < BCH_IOPS_NR; i++)
211 prt_printf(out, "%s iops:\t%u\n", bch2_iops_measurements[i], le32_to_cpu(m.iops[i]));
40f7914e 212
7423330e 213 prt_printf(out, "Bucket size:\t");
3f7b9713
HS
214 prt_units_u64(out, bucket_size << 9);
215 prt_newline(out);
216
7423330e
KO
217 prt_printf(out, "First bucket:\t%u\n", le16_to_cpu(m.first_bucket));
218 prt_printf(out, "Buckets:\t%llu\n", le64_to_cpu(m.nbuckets));
3f7b9713 219
7423330e 220 prt_printf(out, "Last mount:\t");
3f7b9713 221 if (m.last_mount)
59154f2c 222 bch2_prt_datetime(out, le64_to_cpu(m.last_mount));
3f7b9713
HS
223 else
224 prt_printf(out, "(never)");
225 prt_newline(out);
6b00de06 226
7423330e 227 prt_printf(out, "Last superblock write:\t%llu\n", le64_to_cpu(m.seq));
3f7b9713 228
7423330e 229 prt_printf(out, "State:\t%s\n",
3f7b9713
HS
230 BCH_MEMBER_STATE(&m) < BCH_MEMBER_STATE_NR
231 ? bch2_member_states[BCH_MEMBER_STATE(&m)]
232 : "unknown");
3f7b9713 233
7423330e 234 prt_printf(out, "Data allowed:\t");
3f7b9713 235 if (BCH_MEMBER_DATA_ALLOWED(&m))
e58f963c 236 prt_bitflags(out, __bch2_data_types, BCH_MEMBER_DATA_ALLOWED(&m));
3f7b9713
HS
237 else
238 prt_printf(out, "(none)");
239 prt_newline(out);
240
7423330e 241 prt_printf(out, "Has data:\t");
3f7b9713 242 if (data_have)
e58f963c 243 prt_bitflags(out, __bch2_data_types, data_have);
3f7b9713
HS
244 else
245 prt_printf(out, "(none)");
246 prt_newline(out);
247
018b32a6
KO
248 prt_printf(out, "Btree allocated bitmap blocksize:\t");
249 prt_units_u64(out, 1ULL << m.btree_bitmap_shift);
250 prt_newline(out);
251
252 prt_printf(out, "Btree allocated bitmap:\t");
253 bch2_prt_u64_base2_nbits(out, le64_to_cpu(m.btree_allocated_bitmap), 64);
254 prt_newline(out);
255
7423330e 256 prt_printf(out, "Durability:\t%llu\n", BCH_MEMBER_DURABILITY(&m) ? BCH_MEMBER_DURABILITY(&m) - 1 : 1);
d05db127 257
7423330e
KO
258 prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(&m));
259 prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(&m));
3f7b9713
HS
260
261 printbuf_indent_sub(out, 2);
262}
263
a5c3e265
KO
264static int bch2_sb_members_v1_validate(struct bch_sb *sb, struct bch_sb_field *f,
265 enum bch_validate_flags flags, struct printbuf *err)
fb8e5b4c 266{
9af26120 267 struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
fb8e5b4c
KO
268 unsigned i;
269
5c1ab40e 270 if ((void *) members_v1_get_mut(mi, sb->nr_devices) > vstruct_end(&mi->field)) {
fb8e5b4c
KO
271 prt_printf(err, "too many devices for section size");
272 return -BCH_ERR_invalid_sb_members;
273 }
274
275 for (i = 0; i < sb->nr_devices; i++) {
3f7b9713 276 struct bch_member m = members_v1_get(mi, i);
fb8e5b4c 277
3f7b9713
HS
278 int ret = validate_member(err, m, sb, i);
279 if (ret)
280 return ret;
fb8e5b4c
KO
281 }
282
283 return 0;
284}
285
3f7b9713
HS
286static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
287 struct bch_sb_field *f)
fb8e5b4c 288{
9af26120 289 struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
4637429e 290 struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
fb8e5b4c
KO
291 unsigned i;
292
dc7a15fb
KO
293 for (i = 0; i < sb->nr_devices; i++)
294 member_to_text(out, members_v1_get(mi, i), gi, sb, i);
3f7b9713 295}
fb8e5b4c 296
9af26120 297const struct bch_sb_field_ops bch_sb_field_ops_members_v1 = {
3f7b9713
HS
298 .validate = bch2_sb_members_v1_validate,
299 .to_text = bch2_sb_members_v1_to_text,
300};
fb8e5b4c 301
3f7b9713
HS
302static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb,
303 struct bch_sb_field *f)
304{
305 struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2);
4637429e 306 struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
3f7b9713 307 unsigned i;
fb8e5b4c 308
dc7a15fb
KO
309 for (i = 0; i < sb->nr_devices; i++)
310 member_to_text(out, members_v2_get(mi, i), gi, sb, i);
3f7b9713
HS
311}
312
a5c3e265
KO
313static int bch2_sb_members_v2_validate(struct bch_sb *sb, struct bch_sb_field *f,
314 enum bch_validate_flags flags, struct printbuf *err)
3f7b9713
HS
315{
316 struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2);
0f0fc312 317 size_t mi_bytes = (void *) __bch2_members_v2_get_mut(mi, sb->nr_devices) -
3f7b9713 318 (void *) mi;
fb8e5b4c 319
3f7b9713
HS
320 if (mi_bytes > vstruct_bytes(&mi->field)) {
321 prt_printf(err, "section too small (%zu > %zu)",
322 mi_bytes, vstruct_bytes(&mi->field));
323 return -BCH_ERR_invalid_sb_members;
324 }
fb8e5b4c 325
3f7b9713
HS
326 for (unsigned i = 0; i < sb->nr_devices; i++) {
327 int ret = validate_member(err, members_v2_get(mi, i), sb, i);
328 if (ret)
329 return ret;
fb8e5b4c 330 }
3f7b9713
HS
331
332 return 0;
fb8e5b4c
KO
333}
334
3f7b9713
HS
335const struct bch_sb_field_ops bch_sb_field_ops_members_v2 = {
336 .validate = bch2_sb_members_v2_validate,
337 .to_text = bch2_sb_members_v2_to_text,
fb8e5b4c 338};
94119eeb
KO
339
340void bch2_sb_members_from_cpu(struct bch_fs *c)
341{
342 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
94119eeb
KO
343
344 rcu_read_lock();
41b84fb4
KO
345 for_each_member_device_rcu(c, ca, NULL) {
346 struct bch_member *m = __bch2_members_v2_get_mut(mi, ca->dev_idx);
94119eeb 347
41b84fb4 348 for (unsigned e = 0; e < BCH_MEMBER_ERROR_NR; e++)
94119eeb
KO
349 m->errors[e] = cpu_to_le64(atomic64_read(&ca->errors[e]));
350 }
351 rcu_read_unlock();
352}
353
354void bch2_dev_io_errors_to_text(struct printbuf *out, struct bch_dev *ca)
355{
356 struct bch_fs *c = ca->fs;
357 struct bch_member m;
358
359 mutex_lock(&ca->fs->sb_lock);
360 m = bch2_sb_member_get(c->disk_sb.sb, ca->dev_idx);
361 mutex_unlock(&ca->fs->sb_lock);
362
363 printbuf_tabstop_push(out, 12);
364
365 prt_str(out, "IO errors since filesystem creation");
366 prt_newline(out);
367
368 printbuf_indent_add(out, 2);
7423330e
KO
369 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++)
370 prt_printf(out, "%s:\t%llu\n", bch2_member_error_strs[i], atomic64_read(&ca->errors[i]));
94119eeb
KO
371 printbuf_indent_sub(out, 2);
372
373 prt_str(out, "IO errors since ");
374 bch2_pr_time_units(out, (ktime_get_real_seconds() - le64_to_cpu(m.errors_reset_time)) * NSEC_PER_SEC);
375 prt_str(out, " ago");
376 prt_newline(out);
377
378 printbuf_indent_add(out, 2);
7423330e
KO
379 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++)
380 prt_printf(out, "%s:\t%llu\n", bch2_member_error_strs[i],
381 atomic64_read(&ca->errors[i]) - le64_to_cpu(m.errors_at_reset[i]));
94119eeb
KO
382 printbuf_indent_sub(out, 2);
383}
384
385void bch2_dev_errors_reset(struct bch_dev *ca)
386{
387 struct bch_fs *c = ca->fs;
388 struct bch_member *m;
389
390 mutex_lock(&c->sb_lock);
391 m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
392 for (unsigned i = 0; i < ARRAY_SIZE(m->errors_at_reset); i++)
393 m->errors_at_reset[i] = cpu_to_le64(atomic64_read(&ca->errors[i]));
04eb5793 394 m->errors_reset_time = cpu_to_le64(ktime_get_real_seconds());
94119eeb
KO
395
396 bch2_write_super(c);
397 mutex_unlock(&c->sb_lock);
398}
27c15ed2
KO
399
400/*
401 * Per member "range has btree nodes" bitmap:
402 *
403 * This is so that if we ever have to run the btree node scan to repair we don't
404 * have to scan full devices:
405 */
406
407bool bch2_dev_btree_bitmap_marked(struct bch_fs *c, struct bkey_s_c k)
408{
13a16dab
KO
409 bool ret = true;
410 rcu_read_lock();
411 bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) {
412 struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev);
413 if (!ca)
414 continue;
415
416 if (!bch2_dev_btree_bitmap_marked_sectors(ca, ptr->offset, btree_sectors(c))) {
417 ret = false;
418 break;
419 }
420 }
421 rcu_read_unlock();
422 return ret;
27c15ed2
KO
423}
424
425static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, unsigned dev,
426 u64 start, unsigned sectors)
427{
428 struct bch_member *m = __bch2_members_v2_get_mut(mi, dev);
429 u64 bitmap = le64_to_cpu(m->btree_allocated_bitmap);
430
431 u64 end = start + sectors;
432
433 int resize = ilog2(roundup_pow_of_two(end)) - (m->btree_bitmap_shift + 6);
434 if (resize > 0) {
435 u64 new_bitmap = 0;
436
437 for (unsigned i = 0; i < 64; i++)
438 if (bitmap & BIT_ULL(i))
439 new_bitmap |= BIT_ULL(i >> resize);
440 bitmap = new_bitmap;
441 m->btree_bitmap_shift += resize;
442 }
443
60f2b1bc
KO
444 BUG_ON(m->btree_bitmap_shift > 57);
445 BUG_ON(end > 64ULL << m->btree_bitmap_shift);
446
fa845c73
KO
447 for (unsigned bit = start >> m->btree_bitmap_shift;
448 (u64) bit << m->btree_bitmap_shift < end;
27c15ed2
KO
449 bit++)
450 bitmap |= BIT_ULL(bit);
451
452 m->btree_allocated_bitmap = cpu_to_le64(bitmap);
453}
454
455void bch2_dev_btree_bitmap_mark(struct bch_fs *c, struct bkey_s_c k)
456{
457 lockdep_assert_held(&c->sb_lock);
458
459 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
13a16dab
KO
460 bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) {
461 if (!bch2_member_exists(c->disk_sb.sb, ptr->dev))
462 continue;
463
27c15ed2 464 __bch2_dev_btree_bitmap_mark(mi, ptr->dev, ptr->offset, btree_sectors(c));
13a16dab 465 }
27c15ed2 466}