]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/replicas.c
Update bcachefs sources to a9f14c773f bcachefs: More btree gc refactorings
[bcachefs-tools-debian] / libbcachefs / replicas.c
1
2 #include "bcachefs.h"
3 #include "replicas.h"
4 #include "super-io.h"
5
6 struct bch_replicas_entry_padded {
7         struct bch_replicas_entry       e;
8         u8                              pad[BCH_SB_MEMBERS_MAX];
9 };
10
11 static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *,
12                                             struct bch_replicas_cpu *);
13
14 /* Replicas tracking - in memory: */
15
16 static inline int u8_cmp(u8 l, u8 r)
17 {
18         return (l > r) - (l < r);
19 }
20
21 static void replicas_entry_sort(struct bch_replicas_entry *e)
22 {
23         bubble_sort(e->devs, e->nr_devs, u8_cmp);
24 }
25
26 #define for_each_cpu_replicas_entry(_r, _i)                             \
27         for (_i = (_r)->entries;                                        \
28              (void *) (_i) < (void *) (_r)->entries + (_r)->nr * (_r)->entry_size;\
29              _i = (void *) (_i) + (_r)->entry_size)
30
31 static inline struct bch_replicas_entry *
32 cpu_replicas_entry(struct bch_replicas_cpu *r, unsigned i)
33 {
34         return (void *) r->entries + r->entry_size * i;
35 }
36
37 static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
38 {
39         eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
40 }
41
42 static void replicas_entry_to_text(struct printbuf *out,
43                                   struct bch_replicas_entry *e)
44 {
45         unsigned i;
46
47         pr_buf(out, "%s: %u/%u [",
48                bch2_data_types[e->data_type],
49                e->nr_required,
50                e->nr_devs);
51
52         for (i = 0; i < e->nr_devs; i++)
53                 pr_buf(out, i ? " %u" : "%u", e->devs[i]);
54         pr_buf(out, "]");
55 }
56
57 void bch2_cpu_replicas_to_text(struct printbuf *out,
58                               struct bch_replicas_cpu *r)
59 {
60         struct bch_replicas_entry *e;
61         bool first = true;
62
63         for_each_cpu_replicas_entry(r, e) {
64                 if (!first)
65                         pr_buf(out, " ");
66                 first = false;
67
68                 replicas_entry_to_text(out, e);
69         }
70 }
71
72 static void extent_to_replicas(struct bkey_s_c k,
73                                struct bch_replicas_entry *r)
74 {
75         if (bkey_extent_is_data(k.k)) {
76                 struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
77                 const union bch_extent_entry *entry;
78                 struct extent_ptr_decoded p;
79
80                 r->nr_required  = 1;
81
82                 extent_for_each_ptr_decode(e, p, entry)
83                         if (!p.ptr.cached)
84                                 r->devs[r->nr_devs++] = p.ptr.dev;
85         }
86 }
87
88 static void bkey_to_replicas(enum bkey_type type,
89                              struct bkey_s_c k,
90                              struct bch_replicas_entry *e)
91 {
92         e->nr_devs = 0;
93
94         switch (type) {
95         case BKEY_TYPE_BTREE:
96                 e->data_type = BCH_DATA_BTREE;
97                 extent_to_replicas(k, e);
98                 break;
99         case BKEY_TYPE_EXTENTS:
100                 e->data_type = BCH_DATA_USER;
101                 extent_to_replicas(k, e);
102                 break;
103         default:
104                 break;
105         }
106
107         replicas_entry_sort(e);
108 }
109
110 static inline void devlist_to_replicas(struct bch_devs_list devs,
111                                        enum bch_data_type data_type,
112                                        struct bch_replicas_entry *e)
113 {
114         unsigned i;
115
116         BUG_ON(!data_type ||
117                data_type == BCH_DATA_SB ||
118                data_type >= BCH_DATA_NR);
119
120         e->data_type    = data_type;
121         e->nr_devs      = 0;
122         e->nr_required  = 1;
123
124         for (i = 0; i < devs.nr; i++)
125                 e->devs[e->nr_devs++] = devs.devs[i];
126
127         replicas_entry_sort(e);
128 }
129
130 static struct bch_replicas_cpu *
131 cpu_replicas_add_entry(struct bch_replicas_cpu *old,
132                        struct bch_replicas_entry *new_entry)
133 {
134         struct bch_replicas_cpu *new;
135         unsigned i, nr, entry_size;
136
137         entry_size = max_t(unsigned, old->entry_size,
138                            replicas_entry_bytes(new_entry));
139         nr = old->nr + 1;
140
141         new = kzalloc(sizeof(struct bch_replicas_cpu) +
142                       nr * entry_size, GFP_NOIO);
143         if (!new)
144                 return NULL;
145
146         new->nr         = nr;
147         new->entry_size = entry_size;
148
149         for (i = 0; i < old->nr; i++)
150                 memcpy(cpu_replicas_entry(new, i),
151                        cpu_replicas_entry(old, i),
152                        old->entry_size);
153
154         memcpy(cpu_replicas_entry(new, old->nr),
155                new_entry,
156                replicas_entry_bytes(new_entry));
157
158         bch2_cpu_replicas_sort(new);
159         return new;
160 }
161
162 static bool __replicas_has_entry(struct bch_replicas_cpu *r,
163                                  struct bch_replicas_entry *search)
164 {
165         return replicas_entry_bytes(search) <= r->entry_size &&
166                 eytzinger0_find(r->entries, r->nr,
167                                 r->entry_size,
168                                 memcmp, search) < r->nr;
169 }
170
171 static bool replicas_has_entry(struct bch_fs *c,
172                                struct bch_replicas_entry *search,
173                                bool check_gc_replicas)
174 {
175         struct bch_replicas_cpu *r, *gc_r;
176         bool marked;
177
178         rcu_read_lock();
179         r = rcu_dereference(c->replicas);
180         marked = __replicas_has_entry(r, search) &&
181                 (!check_gc_replicas ||
182                  likely(!(gc_r = rcu_dereference(c->replicas_gc))) ||
183                  __replicas_has_entry(gc_r, search));
184         rcu_read_unlock();
185
186         return marked;
187 }
188
189 noinline
190 static int bch2_mark_replicas_slowpath(struct bch_fs *c,
191                                 struct bch_replicas_entry *new_entry)
192 {
193         struct bch_replicas_cpu *old_gc, *new_gc = NULL, *old_r, *new_r = NULL;
194         int ret = -ENOMEM;
195
196         mutex_lock(&c->sb_lock);
197
198         old_gc = rcu_dereference_protected(c->replicas_gc,
199                                            lockdep_is_held(&c->sb_lock));
200         if (old_gc && !__replicas_has_entry(old_gc, new_entry)) {
201                 new_gc = cpu_replicas_add_entry(old_gc, new_entry);
202                 if (!new_gc)
203                         goto err;
204         }
205
206         old_r = rcu_dereference_protected(c->replicas,
207                                           lockdep_is_held(&c->sb_lock));
208         if (!__replicas_has_entry(old_r, new_entry)) {
209                 new_r = cpu_replicas_add_entry(old_r, new_entry);
210                 if (!new_r)
211                         goto err;
212
213                 ret = bch2_cpu_replicas_to_sb_replicas(c, new_r);
214                 if (ret)
215                         goto err;
216         }
217
218         /* allocations done, now commit: */
219
220         if (new_r)
221                 bch2_write_super(c);
222
223         /* don't update in memory replicas until changes are persistent */
224
225         if (new_gc) {
226                 rcu_assign_pointer(c->replicas_gc, new_gc);
227                 kfree_rcu(old_gc, rcu);
228         }
229
230         if (new_r) {
231                 rcu_assign_pointer(c->replicas, new_r);
232                 kfree_rcu(old_r, rcu);
233         }
234
235         mutex_unlock(&c->sb_lock);
236         return 0;
237 err:
238         mutex_unlock(&c->sb_lock);
239         kfree(new_gc);
240         kfree(new_r);
241         return ret;
242 }
243
244 static int __bch2_mark_replicas(struct bch_fs *c,
245                                 struct bch_replicas_entry *devs)
246 {
247         return likely(replicas_has_entry(c, devs, true))
248                 ? 0
249                 : bch2_mark_replicas_slowpath(c, devs);
250 }
251
252 int bch2_mark_replicas(struct bch_fs *c,
253                        enum bch_data_type data_type,
254                        struct bch_devs_list devs)
255 {
256         struct bch_replicas_entry_padded search;
257
258         if (!devs.nr)
259                 return 0;
260
261         memset(&search, 0, sizeof(search));
262
263         BUG_ON(devs.nr >= BCH_REPLICAS_MAX);
264
265         devlist_to_replicas(devs, data_type, &search.e);
266
267         return __bch2_mark_replicas(c, &search.e);
268 }
269
270 int bch2_mark_bkey_replicas(struct bch_fs *c,
271                             enum bkey_type type,
272                             struct bkey_s_c k)
273 {
274         struct bch_replicas_entry_padded search;
275         int ret;
276
277         memset(&search, 0, sizeof(search));
278
279         if (type == BKEY_TYPE_EXTENTS) {
280                 struct bch_devs_list cached = bch2_bkey_cached_devs(k);
281                 unsigned i;
282
283                 for (i = 0; i < cached.nr; i++)
284                         if ((ret = bch2_mark_replicas(c, BCH_DATA_CACHED,
285                                                 bch2_dev_list_single(cached.devs[i]))))
286                                 return ret;
287         }
288
289         bkey_to_replicas(type, k, &search.e);
290
291         return search.e.nr_devs
292                 ? __bch2_mark_replicas(c, &search.e)
293                 : 0;
294 }
295
296 int bch2_replicas_gc_end(struct bch_fs *c, int ret)
297 {
298         struct bch_replicas_cpu *new_r, *old_r;
299
300         lockdep_assert_held(&c->replicas_gc_lock);
301
302         mutex_lock(&c->sb_lock);
303
304         new_r = rcu_dereference_protected(c->replicas_gc,
305                                           lockdep_is_held(&c->sb_lock));
306         rcu_assign_pointer(c->replicas_gc, NULL);
307
308         if (ret)
309                 goto err;
310
311         if (bch2_cpu_replicas_to_sb_replicas(c, new_r)) {
312                 ret = -ENOSPC;
313                 goto err;
314         }
315
316         bch2_write_super(c);
317
318         /* don't update in memory replicas until changes are persistent */
319
320         old_r = rcu_dereference_protected(c->replicas,
321                                           lockdep_is_held(&c->sb_lock));
322
323         rcu_assign_pointer(c->replicas, new_r);
324         kfree_rcu(old_r, rcu);
325 out:
326         mutex_unlock(&c->sb_lock);
327         return ret;
328 err:
329         kfree_rcu(new_r, rcu);
330         goto out;
331 }
332
333 int bch2_replicas_gc_start(struct bch_fs *c, unsigned typemask)
334 {
335         struct bch_replicas_cpu *dst, *src;
336         struct bch_replicas_entry *e;
337
338         lockdep_assert_held(&c->replicas_gc_lock);
339
340         mutex_lock(&c->sb_lock);
341         BUG_ON(c->replicas_gc);
342
343         src = rcu_dereference_protected(c->replicas,
344                                         lockdep_is_held(&c->sb_lock));
345
346         dst = kzalloc(sizeof(struct bch_replicas_cpu) +
347                       src->nr * src->entry_size, GFP_NOIO);
348         if (!dst) {
349                 mutex_unlock(&c->sb_lock);
350                 return -ENOMEM;
351         }
352
353         dst->nr         = 0;
354         dst->entry_size = src->entry_size;
355
356         for_each_cpu_replicas_entry(src, e)
357                 if (!((1 << e->data_type) & typemask))
358                         memcpy(cpu_replicas_entry(dst, dst->nr++),
359                                e, dst->entry_size);
360
361         bch2_cpu_replicas_sort(dst);
362
363         rcu_assign_pointer(c->replicas_gc, dst);
364         mutex_unlock(&c->sb_lock);
365
366         return 0;
367 }
368
369 /* Replicas tracking - superblock: */
370
371 static struct bch_replicas_cpu *
372 __bch2_sb_replicas_to_cpu_replicas(struct bch_sb_field_replicas *sb_r)
373 {
374         struct bch_replicas_entry *e, *dst;
375         struct bch_replicas_cpu *cpu_r;
376         unsigned nr = 0, entry_size = 0, idx = 0;
377
378         for_each_replicas_entry(sb_r, e) {
379                 entry_size = max_t(unsigned, entry_size,
380                                    replicas_entry_bytes(e));
381                 nr++;
382         }
383
384         cpu_r = kzalloc(sizeof(struct bch_replicas_cpu) +
385                         nr * entry_size, GFP_NOIO);
386         if (!cpu_r)
387                 return NULL;
388
389         cpu_r->nr               = nr;
390         cpu_r->entry_size       = entry_size;
391
392         for_each_replicas_entry(sb_r, e) {
393                 dst = cpu_replicas_entry(cpu_r, idx++);
394                 memcpy(dst, e, replicas_entry_bytes(e));
395                 replicas_entry_sort(dst);
396         }
397
398         return cpu_r;
399 }
400
401 static struct bch_replicas_cpu *
402 __bch2_sb_replicas_v0_to_cpu_replicas(struct bch_sb_field_replicas_v0 *sb_r)
403 {
404         struct bch_replicas_entry_v0 *e;
405         struct bch_replicas_cpu *cpu_r;
406         unsigned nr = 0, entry_size = 0, idx = 0;
407
408         for_each_replicas_entry(sb_r, e) {
409                 entry_size = max_t(unsigned, entry_size,
410                                    replicas_entry_bytes(e));
411                 nr++;
412         }
413
414         entry_size += sizeof(struct bch_replicas_entry) -
415                 sizeof(struct bch_replicas_entry_v0);
416
417         cpu_r = kzalloc(sizeof(struct bch_replicas_cpu) +
418                         nr * entry_size, GFP_NOIO);
419         if (!cpu_r)
420                 return NULL;
421
422         cpu_r->nr               = nr;
423         cpu_r->entry_size       = entry_size;
424
425         for_each_replicas_entry(sb_r, e) {
426                 struct bch_replicas_entry *dst =
427                         cpu_replicas_entry(cpu_r, idx++);
428
429                 dst->data_type  = e->data_type;
430                 dst->nr_devs    = e->nr_devs;
431                 dst->nr_required = 1;
432                 memcpy(dst->devs, e->devs, e->nr_devs);
433                 replicas_entry_sort(dst);
434         }
435
436         return cpu_r;
437 }
438
439 int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c)
440 {
441         struct bch_sb_field_replicas *sb_v1;
442         struct bch_sb_field_replicas_v0 *sb_v0;
443         struct bch_replicas_cpu *cpu_r, *old_r;
444
445         if ((sb_v1 = bch2_sb_get_replicas(c->disk_sb.sb)))
446                 cpu_r = __bch2_sb_replicas_to_cpu_replicas(sb_v1);
447         else if ((sb_v0 = bch2_sb_get_replicas_v0(c->disk_sb.sb)))
448                 cpu_r = __bch2_sb_replicas_v0_to_cpu_replicas(sb_v0);
449         else
450                 cpu_r = kzalloc(sizeof(struct bch_replicas_cpu), GFP_NOIO);
451
452         if (!cpu_r)
453                 return -ENOMEM;
454
455         bch2_cpu_replicas_sort(cpu_r);
456
457         old_r = rcu_dereference_check(c->replicas, lockdep_is_held(&c->sb_lock));
458         rcu_assign_pointer(c->replicas, cpu_r);
459         if (old_r)
460                 kfree_rcu(old_r, rcu);
461
462         return 0;
463 }
464
465 static int bch2_cpu_replicas_to_sb_replicas_v0(struct bch_fs *c,
466                                                struct bch_replicas_cpu *r)
467 {
468         struct bch_sb_field_replicas_v0 *sb_r;
469         struct bch_replicas_entry_v0 *dst;
470         struct bch_replicas_entry *src;
471         size_t bytes;
472
473         bytes = sizeof(struct bch_sb_field_replicas);
474
475         for_each_cpu_replicas_entry(r, src)
476                 bytes += replicas_entry_bytes(src) - 1;
477
478         sb_r = bch2_sb_resize_replicas_v0(&c->disk_sb,
479                         DIV_ROUND_UP(bytes, sizeof(u64)));
480         if (!sb_r)
481                 return -ENOSPC;
482
483         bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas);
484         sb_r = bch2_sb_get_replicas_v0(c->disk_sb.sb);
485
486         memset(&sb_r->entries, 0,
487                vstruct_end(&sb_r->field) -
488                (void *) &sb_r->entries);
489
490         dst = sb_r->entries;
491         for_each_cpu_replicas_entry(r, src) {
492                 dst->data_type  = src->data_type;
493                 dst->nr_devs    = src->nr_devs;
494                 memcpy(dst->devs, src->devs, src->nr_devs);
495
496                 dst = replicas_entry_next(dst);
497
498                 BUG_ON((void *) dst > vstruct_end(&sb_r->field));
499         }
500
501         return 0;
502 }
503
504 static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *c,
505                                             struct bch_replicas_cpu *r)
506 {
507         struct bch_sb_field_replicas *sb_r;
508         struct bch_replicas_entry *dst, *src;
509         bool need_v1 = false;
510         size_t bytes;
511
512         bytes = sizeof(struct bch_sb_field_replicas);
513
514         for_each_cpu_replicas_entry(r, src) {
515                 bytes += replicas_entry_bytes(src);
516                 if (src->nr_required != 1)
517                         need_v1 = true;
518         }
519
520         if (!need_v1)
521                 return bch2_cpu_replicas_to_sb_replicas_v0(c, r);
522
523         sb_r = bch2_sb_resize_replicas(&c->disk_sb,
524                         DIV_ROUND_UP(bytes, sizeof(u64)));
525         if (!sb_r)
526                 return -ENOSPC;
527
528         bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas_v0);
529         sb_r = bch2_sb_get_replicas(c->disk_sb.sb);
530
531         memset(&sb_r->entries, 0,
532                vstruct_end(&sb_r->field) -
533                (void *) &sb_r->entries);
534
535         dst = sb_r->entries;
536         for_each_cpu_replicas_entry(r, src) {
537                 memcpy(dst, src, replicas_entry_bytes(src));
538
539                 dst = replicas_entry_next(dst);
540
541                 BUG_ON((void *) dst > vstruct_end(&sb_r->field));
542         }
543
544         return 0;
545 }
546
547 static const char *check_dup_replicas_entries(struct bch_replicas_cpu *cpu_r)
548 {
549         unsigned i;
550
551         sort_cmp_size(cpu_r->entries,
552                       cpu_r->nr,
553                       cpu_r->entry_size,
554                       memcmp, NULL);
555
556         for (i = 0; i + 1 < cpu_r->nr; i++) {
557                 struct bch_replicas_entry *l =
558                         cpu_replicas_entry(cpu_r, i);
559                 struct bch_replicas_entry *r =
560                         cpu_replicas_entry(cpu_r, i + 1);
561
562                 BUG_ON(memcmp(l, r, cpu_r->entry_size) > 0);
563
564                 if (!memcmp(l, r, cpu_r->entry_size))
565                         return "duplicate replicas entry";
566         }
567
568         return NULL;
569 }
570
571 static const char *bch2_sb_validate_replicas(struct bch_sb *sb, struct bch_sb_field *f)
572 {
573         struct bch_sb_field_replicas *sb_r = field_to_type(f, replicas);
574         struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
575         struct bch_replicas_cpu *cpu_r = NULL;
576         struct bch_replicas_entry *e;
577         const char *err;
578         unsigned i;
579
580         for_each_replicas_entry(sb_r, e) {
581                 err = "invalid replicas entry: invalid data type";
582                 if (e->data_type >= BCH_DATA_NR)
583                         goto err;
584
585                 err = "invalid replicas entry: no devices";
586                 if (!e->nr_devs)
587                         goto err;
588
589                 err = "invalid replicas entry: bad nr_required";
590                 if (!e->nr_required ||
591                     (e->nr_required > 1 &&
592                      e->nr_required >= e->nr_devs))
593                         goto err;
594
595                 err = "invalid replicas entry: invalid device";
596                 for (i = 0; i < e->nr_devs; i++)
597                         if (!bch2_dev_exists(sb, mi, e->devs[i]))
598                                 goto err;
599         }
600
601         err = "cannot allocate memory";
602         cpu_r = __bch2_sb_replicas_to_cpu_replicas(sb_r);
603         if (!cpu_r)
604                 goto err;
605
606         err = check_dup_replicas_entries(cpu_r);
607 err:
608         kfree(cpu_r);
609         return err;
610 }
611
612 static void bch2_sb_replicas_to_text(struct printbuf *out,
613                                      struct bch_sb *sb,
614                                      struct bch_sb_field *f)
615 {
616         struct bch_sb_field_replicas *r = field_to_type(f, replicas);
617         struct bch_replicas_entry *e;
618         bool first = true;
619
620         for_each_replicas_entry(r, e) {
621                 if (!first)
622                         pr_buf(out, " ");
623                 first = false;
624
625                 replicas_entry_to_text(out, e);
626         }
627 }
628
629 const struct bch_sb_field_ops bch_sb_field_ops_replicas = {
630         .validate       = bch2_sb_validate_replicas,
631         .to_text        = bch2_sb_replicas_to_text,
632 };
633
634 static const char *bch2_sb_validate_replicas_v0(struct bch_sb *sb, struct bch_sb_field *f)
635 {
636         struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
637         struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
638         struct bch_replicas_cpu *cpu_r = NULL;
639         struct bch_replicas_entry_v0 *e;
640         const char *err;
641         unsigned i;
642
643         for_each_replicas_entry_v0(sb_r, e) {
644                 err = "invalid replicas entry: invalid data type";
645                 if (e->data_type >= BCH_DATA_NR)
646                         goto err;
647
648                 err = "invalid replicas entry: no devices";
649                 if (!e->nr_devs)
650                         goto err;
651
652                 err = "invalid replicas entry: invalid device";
653                 for (i = 0; i < e->nr_devs; i++)
654                         if (!bch2_dev_exists(sb, mi, e->devs[i]))
655                                 goto err;
656         }
657
658         err = "cannot allocate memory";
659         cpu_r = __bch2_sb_replicas_v0_to_cpu_replicas(sb_r);
660         if (!cpu_r)
661                 goto err;
662
663         err = check_dup_replicas_entries(cpu_r);
664 err:
665         kfree(cpu_r);
666         return err;
667 }
668
669 const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0 = {
670         .validate       = bch2_sb_validate_replicas_v0,
671 };
672
673 /* Query replicas: */
674
675 bool bch2_replicas_marked(struct bch_fs *c,
676                           enum bch_data_type data_type,
677                           struct bch_devs_list devs,
678                           bool check_gc_replicas)
679 {
680         struct bch_replicas_entry_padded search;
681
682         if (!devs.nr)
683                 return true;
684
685         memset(&search, 0, sizeof(search));
686
687         devlist_to_replicas(devs, data_type, &search.e);
688
689         return replicas_has_entry(c, &search.e, check_gc_replicas);
690 }
691
692 bool bch2_bkey_replicas_marked(struct bch_fs *c,
693                                enum bkey_type type,
694                                struct bkey_s_c k,
695                                bool check_gc_replicas)
696 {
697         struct bch_replicas_entry_padded search;
698
699         memset(&search, 0, sizeof(search));
700
701         if (type == BKEY_TYPE_EXTENTS) {
702                 struct bch_devs_list cached = bch2_bkey_cached_devs(k);
703                 unsigned i;
704
705                 for (i = 0; i < cached.nr; i++)
706                         if (!bch2_replicas_marked(c, BCH_DATA_CACHED,
707                                         bch2_dev_list_single(cached.devs[i]),
708                                         check_gc_replicas))
709                                 return false;
710         }
711
712         bkey_to_replicas(type, k, &search.e);
713
714         return search.e.nr_devs
715                 ? replicas_has_entry(c, &search.e, check_gc_replicas)
716                 : true;
717 }
718
719 struct replicas_status __bch2_replicas_status(struct bch_fs *c,
720                                               struct bch_devs_mask online_devs)
721 {
722         struct bch_sb_field_members *mi;
723         struct bch_replicas_entry *e;
724         struct bch_replicas_cpu *r;
725         unsigned i, nr_online, nr_offline;
726         struct replicas_status ret;
727
728         memset(&ret, 0, sizeof(ret));
729
730         for (i = 0; i < ARRAY_SIZE(ret.replicas); i++)
731                 ret.replicas[i].redundancy = INT_MAX;
732
733         mi = bch2_sb_get_members(c->disk_sb.sb);
734         rcu_read_lock();
735         r = rcu_dereference(c->replicas);
736
737         for_each_cpu_replicas_entry(r, e) {
738                 if (e->data_type >= ARRAY_SIZE(ret.replicas))
739                         panic("e %p data_type %u\n", e, e->data_type);
740
741                 nr_online = nr_offline = 0;
742
743                 for (i = 0; i < e->nr_devs; i++) {
744                         BUG_ON(!bch2_dev_exists(c->disk_sb.sb, mi,
745                                                 e->devs[i]));
746
747                         if (test_bit(e->devs[i], online_devs.d))
748                                 nr_online++;
749                         else
750                                 nr_offline++;
751                 }
752
753                 ret.replicas[e->data_type].redundancy =
754                         min(ret.replicas[e->data_type].redundancy,
755                             (int) nr_online - (int) e->nr_required);
756
757                 ret.replicas[e->data_type].nr_offline =
758                         max(ret.replicas[e->data_type].nr_offline,
759                             nr_offline);
760         }
761
762         rcu_read_unlock();
763
764         for (i = 0; i < ARRAY_SIZE(ret.replicas); i++)
765                 if (ret.replicas[i].redundancy == INT_MAX)
766                         ret.replicas[i].redundancy = 0;
767
768         return ret;
769 }
770
771 struct replicas_status bch2_replicas_status(struct bch_fs *c)
772 {
773         return __bch2_replicas_status(c, bch2_online_devs(c));
774 }
775
776 static bool have_enough_devs(struct replicas_status s,
777                              enum bch_data_type type,
778                              bool force_if_degraded,
779                              bool force_if_lost)
780 {
781         return (!s.replicas[type].nr_offline || force_if_degraded) &&
782                 (s.replicas[type].redundancy >= 0 || force_if_lost);
783 }
784
785 bool bch2_have_enough_devs(struct replicas_status s, unsigned flags)
786 {
787         return (have_enough_devs(s, BCH_DATA_JOURNAL,
788                                  flags & BCH_FORCE_IF_METADATA_DEGRADED,
789                                  flags & BCH_FORCE_IF_METADATA_LOST) &&
790                 have_enough_devs(s, BCH_DATA_BTREE,
791                                  flags & BCH_FORCE_IF_METADATA_DEGRADED,
792                                  flags & BCH_FORCE_IF_METADATA_LOST) &&
793                 have_enough_devs(s, BCH_DATA_USER,
794                                  flags & BCH_FORCE_IF_DATA_DEGRADED,
795                                  flags & BCH_FORCE_IF_DATA_LOST));
796 }
797
798 int bch2_replicas_online(struct bch_fs *c, bool meta)
799 {
800         struct replicas_status s = bch2_replicas_status(c);
801
802         return (meta
803                 ? min(s.replicas[BCH_DATA_JOURNAL].redundancy,
804                       s.replicas[BCH_DATA_BTREE].redundancy)
805                 : s.replicas[BCH_DATA_USER].redundancy) + 1;
806 }
807
808 unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
809 {
810         struct bch_replicas_entry *e;
811         struct bch_replicas_cpu *r;
812         unsigned i, ret = 0;
813
814         rcu_read_lock();
815         r = rcu_dereference(c->replicas);
816
817         for_each_cpu_replicas_entry(r, e)
818                 for (i = 0; i < e->nr_devs; i++)
819                         if (e->devs[i] == ca->dev_idx)
820                                 ret |= 1 << e->data_type;
821
822         rcu_read_unlock();
823
824         return ret;
825 }