]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/backpointers.c
Update bcachefs sources to c3e4d892b77b mean and variance: Promote to lib/math
[bcachefs-tools-debian] / libbcachefs / backpointers.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include "bcachefs.h"
3 #include "bbpos.h"
4 #include "alloc_background.h"
5 #include "backpointers.h"
6 #include "btree_cache.h"
7 #include "btree_update.h"
8 #include "btree_update_interior.h"
9 #include "btree_write_buffer.h"
10 #include "error.h"
11
12 #include <linux/mm.h>
13
14 static bool extent_matches_bp(struct bch_fs *c,
15                               enum btree_id btree_id, unsigned level,
16                               struct bkey_s_c k,
17                               struct bpos bucket,
18                               struct bch_backpointer bp)
19 {
20         struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
21         const union bch_extent_entry *entry;
22         struct extent_ptr_decoded p;
23
24         bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
25                 struct bpos bucket2;
26                 struct bch_backpointer bp2;
27
28                 if (p.ptr.cached)
29                         continue;
30
31                 bch2_extent_ptr_to_bp(c, btree_id, level, k, p,
32                                       &bucket2, &bp2);
33                 if (bpos_eq(bucket, bucket2) &&
34                     !memcmp(&bp, &bp2, sizeof(bp)))
35                         return true;
36         }
37
38         return false;
39 }
40
41 int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
42                              enum bkey_invalid_flags flags,
43                              struct printbuf *err)
44 {
45         struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
46         struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
47         int ret = 0;
48
49         bkey_fsck_err_on(!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
50                          c, err,
51                          backpointer_pos_wrong,
52                          "backpointer at wrong pos");
53 fsck_err:
54         return ret;
55 }
56
57 void bch2_backpointer_to_text(struct printbuf *out, const struct bch_backpointer *bp)
58 {
59         prt_printf(out, "btree=%s l=%u offset=%llu:%u len=%u pos=",
60                bch2_btree_id_str(bp->btree_id),
61                bp->level,
62                (u64) (bp->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT),
63                (u32) bp->bucket_offset & ~(~0U << MAX_EXTENT_COMPRESS_RATIO_SHIFT),
64                bp->bucket_len);
65         bch2_bpos_to_text(out, bp->pos);
66 }
67
68 void bch2_backpointer_k_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
69 {
70         prt_str(out, "bucket=");
71         bch2_bpos_to_text(out, bp_pos_to_bucket(c, k.k->p));
72         prt_str(out, " ");
73
74         bch2_backpointer_to_text(out, bkey_s_c_to_backpointer(k).v);
75 }
76
77 void bch2_backpointer_swab(struct bkey_s k)
78 {
79         struct bkey_s_backpointer bp = bkey_s_to_backpointer(k);
80
81         bp.v->bucket_offset     = swab40(bp.v->bucket_offset);
82         bp.v->bucket_len        = swab32(bp.v->bucket_len);
83         bch2_bpos_swab(&bp.v->pos);
84 }
85
86 static noinline int backpointer_mod_err(struct btree_trans *trans,
87                                         struct bch_backpointer bp,
88                                         struct bkey_s_c bp_k,
89                                         struct bkey_s_c orig_k,
90                                         bool insert)
91 {
92         struct bch_fs *c = trans->c;
93         struct printbuf buf = PRINTBUF;
94
95         if (insert) {
96                 prt_printf(&buf, "existing backpointer found when inserting ");
97                 bch2_backpointer_to_text(&buf, &bp);
98                 prt_newline(&buf);
99                 printbuf_indent_add(&buf, 2);
100
101                 prt_printf(&buf, "found ");
102                 bch2_bkey_val_to_text(&buf, c, bp_k);
103                 prt_newline(&buf);
104
105                 prt_printf(&buf, "for ");
106                 bch2_bkey_val_to_text(&buf, c, orig_k);
107
108                 bch_err(c, "%s", buf.buf);
109         } else if (c->curr_recovery_pass > BCH_RECOVERY_PASS_check_extents_to_backpointers) {
110                 prt_printf(&buf, "backpointer not found when deleting");
111                 prt_newline(&buf);
112                 printbuf_indent_add(&buf, 2);
113
114                 prt_printf(&buf, "searching for ");
115                 bch2_backpointer_to_text(&buf, &bp);
116                 prt_newline(&buf);
117
118                 prt_printf(&buf, "got ");
119                 bch2_bkey_val_to_text(&buf, c, bp_k);
120                 prt_newline(&buf);
121
122                 prt_printf(&buf, "for ");
123                 bch2_bkey_val_to_text(&buf, c, orig_k);
124
125                 bch_err(c, "%s", buf.buf);
126         }
127
128         printbuf_exit(&buf);
129
130         if (c->curr_recovery_pass > BCH_RECOVERY_PASS_check_extents_to_backpointers) {
131                 bch2_inconsistent_error(c);
132                 return -EIO;
133         } else {
134                 return 0;
135         }
136 }
137
138 int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
139                                 struct bpos bucket,
140                                 struct bch_backpointer bp,
141                                 struct bkey_s_c orig_k,
142                                 bool insert)
143 {
144         struct btree_iter bp_iter;
145         struct bkey_s_c k;
146         struct bkey_i_backpointer *bp_k;
147         int ret;
148
149         bp_k = bch2_trans_kmalloc_nomemzero(trans, sizeof(struct bkey_i_backpointer));
150         ret = PTR_ERR_OR_ZERO(bp_k);
151         if (ret)
152                 return ret;
153
154         bkey_backpointer_init(&bp_k->k_i);
155         bp_k->k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
156         bp_k->v = bp;
157
158         if (!insert) {
159                 bp_k->k.type = KEY_TYPE_deleted;
160                 set_bkey_val_u64s(&bp_k->k, 0);
161         }
162
163         k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
164                                bp_k->k.p,
165                                BTREE_ITER_INTENT|
166                                BTREE_ITER_SLOTS|
167                                BTREE_ITER_WITH_UPDATES);
168         ret = bkey_err(k);
169         if (ret)
170                 goto err;
171
172         if (insert
173             ? k.k->type
174             : (k.k->type != KEY_TYPE_backpointer ||
175                memcmp(bkey_s_c_to_backpointer(k).v, &bp, sizeof(bp)))) {
176                 ret = backpointer_mod_err(trans, bp, k, orig_k, insert);
177                 if (ret)
178                         goto err;
179         }
180
181         ret = bch2_trans_update(trans, &bp_iter, &bp_k->k_i, 0);
182 err:
183         bch2_trans_iter_exit(trans, &bp_iter);
184         return ret;
185 }
186
187 /*
188  * Find the next backpointer >= *bp_offset:
189  */
190 int bch2_get_next_backpointer(struct btree_trans *trans,
191                               struct bpos bucket, int gen,
192                               struct bpos *bp_pos,
193                               struct bch_backpointer *bp,
194                               unsigned iter_flags)
195 {
196         struct bch_fs *c = trans->c;
197         struct bpos bp_end_pos = bucket_pos_to_bp(c, bpos_nosnap_successor(bucket), 0);
198         struct btree_iter alloc_iter = { NULL }, bp_iter = { NULL };
199         struct bkey_s_c k;
200         int ret = 0;
201
202         if (bpos_ge(*bp_pos, bp_end_pos))
203                 goto done;
204
205         if (gen >= 0) {
206                 k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc,
207                                        bucket, BTREE_ITER_CACHED|iter_flags);
208                 ret = bkey_err(k);
209                 if (ret)
210                         goto out;
211
212                 if (k.k->type != KEY_TYPE_alloc_v4 ||
213                     bkey_s_c_to_alloc_v4(k).v->gen != gen)
214                         goto done;
215         }
216
217         *bp_pos = bpos_max(*bp_pos, bucket_pos_to_bp(c, bucket, 0));
218
219         for_each_btree_key_norestart(trans, bp_iter, BTREE_ID_backpointers,
220                                      *bp_pos, iter_flags, k, ret) {
221                 if (bpos_ge(k.k->p, bp_end_pos))
222                         break;
223
224                 *bp_pos = k.k->p;
225                 *bp = *bkey_s_c_to_backpointer(k).v;
226                 goto out;
227         }
228 done:
229         *bp_pos = SPOS_MAX;
230 out:
231         bch2_trans_iter_exit(trans, &bp_iter);
232         bch2_trans_iter_exit(trans, &alloc_iter);
233         return ret;
234 }
235
236 static void backpointer_not_found(struct btree_trans *trans,
237                                   struct bpos bp_pos,
238                                   struct bch_backpointer bp,
239                                   struct bkey_s_c k)
240 {
241         struct bch_fs *c = trans->c;
242         struct printbuf buf = PRINTBUF;
243         struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
244
245         /*
246          * If we're using the btree write buffer, the backpointer we were
247          * looking at may have already been deleted - failure to find what it
248          * pointed to is not an error:
249          */
250         if (likely(!bch2_backpointers_no_use_write_buffer))
251                 return;
252
253         prt_printf(&buf, "backpointer doesn't match %s it points to:\n  ",
254                    bp.level ? "btree node" : "extent");
255         prt_printf(&buf, "bucket: ");
256         bch2_bpos_to_text(&buf, bucket);
257         prt_printf(&buf, "\n  ");
258
259         prt_printf(&buf, "backpointer pos: ");
260         bch2_bpos_to_text(&buf, bp_pos);
261         prt_printf(&buf, "\n  ");
262
263         bch2_backpointer_to_text(&buf, &bp);
264         prt_printf(&buf, "\n  ");
265         bch2_bkey_val_to_text(&buf, c, k);
266         if (c->curr_recovery_pass >= BCH_RECOVERY_PASS_check_extents_to_backpointers)
267                 bch_err_ratelimited(c, "%s", buf.buf);
268         else
269                 bch2_trans_inconsistent(trans, "%s", buf.buf);
270
271         printbuf_exit(&buf);
272 }
273
274 struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
275                                          struct btree_iter *iter,
276                                          struct bpos bp_pos,
277                                          struct bch_backpointer bp,
278                                          unsigned iter_flags)
279 {
280         if (likely(!bp.level)) {
281                 struct bch_fs *c = trans->c;
282                 struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
283                 struct bkey_s_c k;
284
285                 bch2_trans_node_iter_init(trans, iter,
286                                           bp.btree_id,
287                                           bp.pos,
288                                           0, 0,
289                                           iter_flags);
290                 k = bch2_btree_iter_peek_slot(iter);
291                 if (bkey_err(k)) {
292                         bch2_trans_iter_exit(trans, iter);
293                         return k;
294                 }
295
296                 if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
297                         return k;
298
299                 bch2_trans_iter_exit(trans, iter);
300                 backpointer_not_found(trans, bp_pos, bp, k);
301                 return bkey_s_c_null;
302         } else {
303                 struct btree *b = bch2_backpointer_get_node(trans, iter, bp_pos, bp);
304
305                 if (IS_ERR_OR_NULL(b)) {
306                         bch2_trans_iter_exit(trans, iter);
307                         return IS_ERR(b) ? bkey_s_c_err(PTR_ERR(b)) : bkey_s_c_null;
308                 }
309                 return bkey_i_to_s_c(&b->key);
310         }
311 }
312
313 struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
314                                         struct btree_iter *iter,
315                                         struct bpos bp_pos,
316                                         struct bch_backpointer bp)
317 {
318         struct bch_fs *c = trans->c;
319         struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
320         struct btree *b;
321
322         BUG_ON(!bp.level);
323
324         bch2_trans_node_iter_init(trans, iter,
325                                   bp.btree_id,
326                                   bp.pos,
327                                   0,
328                                   bp.level - 1,
329                                   0);
330         b = bch2_btree_iter_peek_node(iter);
331         if (IS_ERR_OR_NULL(b))
332                 goto err;
333
334         BUG_ON(b->c.level != bp.level - 1);
335
336         if (extent_matches_bp(c, bp.btree_id, bp.level,
337                               bkey_i_to_s_c(&b->key),
338                               bucket, bp))
339                 return b;
340
341         if (btree_node_will_make_reachable(b)) {
342                 b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node);
343         } else {
344                 backpointer_not_found(trans, bp_pos, bp, bkey_i_to_s_c(&b->key));
345                 b = NULL;
346         }
347 err:
348         bch2_trans_iter_exit(trans, iter);
349         return b;
350 }
351
352 static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_iter *bp_iter,
353                                         struct bkey_s_c k)
354 {
355         struct bch_fs *c = trans->c;
356         struct btree_iter alloc_iter = { NULL };
357         struct bkey_s_c alloc_k;
358         struct printbuf buf = PRINTBUF;
359         int ret = 0;
360
361         if (fsck_err_on(!bch2_dev_exists2(c, k.k->p.inode), c,
362                         backpointer_to_missing_device,
363                         "backpointer for missing device:\n%s",
364                         (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
365                 ret = bch2_btree_delete_at(trans, bp_iter, 0);
366                 goto out;
367         }
368
369         alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc,
370                                      bp_pos_to_bucket(c, k.k->p), 0);
371         ret = bkey_err(alloc_k);
372         if (ret)
373                 goto out;
374
375         if (fsck_err_on(alloc_k.k->type != KEY_TYPE_alloc_v4, c,
376                         backpointer_to_missing_alloc,
377                         "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
378                         alloc_iter.pos.inode, alloc_iter.pos.offset,
379                         (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
380                 ret = bch2_btree_delete_at(trans, bp_iter, 0);
381                 goto out;
382         }
383 out:
384 fsck_err:
385         bch2_trans_iter_exit(trans, &alloc_iter);
386         printbuf_exit(&buf);
387         return ret;
388 }
389
390 /* verify that every backpointer has a corresponding alloc key */
391 int bch2_check_btree_backpointers(struct bch_fs *c)
392 {
393         struct btree_iter iter;
394         struct bkey_s_c k;
395         int ret;
396
397         ret = bch2_trans_run(c,
398                 for_each_btree_key_commit(trans, iter,
399                         BTREE_ID_backpointers, POS_MIN, 0, k,
400                         NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
401                   bch2_check_btree_backpointer(trans, &iter, k)));
402         if (ret)
403                 bch_err_fn(c, ret);
404         return ret;
405 }
406
407 struct bpos_level {
408         unsigned        level;
409         struct bpos     pos;
410 };
411
412 static int check_bp_exists(struct btree_trans *trans,
413                            struct bpos bucket,
414                            struct bch_backpointer bp,
415                            struct bkey_s_c orig_k,
416                            struct bpos bucket_start,
417                            struct bpos bucket_end,
418                            struct bpos_level *last_flushed)
419 {
420         struct bch_fs *c = trans->c;
421         struct btree_iter bp_iter = { NULL };
422         struct printbuf buf = PRINTBUF;
423         struct bkey_s_c bp_k;
424         int ret;
425
426         if (bpos_lt(bucket, bucket_start) ||
427             bpos_gt(bucket, bucket_end))
428                 return 0;
429
430         if (!bch2_dev_bucket_exists(c, bucket))
431                 goto missing;
432
433         bp_k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
434                                   bucket_pos_to_bp(c, bucket, bp.bucket_offset),
435                                   0);
436         ret = bkey_err(bp_k);
437         if (ret)
438                 goto err;
439
440         if (bp_k.k->type != KEY_TYPE_backpointer ||
441             memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) {
442                 if (last_flushed->level != bp.level ||
443                     !bpos_eq(last_flushed->pos, orig_k.k->p)) {
444                         last_flushed->level = bp.level;
445                         last_flushed->pos = orig_k.k->p;
446
447                         ret = bch2_btree_write_buffer_flush_sync(trans) ?:
448                                 -BCH_ERR_transaction_restart_write_buffer_flush;
449                         goto out;
450                 }
451                 goto missing;
452         }
453 out:
454 err:
455 fsck_err:
456         bch2_trans_iter_exit(trans, &bp_iter);
457         printbuf_exit(&buf);
458         return ret;
459 missing:
460         prt_printf(&buf, "missing backpointer for btree=%s l=%u ",
461                bch2_btree_id_str(bp.btree_id), bp.level);
462         bch2_bkey_val_to_text(&buf, c, orig_k);
463         prt_printf(&buf, "\nbp pos ");
464         bch2_bpos_to_text(&buf, bp_iter.pos);
465
466         if (c->sb.version_upgrade_complete < bcachefs_metadata_version_backpointers ||
467             c->opts.reconstruct_alloc ||
468             fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
469                 ret = bch2_bucket_backpointer_mod(trans, bucket, bp, orig_k, true);
470
471         goto out;
472 }
473
474 static int check_extent_to_backpointers(struct btree_trans *trans,
475                                         enum btree_id btree, unsigned level,
476                                         struct bpos bucket_start,
477                                         struct bpos bucket_end,
478                                         struct bpos_level *last_flushed,
479                                         struct bkey_s_c k)
480 {
481         struct bch_fs *c = trans->c;
482         struct bkey_ptrs_c ptrs;
483         const union bch_extent_entry *entry;
484         struct extent_ptr_decoded p;
485         int ret;
486
487         ptrs = bch2_bkey_ptrs_c(k);
488         bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
489                 struct bpos bucket_pos;
490                 struct bch_backpointer bp;
491
492                 if (p.ptr.cached)
493                         continue;
494
495                 bch2_extent_ptr_to_bp(c, btree, level,
496                                       k, p, &bucket_pos, &bp);
497
498                 ret = check_bp_exists(trans, bucket_pos, bp, k,
499                                       bucket_start, bucket_end,
500                                       last_flushed);
501                 if (ret)
502                         return ret;
503         }
504
505         return 0;
506 }
507
508 static int check_btree_root_to_backpointers(struct btree_trans *trans,
509                                             enum btree_id btree_id,
510                                             struct bpos bucket_start,
511                                             struct bpos bucket_end,
512                                             struct bpos_level *last_flushed,
513                                             int *level)
514 {
515         struct bch_fs *c = trans->c;
516         struct btree_iter iter;
517         struct btree *b;
518         struct bkey_s_c k;
519         int ret;
520 retry:
521         bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN,
522                                   0, bch2_btree_id_root(c, btree_id)->b->c.level, 0);
523         b = bch2_btree_iter_peek_node(&iter);
524         ret = PTR_ERR_OR_ZERO(b);
525         if (ret)
526                 goto err;
527
528         if (b != btree_node_root(c, b)) {
529                 bch2_trans_iter_exit(trans, &iter);
530                 goto retry;
531         }
532
533         *level = b->c.level;
534
535         k = bkey_i_to_s_c(&b->key);
536         ret = check_extent_to_backpointers(trans, btree_id, b->c.level + 1,
537                                       bucket_start, bucket_end,
538                                       last_flushed, k);
539 err:
540         bch2_trans_iter_exit(trans, &iter);
541         return ret;
542 }
543
544 static inline struct bbpos bp_to_bbpos(struct bch_backpointer bp)
545 {
546         return (struct bbpos) {
547                 .btree  = bp.btree_id,
548                 .pos    = bp.pos,
549         };
550 }
551
552 static size_t btree_nodes_fit_in_ram(struct bch_fs *c)
553 {
554         struct sysinfo i;
555         u64 mem_bytes;
556
557         si_meminfo(&i);
558         mem_bytes = i.totalram * i.mem_unit;
559         return div_u64(mem_bytes >> 1, btree_bytes(c));
560 }
561
562 static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
563                                         unsigned btree_leaf_mask,
564                                         unsigned btree_interior_mask,
565                                         struct bbpos start, struct bbpos *end)
566 {
567         struct btree_iter iter;
568         struct bkey_s_c k;
569         size_t btree_nodes = btree_nodes_fit_in_ram(trans->c);
570         enum btree_id btree;
571         int ret = 0;
572
573         for (btree = start.btree; btree < BTREE_ID_NR && !ret; btree++) {
574                 unsigned depth = ((1U << btree) & btree_leaf_mask) ? 1 : 2;
575
576                 if (!((1U << btree) & btree_leaf_mask) &&
577                     !((1U << btree) & btree_interior_mask))
578                         continue;
579
580                 bch2_trans_node_iter_init(trans, &iter, btree,
581                                           btree == start.btree ? start.pos : POS_MIN,
582                                           0, depth, 0);
583                 /*
584                  * for_each_btree_key_contineu() doesn't check the return value
585                  * from bch2_btree_iter_advance(), which is needed when
586                  * iterating over interior nodes where we'll see keys at
587                  * SPOS_MAX:
588                  */
589                 do {
590                         k = __bch2_btree_iter_peek_and_restart(trans, &iter, 0);
591                         ret = bkey_err(k);
592                         if (!k.k || ret)
593                                 break;
594
595                         --btree_nodes;
596                         if (!btree_nodes) {
597                                 *end = BBPOS(btree, k.k->p);
598                                 bch2_trans_iter_exit(trans, &iter);
599                                 return 0;
600                         }
601                 } while (bch2_btree_iter_advance(&iter));
602                 bch2_trans_iter_exit(trans, &iter);
603         }
604
605         *end = BBPOS_MAX;
606         return ret;
607 }
608
609 static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
610                                                    struct bpos bucket_start,
611                                                    struct bpos bucket_end)
612 {
613         struct bch_fs *c = trans->c;
614         struct btree_iter iter;
615         enum btree_id btree_id;
616         struct bkey_s_c k;
617         struct bpos_level last_flushed = { UINT_MAX, POS_MIN };
618         int ret = 0;
619
620         for (btree_id = 0; btree_id < btree_id_nr_alive(c); btree_id++) {
621                 int level, depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
622
623                 ret = commit_do(trans, NULL, NULL,
624                                 BCH_TRANS_COMMIT_no_enospc,
625                                 check_btree_root_to_backpointers(trans, btree_id,
626                                                         bucket_start, bucket_end,
627                                                         &last_flushed, &level));
628                 if (ret)
629                         return ret;
630
631                 while (level >= depth) {
632                         bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
633                                                   level,
634                                                   BTREE_ITER_PREFETCH);
635                         for_each_btree_key_continue(trans, iter, BTREE_ITER_PREFETCH, k, ret) {
636                                 ret = commit_do(trans, NULL, NULL,
637                                                 BCH_TRANS_COMMIT_no_enospc,
638                                         check_extent_to_backpointers(trans, btree_id, level,
639                                                                      bucket_start, bucket_end,
640                                                                      &last_flushed, k));
641                                 if (ret)
642                                         break;
643
644                                 if (bpos_eq(iter.pos, SPOS_MAX))
645                                         break;
646                         }
647                         bch2_trans_iter_exit(trans, &iter);
648
649                         if (ret)
650                                 return ret;
651
652                         --level;
653                 }
654         }
655
656         return 0;
657 }
658
659 static struct bpos bucket_pos_to_bp_safe(const struct bch_fs *c,
660                                          struct bpos bucket)
661 {
662         return bch2_dev_exists2(c, bucket.inode)
663                 ? bucket_pos_to_bp(c, bucket, 0)
664                 : bucket;
665 }
666
667 static int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
668                                         struct bpos start, struct bpos *end)
669 {
670         struct btree_iter alloc_iter;
671         struct btree_iter bp_iter;
672         struct bkey_s_c alloc_k, bp_k;
673         size_t btree_nodes = btree_nodes_fit_in_ram(trans->c);
674         bool alloc_end = false, bp_end = false;
675         int ret = 0;
676
677         bch2_trans_node_iter_init(trans, &alloc_iter, BTREE_ID_alloc,
678                                   start, 0, 1, 0);
679         bch2_trans_node_iter_init(trans, &bp_iter, BTREE_ID_backpointers,
680                                   bucket_pos_to_bp_safe(trans->c, start), 0, 1, 0);
681         while (1) {
682                 alloc_k = !alloc_end
683                         ? __bch2_btree_iter_peek_and_restart(trans, &alloc_iter, 0)
684                         : bkey_s_c_null;
685                 bp_k = !bp_end
686                         ? __bch2_btree_iter_peek_and_restart(trans, &bp_iter, 0)
687                         : bkey_s_c_null;
688
689                 ret = bkey_err(alloc_k) ?: bkey_err(bp_k);
690                 if ((!alloc_k.k && !bp_k.k) || ret) {
691                         *end = SPOS_MAX;
692                         break;
693                 }
694
695                 --btree_nodes;
696                 if (!btree_nodes) {
697                         *end = alloc_k.k ? alloc_k.k->p : SPOS_MAX;
698                         break;
699                 }
700
701                 if (bpos_lt(alloc_iter.pos, SPOS_MAX) &&
702                     bpos_lt(bucket_pos_to_bp_safe(trans->c, alloc_iter.pos), bp_iter.pos)) {
703                         if (!bch2_btree_iter_advance(&alloc_iter))
704                                 alloc_end = true;
705                 } else {
706                         if (!bch2_btree_iter_advance(&bp_iter))
707                                 bp_end = true;
708                 }
709         }
710         bch2_trans_iter_exit(trans, &bp_iter);
711         bch2_trans_iter_exit(trans, &alloc_iter);
712         return ret;
713 }
714
715 int bch2_check_extents_to_backpointers(struct bch_fs *c)
716 {
717         struct btree_trans *trans = bch2_trans_get(c);
718         struct bpos start = POS_MIN, end;
719         int ret;
720
721         while (1) {
722                 ret = bch2_get_alloc_in_memory_pos(trans, start, &end);
723                 if (ret)
724                         break;
725
726                 if (bpos_eq(start, POS_MIN) && !bpos_eq(end, SPOS_MAX))
727                         bch_verbose(c, "%s(): alloc info does not fit in ram, running in multiple passes with %zu nodes per pass",
728                                     __func__, btree_nodes_fit_in_ram(c));
729
730                 if (!bpos_eq(start, POS_MIN) || !bpos_eq(end, SPOS_MAX)) {
731                         struct printbuf buf = PRINTBUF;
732
733                         prt_str(&buf, "check_extents_to_backpointers(): ");
734                         bch2_bpos_to_text(&buf, start);
735                         prt_str(&buf, "-");
736                         bch2_bpos_to_text(&buf, end);
737
738                         bch_verbose(c, "%s", buf.buf);
739                         printbuf_exit(&buf);
740                 }
741
742                 ret = bch2_check_extents_to_backpointers_pass(trans, start, end);
743                 if (ret || bpos_eq(end, SPOS_MAX))
744                         break;
745
746                 start = bpos_successor(end);
747         }
748         bch2_trans_put(trans);
749
750         if (ret)
751                 bch_err_fn(c, ret);
752         return ret;
753 }
754
755 static int check_one_backpointer(struct btree_trans *trans,
756                                  struct bbpos start,
757                                  struct bbpos end,
758                                  struct bkey_s_c_backpointer bp,
759                                  struct bpos *last_flushed_pos)
760 {
761         struct bch_fs *c = trans->c;
762         struct btree_iter iter;
763         struct bbpos pos = bp_to_bbpos(*bp.v);
764         struct bkey_s_c k;
765         struct printbuf buf = PRINTBUF;
766         int ret;
767
768         if (bbpos_cmp(pos, start) < 0 ||
769             bbpos_cmp(pos, end) > 0)
770                 return 0;
771
772         k = bch2_backpointer_get_key(trans, &iter, bp.k->p, *bp.v, 0);
773         ret = bkey_err(k);
774         if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node)
775                 return 0;
776         if (ret)
777                 return ret;
778
779         if (!k.k && !bpos_eq(*last_flushed_pos, bp.k->p)) {
780                 *last_flushed_pos = bp.k->p;
781                 ret = bch2_btree_write_buffer_flush_sync(trans) ?:
782                         -BCH_ERR_transaction_restart_write_buffer_flush;
783                 goto out;
784         }
785
786         if (fsck_err_on(!k.k, c,
787                         backpointer_to_missing_ptr,
788                         "backpointer for missing %s\n  %s",
789                         bp.v->level ? "btree node" : "extent",
790                         (bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
791                 ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
792                 goto out;
793         }
794 out:
795 fsck_err:
796         bch2_trans_iter_exit(trans, &iter);
797         printbuf_exit(&buf);
798         return ret;
799 }
800
801 static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
802                                                    struct bbpos start,
803                                                    struct bbpos end)
804 {
805         struct btree_iter iter;
806         struct bkey_s_c k;
807         struct bpos last_flushed_pos = SPOS_MAX;
808
809         return for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
810                                   POS_MIN, BTREE_ITER_PREFETCH, k,
811                                   NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
812                 check_one_backpointer(trans, start, end,
813                                       bkey_s_c_to_backpointer(k),
814                                       &last_flushed_pos));
815 }
816
817 int bch2_check_backpointers_to_extents(struct bch_fs *c)
818 {
819         struct btree_trans *trans = bch2_trans_get(c);
820         struct bbpos start = (struct bbpos) { .btree = 0, .pos = POS_MIN, }, end;
821         int ret;
822
823         while (1) {
824                 ret = bch2_get_btree_in_memory_pos(trans,
825                                                    (1U << BTREE_ID_extents)|
826                                                    (1U << BTREE_ID_reflink),
827                                                    ~0,
828                                                    start, &end);
829                 if (ret)
830                         break;
831
832                 if (!bbpos_cmp(start, BBPOS_MIN) &&
833                     bbpos_cmp(end, BBPOS_MAX))
834                         bch_verbose(c, "%s(): extents do not fit in ram, running in multiple passes with %zu nodes per pass",
835                                     __func__, btree_nodes_fit_in_ram(c));
836
837                 if (bbpos_cmp(start, BBPOS_MIN) ||
838                     bbpos_cmp(end, BBPOS_MAX)) {
839                         struct printbuf buf = PRINTBUF;
840
841                         prt_str(&buf, "check_backpointers_to_extents(): ");
842                         bch2_bbpos_to_text(&buf, start);
843                         prt_str(&buf, "-");
844                         bch2_bbpos_to_text(&buf, end);
845
846                         bch_verbose(c, "%s", buf.buf);
847                         printbuf_exit(&buf);
848                 }
849
850                 ret = bch2_check_backpointers_to_extents_pass(trans, start, end);
851                 if (ret || !bbpos_cmp(end, BBPOS_MAX))
852                         break;
853
854                 start = bbpos_successor(end);
855         }
856         bch2_trans_put(trans);
857
858         if (ret)
859                 bch_err_fn(c, ret);
860         return ret;
861 }