xref: /linux-6.15/fs/bcachefs/backpointers.c (revision d1041d8e)
1a8c752bbSKent Overstreet // SPDX-License-Identifier: GPL-2.0
2a8c752bbSKent Overstreet #include "bcachefs.h"
323792a71SKent Overstreet #include "bbpos.h"
4a8c752bbSKent Overstreet #include "alloc_background.h"
5a8c752bbSKent Overstreet #include "backpointers.h"
6a56c6171SKent Overstreet #include "bkey_buf.h"
7a8c752bbSKent Overstreet #include "btree_cache.h"
8a8c752bbSKent Overstreet #include "btree_update.h"
9853960d0SKent Overstreet #include "btree_update_interior.h"
107c057d35SKent Overstreet #include "btree_write_buffer.h"
114c02e63dSKent Overstreet #include "checksum.h"
12b99a94fdSKent Overstreet #include "disk_accounting.h"
13a8c752bbSKent Overstreet #include "error.h"
14baabeb49SKent Overstreet #include "progress.h"
15a8c752bbSKent Overstreet 
1623792a71SKent Overstreet #include <linux/mm.h>
1723792a71SKent Overstreet 
bch2_backpointer_validate(struct bch_fs * c,struct bkey_s_c k,struct bkey_validate_context from)18d97de0d0SKent Overstreet int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
19a6f4794fSKent Overstreet 			      struct bkey_validate_context from)
20a8c752bbSKent Overstreet {
21a8c752bbSKent Overstreet 	struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
22f8f1dde6SKent Overstreet 	int ret = 0;
23f8f1dde6SKent Overstreet 
24f8f1dde6SKent Overstreet 	bkey_fsck_err_on(bp.v->level > BTREE_MAX_DEPTH,
25f8f1dde6SKent Overstreet 			 c, backpointer_level_bad,
26f8f1dde6SKent Overstreet 			 "backpointer level bad: %u >= %u",
27f8f1dde6SKent Overstreet 			 bp.v->level, BTREE_MAX_DEPTH);
28a5e3dce4SKent Overstreet 
29debe6965SKent Overstreet 	bkey_fsck_err_on(bp.k->p.inode == BCH_SB_MEMBER_INVALID,
30debe6965SKent Overstreet 			 c, backpointer_dev_bad,
31debe6965SKent Overstreet 			 "backpointer for BCH_SB_MEMBER_INVALID");
32b65db750SKent Overstreet fsck_err:
33b65db750SKent Overstreet 	return ret;
34a8c752bbSKent Overstreet }
35a8c752bbSKent Overstreet 
bch2_backpointer_to_text(struct printbuf * out,struct bch_fs * c,struct bkey_s_c k)36eb25733aSKent Overstreet void bch2_backpointer_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
37a8c752bbSKent Overstreet {
38eb25733aSKent Overstreet 	struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
39a8c752bbSKent Overstreet 
40633cf069SKent Overstreet 	rcu_read_lock();
411ab00b6cSKent Overstreet 	struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp.k->p.inode);
42633cf069SKent Overstreet 	if (ca) {
431ab00b6cSKent Overstreet 		u32 bucket_offset;
441ab00b6cSKent Overstreet 		struct bpos bucket = bp_pos_to_bucket_and_offset(ca, bp.k->p, &bucket_offset);
45633cf069SKent Overstreet 		rcu_read_unlock();
461ab00b6cSKent Overstreet 		prt_printf(out, "bucket=%llu:%llu:%u ", bucket.inode, bucket.offset, bucket_offset);
47633cf069SKent Overstreet 	} else {
48633cf069SKent Overstreet 		rcu_read_unlock();
491ab00b6cSKent Overstreet 		prt_printf(out, "sector=%llu:%llu ", bp.k->p.inode, bp.k->p.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT);
501f626223SKent Overstreet 	}
5162a03559SKent Overstreet 
52eb25733aSKent Overstreet 	bch2_btree_id_level_to_text(out, bp.v->btree_id, bp.v->level);
536a9f681eSKent Overstreet 	prt_str(out, " data_type=");
546a9f681eSKent Overstreet 	bch2_prt_data_type(out, bp.v->data_type);
55ebdca072SKent Overstreet 	prt_printf(out, " suboffset=%u len=%u gen=%u pos=",
561ab00b6cSKent Overstreet 		   (u32) bp.k->p.offset & ~(~0U << MAX_EXTENT_COMPRESS_RATIO_SHIFT),
57ebdca072SKent Overstreet 		   bp.v->bucket_len,
58ebdca072SKent Overstreet 		   bp.v->bucket_gen);
59eb25733aSKent Overstreet 	bch2_bpos_to_text(out, bp.v->pos);
60a8c752bbSKent Overstreet }
61a8c752bbSKent Overstreet 
bch2_backpointer_swab(struct bkey_s k)62a8c752bbSKent Overstreet void bch2_backpointer_swab(struct bkey_s k)
63a8c752bbSKent Overstreet {
64a8c752bbSKent Overstreet 	struct bkey_s_backpointer bp = bkey_s_to_backpointer(k);
65a8c752bbSKent Overstreet 
66a8c752bbSKent Overstreet 	bp.v->bucket_len	= swab32(bp.v->bucket_len);
67a8c752bbSKent Overstreet 	bch2_bpos_swab(&bp.v->pos);
68a8c752bbSKent Overstreet }
69a8c752bbSKent Overstreet 
extent_matches_bp(struct bch_fs * c,enum btree_id btree_id,unsigned level,struct bkey_s_c k,struct bkey_s_c_backpointer bp)70eb25733aSKent Overstreet static bool extent_matches_bp(struct bch_fs *c,
71eb25733aSKent Overstreet 			      enum btree_id btree_id, unsigned level,
72eb25733aSKent Overstreet 			      struct bkey_s_c k,
73eb25733aSKent Overstreet 			      struct bkey_s_c_backpointer bp)
74eb25733aSKent Overstreet {
75eb25733aSKent Overstreet 	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
76eb25733aSKent Overstreet 	const union bch_extent_entry *entry;
77eb25733aSKent Overstreet 	struct extent_ptr_decoded p;
78eb25733aSKent Overstreet 
79eb25733aSKent Overstreet 	bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
80eb25733aSKent Overstreet 		struct bkey_i_backpointer bp2;
81aca7a26fSKent Overstreet 		bch2_extent_ptr_to_bp(c, btree_id, level, k, p, entry, &bp2);
82eb25733aSKent Overstreet 
83eb25733aSKent Overstreet 		if (bpos_eq(bp.k->p, bp2.k.p) &&
84aca7a26fSKent Overstreet 		    !memcmp(bp.v, &bp2.v, sizeof(bp2.v)))
85eb25733aSKent Overstreet 			return true;
86eb25733aSKent Overstreet 	}
87eb25733aSKent Overstreet 
88eb25733aSKent Overstreet 	return false;
89eb25733aSKent Overstreet }
90eb25733aSKent Overstreet 
backpointer_mod_err(struct btree_trans * trans,struct bkey_s_c orig_k,struct bkey_i_backpointer * new_bp,struct bkey_s_c found_bp,bool insert)91a8c752bbSKent Overstreet static noinline int backpointer_mod_err(struct btree_trans *trans,
92a8c752bbSKent Overstreet 					struct bkey_s_c orig_k,
93eb25733aSKent Overstreet 					struct bkey_i_backpointer *new_bp,
94eb25733aSKent Overstreet 					struct bkey_s_c found_bp,
95a8c752bbSKent Overstreet 					bool insert)
96a8c752bbSKent Overstreet {
97a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
98a8c752bbSKent Overstreet 	struct printbuf buf = PRINTBUF;
996d77ce4aSKent Overstreet 	int ret = 0;
100a8c752bbSKent Overstreet 
101a8c752bbSKent Overstreet 	if (insert) {
102a8c752bbSKent Overstreet 		prt_printf(&buf, "existing backpointer found when inserting ");
103eb25733aSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&new_bp->k_i));
104a8c752bbSKent Overstreet 		prt_newline(&buf);
105a8c752bbSKent Overstreet 		printbuf_indent_add(&buf, 2);
106a8c752bbSKent Overstreet 
107a8c752bbSKent Overstreet 		prt_printf(&buf, "found ");
108eb25733aSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, found_bp);
109a8c752bbSKent Overstreet 		prt_newline(&buf);
110a8c752bbSKent Overstreet 
111a8c752bbSKent Overstreet 		prt_printf(&buf, "for ");
112a8c752bbSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, orig_k);
113a8c752bbSKent Overstreet 
114a8c752bbSKent Overstreet 		bch_err(c, "%s", buf.buf);
115067d228bSKent Overstreet 	} else if (c->curr_recovery_pass > BCH_RECOVERY_PASS_check_extents_to_backpointers) {
1167423330eSKent Overstreet 		prt_printf(&buf, "backpointer not found when deleting\n");
117a8c752bbSKent Overstreet 		printbuf_indent_add(&buf, 2);
118a8c752bbSKent Overstreet 
119a8c752bbSKent Overstreet 		prt_printf(&buf, "searching for ");
120eb25733aSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&new_bp->k_i));
121a8c752bbSKent Overstreet 		prt_newline(&buf);
122a8c752bbSKent Overstreet 
123a8c752bbSKent Overstreet 		prt_printf(&buf, "got ");
124eb25733aSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, found_bp);
125a8c752bbSKent Overstreet 		prt_newline(&buf);
126a8c752bbSKent Overstreet 
127a8c752bbSKent Overstreet 		prt_printf(&buf, "for ");
128a8c752bbSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, orig_k);
1296d77ce4aSKent Overstreet 	}
1306d77ce4aSKent Overstreet 
1316d77ce4aSKent Overstreet 	if (c->curr_recovery_pass > BCH_RECOVERY_PASS_check_extents_to_backpointers &&
1326d77ce4aSKent Overstreet 	    __bch2_inconsistent_error(c, &buf))
1336d77ce4aSKent Overstreet 		ret = -BCH_ERR_erofs_unfixed_errors;
134a8c752bbSKent Overstreet 
135a8c752bbSKent Overstreet 	bch_err(c, "%s", buf.buf);
136a8c752bbSKent Overstreet 	printbuf_exit(&buf);
1376d77ce4aSKent Overstreet 	return ret;
138a8c752bbSKent Overstreet }
139a8c752bbSKent Overstreet 
bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans * trans,struct bkey_s_c orig_k,struct bkey_i_backpointer * bp,bool insert)140a8c752bbSKent Overstreet int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
141a8c752bbSKent Overstreet 				struct bkey_s_c orig_k,
142eb25733aSKent Overstreet 				struct bkey_i_backpointer *bp,
143a8c752bbSKent Overstreet 				bool insert)
144a8c752bbSKent Overstreet {
145a8c752bbSKent Overstreet 	struct btree_iter bp_iter;
146eb25733aSKent Overstreet 	struct bkey_s_c k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
147eb25733aSKent Overstreet 			       bp->k.p,
1485dd8c60eSKent Overstreet 			       BTREE_ITER_intent|
1495dd8c60eSKent Overstreet 			       BTREE_ITER_slots|
1505dd8c60eSKent Overstreet 			       BTREE_ITER_with_updates);
151eb25733aSKent Overstreet 	int ret = bkey_err(k);
152a8c752bbSKent Overstreet 	if (ret)
153eb25733aSKent Overstreet 		return ret;
154a8c752bbSKent Overstreet 
155a8c752bbSKent Overstreet 	if (insert
156a8c752bbSKent Overstreet 	    ? k.k->type
157a8c752bbSKent Overstreet 	    : (k.k->type != KEY_TYPE_backpointer ||
158eb25733aSKent Overstreet 	       memcmp(bkey_s_c_to_backpointer(k).v, &bp->v, sizeof(bp->v)))) {
159eb25733aSKent Overstreet 		ret = backpointer_mod_err(trans, orig_k, bp, k, insert);
160a8c752bbSKent Overstreet 		if (ret)
161a8c752bbSKent Overstreet 			goto err;
162a8c752bbSKent Overstreet 	}
163a8c752bbSKent Overstreet 
164eb25733aSKent Overstreet 	if (!insert) {
165eb25733aSKent Overstreet 		bp->k.type = KEY_TYPE_deleted;
166eb25733aSKent Overstreet 		set_bkey_val_u64s(&bp->k, 0);
167eb25733aSKent Overstreet 	}
168eb25733aSKent Overstreet 
169eb25733aSKent Overstreet 	ret = bch2_trans_update(trans, &bp_iter, &bp->k_i, 0);
170a8c752bbSKent Overstreet err:
171a8c752bbSKent Overstreet 	bch2_trans_iter_exit(trans, &bp_iter);
172a8c752bbSKent Overstreet 	return ret;
173a8c752bbSKent Overstreet }
174a8c752bbSKent Overstreet 
bch2_backpointer_del(struct btree_trans * trans,struct bpos pos)175c80f33b7SKent Overstreet static int bch2_backpointer_del(struct btree_trans *trans, struct bpos pos)
176c80f33b7SKent Overstreet {
177c2c2a4d6SKent Overstreet 	return (likely(!bch2_backpointers_no_use_write_buffer)
178c80f33b7SKent Overstreet 		? bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, pos)
179c2c2a4d6SKent Overstreet 		: bch2_btree_delete(trans, BTREE_ID_backpointers, pos, 0)) ?:
180c2c2a4d6SKent Overstreet 		 bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
181c80f33b7SKent Overstreet }
182c80f33b7SKent Overstreet 
bch2_backpointers_maybe_flush(struct btree_trans * trans,struct bkey_s_c visiting_k,struct bkey_buf * last_flushed)1833f57171dSKent Overstreet static inline int bch2_backpointers_maybe_flush(struct btree_trans *trans,
184c80f33b7SKent Overstreet 					 struct bkey_s_c visiting_k,
185c80f33b7SKent Overstreet 					 struct bkey_buf *last_flushed)
186c80f33b7SKent Overstreet {
187c80f33b7SKent Overstreet 	return likely(!bch2_backpointers_no_use_write_buffer)
188c80f33b7SKent Overstreet 		? bch2_btree_write_buffer_maybe_flush(trans, visiting_k, last_flushed)
189c80f33b7SKent Overstreet 		: 0;
190c80f33b7SKent Overstreet }
191c80f33b7SKent Overstreet 
backpointer_target_not_found(struct btree_trans * trans,struct bkey_s_c_backpointer bp,struct bkey_s_c target_k,struct bkey_buf * last_flushed,bool commit)192c2c2a4d6SKent Overstreet static int backpointer_target_not_found(struct btree_trans *trans,
1939e92d6e9SKent Overstreet 				  struct bkey_s_c_backpointer bp,
194c2c2a4d6SKent Overstreet 				  struct bkey_s_c target_k,
195*d1041d8eSKent Overstreet 				  struct bkey_buf *last_flushed,
196*d1041d8eSKent Overstreet 				  bool commit)
197a8c752bbSKent Overstreet {
198a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
199a8c752bbSKent Overstreet 	struct printbuf buf = PRINTBUF;
200c2c2a4d6SKent Overstreet 	int ret = 0;
201a8c752bbSKent Overstreet 
202853960d0SKent Overstreet 	/*
203853960d0SKent Overstreet 	 * If we're using the btree write buffer, the backpointer we were
204853960d0SKent Overstreet 	 * looking at may have already been deleted - failure to find what it
205853960d0SKent Overstreet 	 * pointed to is not an error:
206853960d0SKent Overstreet 	 */
207c2c2a4d6SKent Overstreet 	ret = last_flushed
208c2c2a4d6SKent Overstreet 		? bch2_backpointers_maybe_flush(trans, bp.s_c, last_flushed)
209c2c2a4d6SKent Overstreet 		: 0;
210c2c2a4d6SKent Overstreet 	if (ret)
211c2c2a4d6SKent Overstreet 		return ret;
212a8c752bbSKent Overstreet 
213a8c752bbSKent Overstreet 	prt_printf(&buf, "backpointer doesn't match %s it points to:\n",
2149e92d6e9SKent Overstreet 		   bp.v->level ? "btree node" : "extent");
215eb25733aSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, bp.s_c);
216a8c752bbSKent Overstreet 
2171ece5323SKent Overstreet 	prt_newline(&buf);
2189e92d6e9SKent Overstreet 	bch2_bkey_val_to_text(&buf, c, target_k);
219a8c752bbSKent Overstreet 
2207611d6b5SKent Overstreet 	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(target_k);
2217611d6b5SKent Overstreet 	const union bch_extent_entry *entry;
2227611d6b5SKent Overstreet 	struct extent_ptr_decoded p;
2237611d6b5SKent Overstreet 	bkey_for_each_ptr_decode(target_k.k, ptrs, p, entry)
2247611d6b5SKent Overstreet 		if (p.ptr.dev == bp.k->p.inode) {
2251ece5323SKent Overstreet 			prt_newline(&buf);
2267611d6b5SKent Overstreet 			struct bkey_i_backpointer bp2;
2277611d6b5SKent Overstreet 			bch2_extent_ptr_to_bp(c, bp.v->btree_id, bp.v->level, target_k, p, entry, &bp2);
2287611d6b5SKent Overstreet 			bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp2.k_i));
2297611d6b5SKent Overstreet 		}
2307611d6b5SKent Overstreet 
231c2c2a4d6SKent Overstreet 	if (fsck_err(trans, backpointer_to_missing_ptr,
232*d1041d8eSKent Overstreet 		     "%s", buf.buf)) {
233c2c2a4d6SKent Overstreet 		ret = bch2_backpointer_del(trans, bp.k->p);
234*d1041d8eSKent Overstreet 		if (ret || !commit)
235*d1041d8eSKent Overstreet 			goto out;
236*d1041d8eSKent Overstreet 
237*d1041d8eSKent Overstreet 		/*
238*d1041d8eSKent Overstreet 		 * Normally, on transaction commit from inside a transaction,
239*d1041d8eSKent Overstreet 		 * we'll return -BCH_ERR_transaction_restart_nested, since a
240*d1041d8eSKent Overstreet 		 * transaction commit invalidates pointers given out by peek().
241*d1041d8eSKent Overstreet 		 *
242*d1041d8eSKent Overstreet 		 * However, since we're updating a write buffer btree, if we
243*d1041d8eSKent Overstreet 		 * return a transaction restart and loop we won't see that the
244*d1041d8eSKent Overstreet 		 * backpointer has been deleted without an additional write
245*d1041d8eSKent Overstreet 		 * buffer flush - and those are expensive.
246*d1041d8eSKent Overstreet 		 *
247*d1041d8eSKent Overstreet 		 * So we're relying on the caller immediately advancing to the
248*d1041d8eSKent Overstreet 		 * next backpointer and starting a new transaction immediately
249*d1041d8eSKent Overstreet 		 * after backpointer_get_key() returns NULL:
250*d1041d8eSKent Overstreet 		 */
251*d1041d8eSKent Overstreet 		ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
252*d1041d8eSKent Overstreet 	}
253*d1041d8eSKent Overstreet out:
254c2c2a4d6SKent Overstreet fsck_err:
255a8c752bbSKent Overstreet 	printbuf_exit(&buf);
256c2c2a4d6SKent Overstreet 	return ret;
257a8c752bbSKent Overstreet }
258a8c752bbSKent Overstreet 
__bch2_backpointer_get_node(struct btree_trans * trans,struct bkey_s_c_backpointer bp,struct btree_iter * iter,struct bkey_buf * last_flushed,bool commit)259*d1041d8eSKent Overstreet static struct btree *__bch2_backpointer_get_node(struct btree_trans *trans,
260*d1041d8eSKent Overstreet 						 struct bkey_s_c_backpointer bp,
261*d1041d8eSKent Overstreet 						 struct btree_iter *iter,
262*d1041d8eSKent Overstreet 						 struct bkey_buf *last_flushed,
263*d1041d8eSKent Overstreet 						 bool commit)
264*d1041d8eSKent Overstreet {
265*d1041d8eSKent Overstreet 	struct bch_fs *c = trans->c;
266*d1041d8eSKent Overstreet 
267*d1041d8eSKent Overstreet 	BUG_ON(!bp.v->level);
268*d1041d8eSKent Overstreet 
269*d1041d8eSKent Overstreet 	bch2_trans_node_iter_init(trans, iter,
270*d1041d8eSKent Overstreet 				  bp.v->btree_id,
271*d1041d8eSKent Overstreet 				  bp.v->pos,
272*d1041d8eSKent Overstreet 				  0,
273*d1041d8eSKent Overstreet 				  bp.v->level - 1,
274*d1041d8eSKent Overstreet 				  0);
275*d1041d8eSKent Overstreet 	struct btree *b = bch2_btree_iter_peek_node(trans, iter);
276*d1041d8eSKent Overstreet 	if (IS_ERR_OR_NULL(b))
277*d1041d8eSKent Overstreet 		goto err;
278*d1041d8eSKent Overstreet 
279*d1041d8eSKent Overstreet 	BUG_ON(b->c.level != bp.v->level - 1);
280*d1041d8eSKent Overstreet 
281*d1041d8eSKent Overstreet 	if (extent_matches_bp(c, bp.v->btree_id, bp.v->level,
282*d1041d8eSKent Overstreet 			      bkey_i_to_s_c(&b->key), bp))
283*d1041d8eSKent Overstreet 		return b;
284*d1041d8eSKent Overstreet 
285*d1041d8eSKent Overstreet 	if (btree_node_will_make_reachable(b)) {
286*d1041d8eSKent Overstreet 		b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node);
287*d1041d8eSKent Overstreet 	} else {
288*d1041d8eSKent Overstreet 		int ret = backpointer_target_not_found(trans, bp, bkey_i_to_s_c(&b->key),
289*d1041d8eSKent Overstreet 						       last_flushed, commit);
290*d1041d8eSKent Overstreet 		b = ret ? ERR_PTR(ret) : NULL;
291*d1041d8eSKent Overstreet 	}
292*d1041d8eSKent Overstreet err:
293*d1041d8eSKent Overstreet 	bch2_trans_iter_exit(trans, iter);
294*d1041d8eSKent Overstreet 	return b;
295*d1041d8eSKent Overstreet }
296*d1041d8eSKent Overstreet 
__bch2_backpointer_get_key(struct btree_trans * trans,struct bkey_s_c_backpointer bp,struct btree_iter * iter,unsigned iter_flags,struct bkey_buf * last_flushed,bool commit)297*d1041d8eSKent Overstreet static struct bkey_s_c __bch2_backpointer_get_key(struct btree_trans *trans,
2989e92d6e9SKent Overstreet 						  struct bkey_s_c_backpointer bp,
299a8c752bbSKent Overstreet 						  struct btree_iter *iter,
300056cae1cSKent Overstreet 						  unsigned iter_flags,
301*d1041d8eSKent Overstreet 						  struct bkey_buf *last_flushed,
302*d1041d8eSKent Overstreet 						  bool commit)
303a8c752bbSKent Overstreet {
304a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
305633cf069SKent Overstreet 
306f11ca2abSKent Overstreet 	if (unlikely(bp.v->btree_id >= btree_id_nr_alive(c)))
307f11ca2abSKent Overstreet 		return bkey_s_c_null;
308f11ca2abSKent Overstreet 
309a8c752bbSKent Overstreet 	bch2_trans_node_iter_init(trans, iter,
3109e92d6e9SKent Overstreet 				  bp.v->btree_id,
3119e92d6e9SKent Overstreet 				  bp.v->pos,
312ca16fa6bSKent Overstreet 				  0,
313ca16fa6bSKent Overstreet 				  bp.v->level,
3146bdefe9cSKent Overstreet 				  iter_flags);
3159180ad2eSKent Overstreet 	struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, iter);
316a8c752bbSKent Overstreet 	if (bkey_err(k)) {
317a8c752bbSKent Overstreet 		bch2_trans_iter_exit(trans, iter);
318a8c752bbSKent Overstreet 		return k;
319a8c752bbSKent Overstreet 	}
320a8c752bbSKent Overstreet 
3212581f89aSKent Overstreet 	/*
3222581f89aSKent Overstreet 	 * peek_slot() doesn't normally return NULL - except when we ask for a
3232581f89aSKent Overstreet 	 * key at a btree level that doesn't exist.
3242581f89aSKent Overstreet 	 *
3252581f89aSKent Overstreet 	 * We may want to revisit this and change peek_slot():
3262581f89aSKent Overstreet 	 */
3272581f89aSKent Overstreet 	if (!k.k) {
3282581f89aSKent Overstreet 		bkey_init(&iter->k);
3292581f89aSKent Overstreet 		iter->k.p = bp.v->pos;
3302581f89aSKent Overstreet 		k.k = &iter->k;
3312581f89aSKent Overstreet 	}
3322581f89aSKent Overstreet 
3339e92d6e9SKent Overstreet 	if (k.k &&
334eb25733aSKent Overstreet 	    extent_matches_bp(c, bp.v->btree_id, bp.v->level, k, bp))
335a8c752bbSKent Overstreet 		return k;
336a8c752bbSKent Overstreet 
337a8c752bbSKent Overstreet 	bch2_trans_iter_exit(trans, iter);
338ca16fa6bSKent Overstreet 
339ca16fa6bSKent Overstreet 	if (!bp.v->level) {
340*d1041d8eSKent Overstreet 		int ret = backpointer_target_not_found(trans, bp, k, last_flushed, commit);
341c2c2a4d6SKent Overstreet 		return ret ? bkey_s_c_err(ret) : bkey_s_c_null;
342853960d0SKent Overstreet 	} else {
343*d1041d8eSKent Overstreet 		struct btree *b = __bch2_backpointer_get_node(trans, bp, iter, last_flushed, commit);
344ca16fa6bSKent Overstreet 		if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node))
345ca16fa6bSKent Overstreet 			return bkey_s_c_null;
346c2c2a4d6SKent Overstreet 		if (IS_ERR_OR_NULL(b))
347c2c2a4d6SKent Overstreet 			return ((struct bkey_s_c) { .k = ERR_CAST(b) });
348853960d0SKent Overstreet 
349853960d0SKent Overstreet 		return bkey_i_to_s_c(&b->key);
350853960d0SKent Overstreet 	}
351a8c752bbSKent Overstreet }
352a8c752bbSKent Overstreet 
bch2_backpointer_get_node(struct btree_trans * trans,struct bkey_s_c_backpointer bp,struct btree_iter * iter,struct bkey_buf * last_flushed)353a8c752bbSKent Overstreet struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
3549e92d6e9SKent Overstreet 					struct bkey_s_c_backpointer bp,
355056cae1cSKent Overstreet 					struct btree_iter *iter,
356056cae1cSKent Overstreet 					struct bkey_buf *last_flushed)
357a8c752bbSKent Overstreet {
358*d1041d8eSKent Overstreet 	return __bch2_backpointer_get_node(trans, bp, iter, last_flushed, true);
359a8c752bbSKent Overstreet }
360*d1041d8eSKent Overstreet 
bch2_backpointer_get_key(struct btree_trans * trans,struct bkey_s_c_backpointer bp,struct btree_iter * iter,unsigned iter_flags,struct bkey_buf * last_flushed)361*d1041d8eSKent Overstreet struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
362*d1041d8eSKent Overstreet 					 struct bkey_s_c_backpointer bp,
363*d1041d8eSKent Overstreet 					 struct btree_iter *iter,
364*d1041d8eSKent Overstreet 					 unsigned iter_flags,
365*d1041d8eSKent Overstreet 					 struct bkey_buf *last_flushed)
366*d1041d8eSKent Overstreet {
367*d1041d8eSKent Overstreet 	return __bch2_backpointer_get_key(trans, bp, iter, iter_flags, last_flushed, true);
368a8c752bbSKent Overstreet }
369a8c752bbSKent Overstreet 
bch2_check_backpointer_has_valid_bucket(struct btree_trans * trans,struct bkey_s_c k,struct bkey_buf * last_flushed)370c80f33b7SKent Overstreet static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, struct bkey_s_c k,
371c80f33b7SKent Overstreet 						   struct bkey_buf *last_flushed)
372a8c752bbSKent Overstreet {
373c80f33b7SKent Overstreet 	if (k.k->type != KEY_TYPE_backpointer)
374c80f33b7SKent Overstreet 		return 0;
375c80f33b7SKent Overstreet 
376a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
3779180ad2eSKent Overstreet 	struct btree_iter alloc_iter = {};
378a8c752bbSKent Overstreet 	struct bkey_s_c alloc_k;
379a8c752bbSKent Overstreet 	struct printbuf buf = PRINTBUF;
380a8c752bbSKent Overstreet 	int ret = 0;
381a8c752bbSKent Overstreet 
382633cf069SKent Overstreet 	struct bpos bucket;
383633cf069SKent Overstreet 	if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
384c80f33b7SKent Overstreet 		ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
385c80f33b7SKent Overstreet 		if (ret)
386c80f33b7SKent Overstreet 			goto out;
387c80f33b7SKent Overstreet 
388a850bde6SKent Overstreet 		if (fsck_err(trans, backpointer_to_missing_device,
3896bf3766bSColin Ian King 			     "backpointer for missing device:\n%s",
390633cf069SKent Overstreet 			     (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
391c80f33b7SKent Overstreet 			ret = bch2_backpointer_del(trans, k.k->p);
392a8c752bbSKent Overstreet 		goto out;
393a8c752bbSKent Overstreet 	}
394a8c752bbSKent Overstreet 
395633cf069SKent Overstreet 	alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc, bucket, 0);
396a8c752bbSKent Overstreet 	ret = bkey_err(alloc_k);
397a8c752bbSKent Overstreet 	if (ret)
398a8c752bbSKent Overstreet 		goto out;
399a8c752bbSKent Overstreet 
400c80f33b7SKent Overstreet 	if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
401c80f33b7SKent Overstreet 		ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
402c80f33b7SKent Overstreet 		if (ret)
403c80f33b7SKent Overstreet 			goto out;
404c80f33b7SKent Overstreet 
405c80f33b7SKent Overstreet 		if (fsck_err(trans, backpointer_to_missing_alloc,
406a8c752bbSKent Overstreet 			     "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
407a8c752bbSKent Overstreet 			     alloc_iter.pos.inode, alloc_iter.pos.offset,
408c80f33b7SKent Overstreet 			     (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
409c80f33b7SKent Overstreet 			ret = bch2_backpointer_del(trans, k.k->p);
410a8c752bbSKent Overstreet 	}
411a8c752bbSKent Overstreet out:
412a8c752bbSKent Overstreet fsck_err:
413a8c752bbSKent Overstreet 	bch2_trans_iter_exit(trans, &alloc_iter);
414a8c752bbSKent Overstreet 	printbuf_exit(&buf);
415a8c752bbSKent Overstreet 	return ret;
416a8c752bbSKent Overstreet }
417a8c752bbSKent Overstreet 
418a8c752bbSKent Overstreet /* verify that every backpointer has a corresponding alloc key */
bch2_check_btree_backpointers(struct bch_fs * c)419a8c752bbSKent Overstreet int bch2_check_btree_backpointers(struct bch_fs *c)
420a8c752bbSKent Overstreet {
421c80f33b7SKent Overstreet 	struct bkey_buf last_flushed;
422c80f33b7SKent Overstreet 	bch2_bkey_buf_init(&last_flushed);
423c80f33b7SKent Overstreet 	bkey_init(&last_flushed.k->k);
424c80f33b7SKent Overstreet 
425cf904c8dSKent Overstreet 	int ret = bch2_trans_run(c,
4266bd68ec2SKent Overstreet 		for_each_btree_key_commit(trans, iter,
427a8c752bbSKent Overstreet 			BTREE_ID_backpointers, POS_MIN, 0, k,
4283f0e297dSKent Overstreet 			NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
429c80f33b7SKent Overstreet 		  bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed)));
430c80f33b7SKent Overstreet 
431c80f33b7SKent Overstreet 	bch2_bkey_buf_exit(&last_flushed, c);
4321bb3c2a9SKent Overstreet 	bch_err_fn(c, ret);
4331bb3c2a9SKent Overstreet 	return ret;
434a8c752bbSKent Overstreet }
435a8c752bbSKent Overstreet 
4361a503904SKent Overstreet struct extents_to_bp_state {
437e48fda6cSKent Overstreet 	struct bpos	bp_start;
438e48fda6cSKent Overstreet 	struct bpos	bp_end;
4391a503904SKent Overstreet 	struct bkey_buf last_flushed;
4401a503904SKent Overstreet };
4411a503904SKent Overstreet 
drop_dev_and_update(struct btree_trans * trans,enum btree_id btree,struct bkey_s_c extent,unsigned dev)4424c02e63dSKent Overstreet static int drop_dev_and_update(struct btree_trans *trans, enum btree_id btree,
4434c02e63dSKent Overstreet 			       struct bkey_s_c extent, unsigned dev)
4444c02e63dSKent Overstreet {
4454c02e63dSKent Overstreet 	struct bkey_i *n = bch2_bkey_make_mut_noupdate(trans, extent);
4464c02e63dSKent Overstreet 	int ret = PTR_ERR_OR_ZERO(n);
4474c02e63dSKent Overstreet 	if (ret)
4484c02e63dSKent Overstreet 		return ret;
4494c02e63dSKent Overstreet 
4504c02e63dSKent Overstreet 	bch2_bkey_drop_device(bkey_i_to_s(n), dev);
4514c02e63dSKent Overstreet 	return bch2_btree_insert_trans(trans, btree, n, 0);
4524c02e63dSKent Overstreet }
4534c02e63dSKent Overstreet 
check_extent_checksum(struct btree_trans * trans,enum btree_id btree,struct bkey_s_c extent,enum btree_id o_btree,struct bkey_s_c extent2,unsigned dev)4544c02e63dSKent Overstreet static int check_extent_checksum(struct btree_trans *trans,
4554c02e63dSKent Overstreet 				 enum btree_id btree, struct bkey_s_c extent,
4564c02e63dSKent Overstreet 				 enum btree_id o_btree, struct bkey_s_c extent2, unsigned dev)
4574c02e63dSKent Overstreet {
4584c02e63dSKent Overstreet 	struct bch_fs *c = trans->c;
4594c02e63dSKent Overstreet 	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(extent);
4604c02e63dSKent Overstreet 	const union bch_extent_entry *entry;
4614c02e63dSKent Overstreet 	struct extent_ptr_decoded p;
4624c02e63dSKent Overstreet 	struct printbuf buf = PRINTBUF;
4634c02e63dSKent Overstreet 	void *data_buf = NULL;
4644c02e63dSKent Overstreet 	struct bio *bio = NULL;
4654c02e63dSKent Overstreet 	size_t bytes;
4664c02e63dSKent Overstreet 	int ret = 0;
4674c02e63dSKent Overstreet 
4684c02e63dSKent Overstreet 	if (bkey_is_btree_ptr(extent.k))
4694c02e63dSKent Overstreet 		return false;
4704c02e63dSKent Overstreet 
4714c02e63dSKent Overstreet 	bkey_for_each_ptr_decode(extent.k, ptrs, p, entry)
4724c02e63dSKent Overstreet 		if (p.ptr.dev == dev)
4734c02e63dSKent Overstreet 			goto found;
4744c02e63dSKent Overstreet 	BUG();
4754c02e63dSKent Overstreet found:
4764c02e63dSKent Overstreet 	if (!p.crc.csum_type)
4774c02e63dSKent Overstreet 		return false;
4784c02e63dSKent Overstreet 
4794c02e63dSKent Overstreet 	bytes = p.crc.compressed_size << 9;
4804c02e63dSKent Overstreet 
4812c91ab72SKent Overstreet 	struct bch_dev *ca = bch2_dev_get_ioref(c, dev, READ);
482466298e2SKent Overstreet 	if (!ca)
4834c02e63dSKent Overstreet 		return false;
4844c02e63dSKent Overstreet 
4854c02e63dSKent Overstreet 	data_buf = kvmalloc(bytes, GFP_KERNEL);
4864c02e63dSKent Overstreet 	if (!data_buf) {
4874c02e63dSKent Overstreet 		ret = -ENOMEM;
4884c02e63dSKent Overstreet 		goto err;
4894c02e63dSKent Overstreet 	}
4904c02e63dSKent Overstreet 
4910389c09bSKent Overstreet 	bio = bio_alloc(ca->disk_sb.bdev, buf_pages(data_buf, bytes), REQ_OP_READ, GFP_KERNEL);
4924c02e63dSKent Overstreet 	bio->bi_iter.bi_sector = p.ptr.offset;
4934c02e63dSKent Overstreet 	bch2_bio_map(bio, data_buf, bytes);
4944c02e63dSKent Overstreet 	ret = submit_bio_wait(bio);
4954c02e63dSKent Overstreet 	if (ret)
4964c02e63dSKent Overstreet 		goto err;
4974c02e63dSKent Overstreet 
4981ece5323SKent Overstreet 	prt_printf(&buf, "extents pointing to same space, but first extent checksum bad:\n");
499db514cf6SKent Overstreet 	bch2_btree_id_to_text(&buf, btree);
500db514cf6SKent Overstreet 	prt_str(&buf, " ");
5014c02e63dSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, extent);
5021ece5323SKent Overstreet 	prt_newline(&buf);
503db514cf6SKent Overstreet 	bch2_btree_id_to_text(&buf, o_btree);
504db514cf6SKent Overstreet 	prt_str(&buf, " ");
5054c02e63dSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, extent2);
5064c02e63dSKent Overstreet 
507cf49f8a8SKent Overstreet 	struct nonce nonce = extent_nonce(extent.k->bversion, p.crc);
5084c02e63dSKent Overstreet 	struct bch_csum csum = bch2_checksum(c, p.crc.csum_type, nonce, data_buf, bytes);
5094c02e63dSKent Overstreet 	if (fsck_err_on(bch2_crc_cmp(csum, p.crc.csum),
510a850bde6SKent Overstreet 			trans, dup_backpointer_to_bad_csum_extent,
5114c02e63dSKent Overstreet 			"%s", buf.buf))
5124c02e63dSKent Overstreet 		ret = drop_dev_and_update(trans, btree, extent, dev) ?: 1;
5134c02e63dSKent Overstreet fsck_err:
5144c02e63dSKent Overstreet err:
5154c02e63dSKent Overstreet 	if (bio)
5164c02e63dSKent Overstreet 		bio_put(bio);
5174c02e63dSKent Overstreet 	kvfree(data_buf);
518dcffc3b1SKent Overstreet 	percpu_ref_put(&ca->io_ref[READ]);
5194c02e63dSKent Overstreet 	printbuf_exit(&buf);
5204c02e63dSKent Overstreet 	return ret;
5214c02e63dSKent Overstreet }
5224c02e63dSKent Overstreet 
check_bp_exists(struct btree_trans * trans,struct extents_to_bp_state * s,struct bkey_i_backpointer * bp,struct bkey_s_c orig_k)523a8c752bbSKent Overstreet static int check_bp_exists(struct btree_trans *trans,
5241a503904SKent Overstreet 			   struct extents_to_bp_state *s,
525eb25733aSKent Overstreet 			   struct bkey_i_backpointer *bp,
5261a503904SKent Overstreet 			   struct bkey_s_c orig_k)
527a8c752bbSKent Overstreet {
528a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
5294c02e63dSKent Overstreet 	struct btree_iter other_extent_iter = {};
530a8c752bbSKent Overstreet 	struct printbuf buf = PRINTBUF;
531a8c752bbSKent Overstreet 
532e48fda6cSKent Overstreet 	if (bpos_lt(bp->k.p, s->bp_start) ||
533e48fda6cSKent Overstreet 	    bpos_gt(bp->k.p, s->bp_end))
534e48fda6cSKent Overstreet 		return 0;
5354c02e63dSKent Overstreet 
536e48fda6cSKent Overstreet 	struct btree_iter bp_iter;
537e48fda6cSKent Overstreet 	struct bkey_s_c bp_k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers, bp->k.p, 0);
538e48fda6cSKent Overstreet 	int ret = bkey_err(bp_k);
539a8c752bbSKent Overstreet 	if (ret)
540a8c752bbSKent Overstreet 		goto err;
541a8c752bbSKent Overstreet 
542a8c752bbSKent Overstreet 	if (bp_k.k->type != KEY_TYPE_backpointer ||
543eb25733aSKent Overstreet 	    memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp->v, sizeof(bp->v))) {
54492e1c29aSKent Overstreet 		ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed);
545cd404e5bSKent Overstreet 		if (ret)
546cd404e5bSKent Overstreet 			goto err;
547cd404e5bSKent Overstreet 
5484c02e63dSKent Overstreet 		goto check_existing_bp;
5497c057d35SKent Overstreet 	}
550a8c752bbSKent Overstreet out:
551a8c752bbSKent Overstreet err:
552a8c752bbSKent Overstreet fsck_err:
5534c02e63dSKent Overstreet 	bch2_trans_iter_exit(trans, &other_extent_iter);
554a8c752bbSKent Overstreet 	bch2_trans_iter_exit(trans, &bp_iter);
555a8c752bbSKent Overstreet 	printbuf_exit(&buf);
556a8c752bbSKent Overstreet 	return ret;
5574c02e63dSKent Overstreet check_existing_bp:
5584c02e63dSKent Overstreet 	/* Do we have a backpointer for a different extent? */
5594c02e63dSKent Overstreet 	if (bp_k.k->type != KEY_TYPE_backpointer)
5604c02e63dSKent Overstreet 		goto missing;
5614c02e63dSKent Overstreet 
5629e92d6e9SKent Overstreet 	struct bkey_s_c_backpointer other_bp = bkey_s_c_to_backpointer(bp_k);
5634c02e63dSKent Overstreet 
5644c02e63dSKent Overstreet 	struct bkey_s_c other_extent =
565*d1041d8eSKent Overstreet 		__bch2_backpointer_get_key(trans, other_bp, &other_extent_iter, 0, NULL, false);
5664c02e63dSKent Overstreet 	ret = bkey_err(other_extent);
5674c02e63dSKent Overstreet 	if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node)
5684c02e63dSKent Overstreet 		ret = 0;
5694c02e63dSKent Overstreet 	if (ret)
5704c02e63dSKent Overstreet 		goto err;
5714c02e63dSKent Overstreet 
5724c02e63dSKent Overstreet 	if (!other_extent.k)
5734c02e63dSKent Overstreet 		goto missing;
5744c02e63dSKent Overstreet 
575c3c9957cSKent Overstreet 	rcu_read_lock();
576c3c9957cSKent Overstreet 	struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp->k.p.inode);
577c3c9957cSKent Overstreet 	if (ca) {
578c3c9957cSKent Overstreet 		struct bkey_ptrs_c other_extent_ptrs = bch2_bkey_ptrs_c(other_extent);
579c3c9957cSKent Overstreet 		bkey_for_each_ptr(other_extent_ptrs, ptr)
580c3c9957cSKent Overstreet 			if (ptr->dev == bp->k.p.inode &&
581c3c9957cSKent Overstreet 			    dev_ptr_stale_rcu(ca, ptr)) {
582c3c9957cSKent Overstreet 				ret = drop_dev_and_update(trans, other_bp.v->btree_id,
583c3c9957cSKent Overstreet 							  other_extent, bp->k.p.inode);
584c3c9957cSKent Overstreet 				if (ret)
585c3c9957cSKent Overstreet 					goto err;
586c3c9957cSKent Overstreet 				goto out;
587c3c9957cSKent Overstreet 			}
588c3c9957cSKent Overstreet 	}
589c3c9957cSKent Overstreet 	rcu_read_unlock();
590c3c9957cSKent Overstreet 
5914c02e63dSKent Overstreet 	if (bch2_extents_match(orig_k, other_extent)) {
5924c02e63dSKent Overstreet 		printbuf_reset(&buf);
5934c02e63dSKent Overstreet 		prt_printf(&buf, "duplicate versions of same extent, deleting smaller\n");
5944c02e63dSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, orig_k);
5951ece5323SKent Overstreet 		prt_newline(&buf);
5964c02e63dSKent Overstreet 		bch2_bkey_val_to_text(&buf, c, other_extent);
5974c02e63dSKent Overstreet 		bch_err(c, "%s", buf.buf);
5984c02e63dSKent Overstreet 
5994c02e63dSKent Overstreet 		if (other_extent.k->size <= orig_k.k->size) {
600e48fda6cSKent Overstreet 			ret = drop_dev_and_update(trans, other_bp.v->btree_id,
601e48fda6cSKent Overstreet 						  other_extent, bp->k.p.inode);
6024c02e63dSKent Overstreet 			if (ret)
6034c02e63dSKent Overstreet 				goto err;
6044c02e63dSKent Overstreet 			goto out;
6054c02e63dSKent Overstreet 		} else {
606e48fda6cSKent Overstreet 			ret = drop_dev_and_update(trans, bp->v.btree_id, orig_k, bp->k.p.inode);
6074c02e63dSKent Overstreet 			if (ret)
6084c02e63dSKent Overstreet 				goto err;
6094c02e63dSKent Overstreet 			goto missing;
6104c02e63dSKent Overstreet 		}
6114c02e63dSKent Overstreet 	}
6124c02e63dSKent Overstreet 
613eb25733aSKent Overstreet 	ret = check_extent_checksum(trans,
614eb25733aSKent Overstreet 				    other_bp.v->btree_id, other_extent,
615eb25733aSKent Overstreet 				    bp->v.btree_id, orig_k,
616e48fda6cSKent Overstreet 				    bp->k.p.inode);
6174c02e63dSKent Overstreet 	if (ret < 0)
6184c02e63dSKent Overstreet 		goto err;
6194c02e63dSKent Overstreet 	if (ret) {
6204c02e63dSKent Overstreet 		ret = 0;
6214c02e63dSKent Overstreet 		goto missing;
6224c02e63dSKent Overstreet 	}
6234c02e63dSKent Overstreet 
624eb25733aSKent Overstreet 	ret = check_extent_checksum(trans, bp->v.btree_id, orig_k,
625e48fda6cSKent Overstreet 				    other_bp.v->btree_id, other_extent, bp->k.p.inode);
6264c02e63dSKent Overstreet 	if (ret < 0)
6274c02e63dSKent Overstreet 		goto err;
6284c02e63dSKent Overstreet 	if (ret) {
6294c02e63dSKent Overstreet 		ret = 0;
6304c02e63dSKent Overstreet 		goto out;
6314c02e63dSKent Overstreet 	}
6324c02e63dSKent Overstreet 
6334c02e63dSKent Overstreet 	printbuf_reset(&buf);
634e48fda6cSKent Overstreet 	prt_printf(&buf, "duplicate extents pointing to same space on dev %llu\n", bp->k.p.inode);
6354c02e63dSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, orig_k);
6361ece5323SKent Overstreet 	prt_newline(&buf);
6374c02e63dSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, other_extent);
6384c02e63dSKent Overstreet 	bch_err(c, "%s", buf.buf);
6394c02e63dSKent Overstreet 	ret = -BCH_ERR_fsck_repair_unimplemented;
6404c02e63dSKent Overstreet 	goto err;
641a8c752bbSKent Overstreet missing:
6424c02e63dSKent Overstreet 	printbuf_reset(&buf);
6430475c763SKent Overstreet 	prt_str(&buf, "missing backpointer\nfor:  ");
644a8c752bbSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, orig_k);
6450475c763SKent Overstreet 	prt_printf(&buf, "\nwant: ");
6460475c763SKent Overstreet 	bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp->k_i));
6474c02e63dSKent Overstreet 	prt_printf(&buf, "\ngot:  ");
6484c02e63dSKent Overstreet 	bch2_bkey_val_to_text(&buf, c, bp_k);
6494c02e63dSKent Overstreet 
650a850bde6SKent Overstreet 	if (fsck_err(trans, ptr_to_missing_backpointer, "%s", buf.buf))
651eb25733aSKent Overstreet 		ret = bch2_bucket_backpointer_mod(trans, orig_k, bp, true);
652a8c752bbSKent Overstreet 
653a8c752bbSKent Overstreet 	goto out;
654a8c752bbSKent Overstreet }
655a8c752bbSKent Overstreet 
check_extent_to_backpointers(struct btree_trans * trans,struct extents_to_bp_state * s,enum btree_id btree,unsigned level,struct bkey_s_c k)656a8c752bbSKent Overstreet static int check_extent_to_backpointers(struct btree_trans *trans,
6571a503904SKent Overstreet 					struct extents_to_bp_state *s,
658cd404e5bSKent Overstreet 					enum btree_id btree, unsigned level,
659cd404e5bSKent Overstreet 					struct bkey_s_c k)
660a8c752bbSKent Overstreet {
661a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
662c738866eSKent Overstreet 	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
663a8c752bbSKent Overstreet 	const union bch_extent_entry *entry;
664a8c752bbSKent Overstreet 	struct extent_ptr_decoded p;
665a8c752bbSKent Overstreet 
666a8c752bbSKent Overstreet 	bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
667aca7a26fSKent Overstreet 		if (p.ptr.dev == BCH_SB_MEMBER_INVALID)
668633cf069SKent Overstreet 			continue;
669a8c752bbSKent Overstreet 
670c738866eSKent Overstreet 		rcu_read_lock();
671c738866eSKent Overstreet 		struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev);
672c738866eSKent Overstreet 		bool check = ca && test_bit(PTR_BUCKET_NR(ca, &p.ptr), ca->bucket_backpointer_mismatches);
673c738866eSKent Overstreet 		bool empty = ca && test_bit(PTR_BUCKET_NR(ca, &p.ptr), ca->bucket_backpointer_empty);
67415800f3dSKent Overstreet 
67515800f3dSKent Overstreet 		bool stale = p.ptr.cached && (!ca || dev_ptr_stale_rcu(ca, &p.ptr));
676c738866eSKent Overstreet 		rcu_read_unlock();
677c738866eSKent Overstreet 
67815800f3dSKent Overstreet 		if ((check || empty) && !stale) {
679c738866eSKent Overstreet 			struct bkey_i_backpointer bp;
680aca7a26fSKent Overstreet 			bch2_extent_ptr_to_bp(c, btree, level, k, p, entry, &bp);
681c738866eSKent Overstreet 
682c738866eSKent Overstreet 			int ret = check
683c738866eSKent Overstreet 				? check_bp_exists(trans, s, &bp, k)
684c738866eSKent Overstreet 				: bch2_bucket_backpointer_mod(trans, k, &bp, true);
685a8c752bbSKent Overstreet 			if (ret)
686a8c752bbSKent Overstreet 				return ret;
687a8c752bbSKent Overstreet 		}
688c738866eSKent Overstreet 	}
689a8c752bbSKent Overstreet 
690a8c752bbSKent Overstreet 	return 0;
691a8c752bbSKent Overstreet }
692a8c752bbSKent Overstreet 
check_btree_root_to_backpointers(struct btree_trans * trans,struct extents_to_bp_state * s,enum btree_id btree_id,int * level)693a8c752bbSKent Overstreet static int check_btree_root_to_backpointers(struct btree_trans *trans,
6941a503904SKent Overstreet 					    struct extents_to_bp_state *s,
695b32f9a57SKent Overstreet 					    enum btree_id btree_id,
696cd404e5bSKent Overstreet 					    int *level)
697a8c752bbSKent Overstreet {
698a8c752bbSKent Overstreet 	struct bch_fs *c = trans->c;
699a8c752bbSKent Overstreet 	struct btree_iter iter;
700a8c752bbSKent Overstreet 	struct btree *b;
701a8c752bbSKent Overstreet 	struct bkey_s_c k;
702a8c752bbSKent Overstreet 	int ret;
703cd404e5bSKent Overstreet retry:
704cd404e5bSKent Overstreet 	bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN,
705cd404e5bSKent Overstreet 				  0, bch2_btree_id_root(c, btree_id)->b->c.level, 0);
7069180ad2eSKent Overstreet 	b = bch2_btree_iter_peek_node(trans, &iter);
707a8c752bbSKent Overstreet 	ret = PTR_ERR_OR_ZERO(b);
708a8c752bbSKent Overstreet 	if (ret)
709a8c752bbSKent Overstreet 		goto err;
710a8c752bbSKent Overstreet 
711cd404e5bSKent Overstreet 	if (b != btree_node_root(c, b)) {
712cd404e5bSKent Overstreet 		bch2_trans_iter_exit(trans, &iter);
713cd404e5bSKent Overstreet 		goto retry;
714cd404e5bSKent Overstreet 	}
715cd404e5bSKent Overstreet 
716cd404e5bSKent Overstreet 	*level = b->c.level;
717a8c752bbSKent Overstreet 
718a8c752bbSKent Overstreet 	k = bkey_i_to_s_c(&b->key);
7191a503904SKent Overstreet 	ret = check_extent_to_backpointers(trans, s, btree_id, b->c.level + 1, k);
720a8c752bbSKent Overstreet err:
721a8c752bbSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
722a8c752bbSKent Overstreet 	return ret;
723a8c752bbSKent Overstreet }
724a8c752bbSKent Overstreet 
bp_to_bbpos(struct bch_backpointer bp)72523792a71SKent Overstreet static inline struct bbpos bp_to_bbpos(struct bch_backpointer bp)
72623792a71SKent Overstreet {
72723792a71SKent Overstreet 	return (struct bbpos) {
72823792a71SKent Overstreet 		.btree	= bp.btree_id,
72923792a71SKent Overstreet 		.pos	= bp.pos,
73023792a71SKent Overstreet 	};
73123792a71SKent Overstreet }
73223792a71SKent Overstreet 
mem_may_pin_bytes(struct bch_fs * c)73391dcad18SKent Overstreet static u64 mem_may_pin_bytes(struct bch_fs *c)
73423792a71SKent Overstreet {
73523792a71SKent Overstreet 	struct sysinfo i;
73623792a71SKent Overstreet 	si_meminfo(&i);
73791dcad18SKent Overstreet 
73891dcad18SKent Overstreet 	u64 mem_bytes = i.totalram * i.mem_unit;
73991dcad18SKent Overstreet 	return div_u64(mem_bytes * c->opts.fsck_memory_usage_percent, 100);
74091dcad18SKent Overstreet }
74191dcad18SKent Overstreet 
btree_nodes_fit_in_ram(struct bch_fs * c)74291dcad18SKent Overstreet static size_t btree_nodes_fit_in_ram(struct bch_fs *c)
74391dcad18SKent Overstreet {
74491dcad18SKent Overstreet 	return div_u64(mem_may_pin_bytes(c), c->opts.btree_node_size);
74523792a71SKent Overstreet }
74623792a71SKent Overstreet 
bch2_get_btree_in_memory_pos(struct btree_trans * trans,u64 btree_leaf_mask,u64 btree_interior_mask,struct bbpos start,struct bbpos * end)74773bd774dSKent Overstreet static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
74891dcad18SKent Overstreet 					u64 btree_leaf_mask,
74991dcad18SKent Overstreet 					u64 btree_interior_mask,
75023792a71SKent Overstreet 					struct bbpos start, struct bbpos *end)
75123792a71SKent Overstreet {
75291dcad18SKent Overstreet 	struct bch_fs *c = trans->c;
75391dcad18SKent Overstreet 	s64 mem_may_pin = mem_may_pin_bytes(c);
75423792a71SKent Overstreet 	int ret = 0;
75523792a71SKent Overstreet 
7567a51608dSKent Overstreet 	bch2_btree_cache_unpin(c);
7577a51608dSKent Overstreet 
75891dcad18SKent Overstreet 	btree_interior_mask |= btree_leaf_mask;
75991dcad18SKent Overstreet 
7607a51608dSKent Overstreet 	c->btree_cache.pinned_nodes_mask[0]		= btree_leaf_mask;
7617a51608dSKent Overstreet 	c->btree_cache.pinned_nodes_mask[1]		= btree_interior_mask;
76291dcad18SKent Overstreet 	c->btree_cache.pinned_nodes_start		= start;
76391dcad18SKent Overstreet 	c->btree_cache.pinned_nodes_end			= *end = BBPOS_MAX;
76491dcad18SKent Overstreet 
76591dcad18SKent Overstreet 	for (enum btree_id btree = start.btree;
76691dcad18SKent Overstreet 	     btree < BTREE_ID_NR && !ret;
76791dcad18SKent Overstreet 	     btree++) {
76852fd0f96SKent Overstreet 		unsigned depth = (BIT_ULL(btree) & btree_leaf_mask) ? 0 : 1;
76923792a71SKent Overstreet 
77052fd0f96SKent Overstreet 		if (!(BIT_ULL(btree) & btree_leaf_mask) &&
77152fd0f96SKent Overstreet 		    !(BIT_ULL(btree) & btree_interior_mask))
77223792a71SKent Overstreet 			continue;
77323792a71SKent Overstreet 
774968feb85SKent Overstreet 		ret = __for_each_btree_node(trans, iter, btree,
77523792a71SKent Overstreet 				      btree == start.btree ? start.pos : POS_MIN,
776968feb85SKent Overstreet 				      0, depth, BTREE_ITER_prefetch, b, ({
77791dcad18SKent Overstreet 			mem_may_pin -= btree_buf_bytes(b);
77891dcad18SKent Overstreet 			if (mem_may_pin <= 0) {
77991dcad18SKent Overstreet 				c->btree_cache.pinned_nodes_end = *end =
78091dcad18SKent Overstreet 					BBPOS(btree, b->key.k.p);
781968feb85SKent Overstreet 				break;
78223792a71SKent Overstreet 			}
7837a51608dSKent Overstreet 			bch2_node_pin(c, b);
784968feb85SKent Overstreet 			0;
785968feb85SKent Overstreet 		}));
78623792a71SKent Overstreet 	}
78723792a71SKent Overstreet 
78823792a71SKent Overstreet 	return ret;
78923792a71SKent Overstreet }
79023792a71SKent Overstreet 
bch2_check_extents_to_backpointers_pass(struct btree_trans * trans,struct extents_to_bp_state * s)791b32f9a57SKent Overstreet static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
7921a503904SKent Overstreet 						   struct extents_to_bp_state *s)
793a8c752bbSKent Overstreet {
794faa6cb6cSKent Overstreet 	struct bch_fs *c = trans->c;
795b99a94fdSKent Overstreet 	struct progress_indicator_state progress;
796a8c752bbSKent Overstreet 	int ret = 0;
797a8c752bbSKent Overstreet 
798baabeb49SKent Overstreet 	bch2_progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_extents)|BIT_ULL(BTREE_ID_reflink));
799b99a94fdSKent Overstreet 
8001a503904SKent Overstreet 	for (enum btree_id btree_id = 0;
8011a503904SKent Overstreet 	     btree_id < btree_id_nr_alive(c);
8021a503904SKent Overstreet 	     btree_id++) {
803cd404e5bSKent Overstreet 		int level, depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
804a8c752bbSKent Overstreet 
805b32f9a57SKent Overstreet 		ret = commit_do(trans, NULL, NULL,
806cb52d23eSKent Overstreet 				BCH_TRANS_COMMIT_no_enospc,
8071a503904SKent Overstreet 				check_btree_root_to_backpointers(trans, s, btree_id, &level));
808cd404e5bSKent Overstreet 		if (ret)
809cd404e5bSKent Overstreet 			return ret;
810cd404e5bSKent Overstreet 
811cd404e5bSKent Overstreet 		while (level >= depth) {
8121a503904SKent Overstreet 			struct btree_iter iter;
813665e8b32SKent Overstreet 			bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, level,
8145dd8c60eSKent Overstreet 						  BTREE_ITER_prefetch);
8151a503904SKent Overstreet 
816665e8b32SKent Overstreet 			ret = for_each_btree_key_continue(trans, iter, 0, k, ({
817baabeb49SKent Overstreet 				bch2_progress_update_iter(trans, &progress, &iter, "extents_to_backpointers");
8181a503904SKent Overstreet 				check_extent_to_backpointers(trans, s, btree_id, level, k) ?:
819665e8b32SKent Overstreet 				bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
820665e8b32SKent Overstreet 			}));
821cd404e5bSKent Overstreet 			if (ret)
822b32f9a57SKent Overstreet 				return ret;
823cd404e5bSKent Overstreet 
824cd404e5bSKent Overstreet 			--level;
825cd404e5bSKent Overstreet 		}
826cd404e5bSKent Overstreet 	}
827cd404e5bSKent Overstreet 
828cd404e5bSKent Overstreet 	return 0;
829b32f9a57SKent Overstreet }
830b32f9a57SKent Overstreet 
831c738866eSKent Overstreet enum alloc_sector_counter {
832c738866eSKent Overstreet 	ALLOC_dirty,
833c738866eSKent Overstreet 	ALLOC_cached,
834c738866eSKent Overstreet 	ALLOC_stripe,
835c738866eSKent Overstreet 	ALLOC_SECTORS_NR
836c738866eSKent Overstreet };
837c738866eSKent Overstreet 
data_type_to_alloc_counter(enum bch_data_type t)83896232247SKent Overstreet static int data_type_to_alloc_counter(enum bch_data_type t)
839c738866eSKent Overstreet {
840c738866eSKent Overstreet 	switch (t) {
841c738866eSKent Overstreet 	case BCH_DATA_btree:
842c738866eSKent Overstreet 	case BCH_DATA_user:
843c738866eSKent Overstreet 		return ALLOC_dirty;
844c738866eSKent Overstreet 	case BCH_DATA_cached:
845c738866eSKent Overstreet 		return ALLOC_cached;
846c738866eSKent Overstreet 	case BCH_DATA_stripe:
8476a9f681eSKent Overstreet 	case BCH_DATA_parity:
848c738866eSKent Overstreet 		return ALLOC_stripe;
849c738866eSKent Overstreet 	default:
85096232247SKent Overstreet 		return -1;
851c738866eSKent Overstreet 	}
852c738866eSKent Overstreet }
853c738866eSKent Overstreet 
854c738866eSKent Overstreet static int check_bucket_backpointers_to_extents(struct btree_trans *, struct bch_dev *, struct bpos);
855c738866eSKent Overstreet 
check_bucket_backpointer_mismatch(struct btree_trans * trans,struct bkey_s_c alloc_k,struct bkey_buf * last_flushed)856c738866eSKent Overstreet static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct bkey_s_c alloc_k,
857c738866eSKent Overstreet 					     struct bkey_buf *last_flushed)
858c738866eSKent Overstreet {
859c738866eSKent Overstreet 	struct bch_fs *c = trans->c;
860c738866eSKent Overstreet 	struct bch_alloc_v4 a_convert;
861c738866eSKent Overstreet 	const struct bch_alloc_v4 *a = bch2_alloc_to_v4(alloc_k, &a_convert);
862c738866eSKent Overstreet 	bool need_commit = false;
863c738866eSKent Overstreet 
864c738866eSKent Overstreet 	if (a->data_type == BCH_DATA_sb ||
865c738866eSKent Overstreet 	    a->data_type == BCH_DATA_journal ||
866c738866eSKent Overstreet 	    a->data_type == BCH_DATA_parity)
867c738866eSKent Overstreet 		return 0;
868c738866eSKent Overstreet 
869c738866eSKent Overstreet 	u32 sectors[ALLOC_SECTORS_NR];
870c738866eSKent Overstreet 	memset(sectors, 0, sizeof(sectors));
871c738866eSKent Overstreet 
872c738866eSKent Overstreet 	struct bch_dev *ca = bch2_dev_bucket_tryget_noerror(trans->c, alloc_k.k->p);
873c738866eSKent Overstreet 	if (!ca)
874c738866eSKent Overstreet 		return 0;
875c738866eSKent Overstreet 
876c738866eSKent Overstreet 	struct btree_iter iter;
877c738866eSKent Overstreet 	struct bkey_s_c bp_k;
878c738866eSKent Overstreet 	int ret = 0;
879c738866eSKent Overstreet 	for_each_btree_key_max_norestart(trans, iter, BTREE_ID_backpointers,
880c738866eSKent Overstreet 				bucket_pos_to_bp_start(ca, alloc_k.k->p),
881c738866eSKent Overstreet 				bucket_pos_to_bp_end(ca, alloc_k.k->p), 0, bp_k, ret) {
882c738866eSKent Overstreet 		if (bp_k.k->type != KEY_TYPE_backpointer)
883c738866eSKent Overstreet 			continue;
884c738866eSKent Overstreet 
885c738866eSKent Overstreet 		struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(bp_k);
886c738866eSKent Overstreet 
887c738866eSKent Overstreet 		if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen &&
888c738866eSKent Overstreet 		    (bp.v->bucket_gen != a->gen ||
889c738866eSKent Overstreet 		     bp.v->pad)) {
890c738866eSKent Overstreet 			ret = bch2_backpointer_del(trans, bp_k.k->p);
891c738866eSKent Overstreet 			if (ret)
892c738866eSKent Overstreet 				break;
893c738866eSKent Overstreet 
894c738866eSKent Overstreet 			need_commit = true;
895c738866eSKent Overstreet 			continue;
896c738866eSKent Overstreet 		}
897c738866eSKent Overstreet 
898c738866eSKent Overstreet 		if (bp.v->bucket_gen != a->gen)
899c738866eSKent Overstreet 			continue;
900c738866eSKent Overstreet 
90196232247SKent Overstreet 		int alloc_counter = data_type_to_alloc_counter(bp.v->data_type);
90296232247SKent Overstreet 		if (alloc_counter < 0)
90396232247SKent Overstreet 			continue;
90496232247SKent Overstreet 
90596232247SKent Overstreet 		sectors[alloc_counter] += bp.v->bucket_len;
906c738866eSKent Overstreet 	};
907c738866eSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
908c738866eSKent Overstreet 	if (ret)
909c738866eSKent Overstreet 		goto err;
910c738866eSKent Overstreet 
911c738866eSKent Overstreet 	if (need_commit) {
912c738866eSKent Overstreet 		ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
913c738866eSKent Overstreet 		if (ret)
914c738866eSKent Overstreet 			goto err;
915c738866eSKent Overstreet 	}
916c738866eSKent Overstreet 
917c738866eSKent Overstreet 	if (sectors[ALLOC_dirty]  != a->dirty_sectors ||
91815800f3dSKent Overstreet 	    sectors[ALLOC_cached] != a->cached_sectors ||
919c738866eSKent Overstreet 	    sectors[ALLOC_stripe] != a->stripe_sectors) {
920c738866eSKent Overstreet 		if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen) {
921c738866eSKent Overstreet 			ret = bch2_backpointers_maybe_flush(trans, alloc_k, last_flushed);
922c738866eSKent Overstreet 			if (ret)
923c738866eSKent Overstreet 				goto err;
924c738866eSKent Overstreet 		}
925c738866eSKent Overstreet 
926c738866eSKent Overstreet 		if (sectors[ALLOC_dirty]  > a->dirty_sectors ||
92715800f3dSKent Overstreet 		    sectors[ALLOC_cached] > a->cached_sectors ||
928c738866eSKent Overstreet 		    sectors[ALLOC_stripe] > a->stripe_sectors) {
929c738866eSKent Overstreet 			ret = check_bucket_backpointers_to_extents(trans, ca, alloc_k.k->p) ?:
930c738866eSKent Overstreet 				-BCH_ERR_transaction_restart_nested;
931c738866eSKent Overstreet 			goto err;
932c738866eSKent Overstreet 		}
933c738866eSKent Overstreet 
934c738866eSKent Overstreet 		if (!sectors[ALLOC_dirty] &&
93515800f3dSKent Overstreet 		    !sectors[ALLOC_stripe] &&
93615800f3dSKent Overstreet 		    !sectors[ALLOC_cached])
937c738866eSKent Overstreet 			__set_bit(alloc_k.k->p.offset, ca->bucket_backpointer_empty);
938c738866eSKent Overstreet 		else
939c738866eSKent Overstreet 			__set_bit(alloc_k.k->p.offset, ca->bucket_backpointer_mismatches);
940c738866eSKent Overstreet 	}
941c738866eSKent Overstreet err:
942c738866eSKent Overstreet 	bch2_dev_put(ca);
943c738866eSKent Overstreet 	return ret;
944c738866eSKent Overstreet }
945c738866eSKent Overstreet 
backpointer_node_has_missing(struct bch_fs * c,struct bkey_s_c k)946c738866eSKent Overstreet static bool backpointer_node_has_missing(struct bch_fs *c, struct bkey_s_c k)
947c738866eSKent Overstreet {
948c738866eSKent Overstreet 	switch (k.k->type) {
949c738866eSKent Overstreet 	case KEY_TYPE_btree_ptr_v2: {
950c738866eSKent Overstreet 		bool ret = false;
951c738866eSKent Overstreet 
952c738866eSKent Overstreet 		rcu_read_lock();
953c738866eSKent Overstreet 		struct bpos pos = bkey_s_c_to_btree_ptr_v2(k).v->min_key;
954c738866eSKent Overstreet 		while (pos.inode <= k.k->p.inode) {
955c738866eSKent Overstreet 			if (pos.inode >= c->sb.nr_devices)
956c738866eSKent Overstreet 				break;
957c738866eSKent Overstreet 
958c738866eSKent Overstreet 			struct bch_dev *ca = bch2_dev_rcu_noerror(c, pos.inode);
959c738866eSKent Overstreet 			if (!ca)
960c738866eSKent Overstreet 				goto next;
961c738866eSKent Overstreet 
962c738866eSKent Overstreet 			struct bpos bucket = bp_pos_to_bucket(ca, pos);
963c738866eSKent Overstreet 			bucket.offset = find_next_bit(ca->bucket_backpointer_mismatches,
964c738866eSKent Overstreet 						      ca->mi.nbuckets, bucket.offset);
965c738866eSKent Overstreet 			if (bucket.offset == ca->mi.nbuckets)
966c738866eSKent Overstreet 				goto next;
967c738866eSKent Overstreet 
968c738866eSKent Overstreet 			ret = bpos_le(bucket_pos_to_bp_end(ca, bucket), k.k->p);
969c738866eSKent Overstreet 			if (ret)
970c738866eSKent Overstreet 				break;
971c738866eSKent Overstreet next:
972c738866eSKent Overstreet 			pos = SPOS(pos.inode + 1, 0, 0);
973c738866eSKent Overstreet 		}
974c738866eSKent Overstreet 		rcu_read_unlock();
975c738866eSKent Overstreet 
976c738866eSKent Overstreet 		return ret;
977c738866eSKent Overstreet 	}
978c738866eSKent Overstreet 	case KEY_TYPE_btree_ptr:
979c738866eSKent Overstreet 		return true;
980c738866eSKent Overstreet 	default:
981c738866eSKent Overstreet 		return false;
982c738866eSKent Overstreet 	}
983c738866eSKent Overstreet }
984c738866eSKent Overstreet 
btree_node_get_and_pin(struct btree_trans * trans,struct bkey_i * k,enum btree_id btree,unsigned level)985c738866eSKent Overstreet static int btree_node_get_and_pin(struct btree_trans *trans, struct bkey_i *k,
986c738866eSKent Overstreet 				  enum btree_id btree, unsigned level)
987c738866eSKent Overstreet {
988c738866eSKent Overstreet 	struct btree_iter iter;
989c738866eSKent Overstreet 	bch2_trans_node_iter_init(trans, &iter, btree, k->k.p, 0, level, 0);
9909180ad2eSKent Overstreet 	struct btree *b = bch2_btree_iter_peek_node(trans, &iter);
991c738866eSKent Overstreet 	int ret = PTR_ERR_OR_ZERO(b);
992c738866eSKent Overstreet 	if (ret)
993c738866eSKent Overstreet 		goto err;
994c738866eSKent Overstreet 
995c738866eSKent Overstreet 	if (b)
996c738866eSKent Overstreet 		bch2_node_pin(trans->c, b);
997c738866eSKent Overstreet err:
998c738866eSKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
999c738866eSKent Overstreet 	return ret;
1000c738866eSKent Overstreet }
1001c738866eSKent Overstreet 
bch2_pin_backpointer_nodes_with_missing(struct btree_trans * trans,struct bpos start,struct bpos * end)1002c738866eSKent Overstreet static int bch2_pin_backpointer_nodes_with_missing(struct btree_trans *trans,
1003c738866eSKent Overstreet 						   struct bpos start, struct bpos *end)
1004c738866eSKent Overstreet {
1005c738866eSKent Overstreet 	struct bch_fs *c = trans->c;
1006c738866eSKent Overstreet 	int ret = 0;
1007c738866eSKent Overstreet 
1008c738866eSKent Overstreet 	struct bkey_buf tmp;
1009c738866eSKent Overstreet 	bch2_bkey_buf_init(&tmp);
1010c738866eSKent Overstreet 
1011c738866eSKent Overstreet 	bch2_btree_cache_unpin(c);
1012c738866eSKent Overstreet 
1013c738866eSKent Overstreet 	*end = SPOS_MAX;
1014c738866eSKent Overstreet 
1015c738866eSKent Overstreet 	s64 mem_may_pin = mem_may_pin_bytes(c);
1016c738866eSKent Overstreet 	struct btree_iter iter;
1017c738866eSKent Overstreet 	bch2_trans_node_iter_init(trans, &iter, BTREE_ID_backpointers, start,
1018c738866eSKent Overstreet 				  0, 1, BTREE_ITER_prefetch);
1019c738866eSKent Overstreet 	ret = for_each_btree_key_continue(trans, iter, 0, k, ({
1020c738866eSKent Overstreet 		if (!backpointer_node_has_missing(c, k))
1021c738866eSKent Overstreet 			continue;
1022c738866eSKent Overstreet 
1023c738866eSKent Overstreet 		mem_may_pin -= c->opts.btree_node_size;
1024c738866eSKent Overstreet 		if (mem_may_pin <= 0)
1025c738866eSKent Overstreet 			break;
1026c738866eSKent Overstreet 
1027c738866eSKent Overstreet 		bch2_bkey_buf_reassemble(&tmp, c, k);
1028c738866eSKent Overstreet 		struct btree_path *path = btree_iter_path(trans, &iter);
1029c738866eSKent Overstreet 
1030c738866eSKent Overstreet 		BUG_ON(path->level != 1);
1031c738866eSKent Overstreet 
1032c738866eSKent Overstreet 		bch2_btree_node_prefetch(trans, path, tmp.k, path->btree_id, path->level - 1);
1033c738866eSKent Overstreet 	}));
1034c738866eSKent Overstreet 	if (ret)
1035c738866eSKent Overstreet 		return ret;
1036c738866eSKent Overstreet 
1037c738866eSKent Overstreet 	struct bpos pinned = SPOS_MAX;
1038c738866eSKent Overstreet 	mem_may_pin = mem_may_pin_bytes(c);
1039c738866eSKent Overstreet 	bch2_trans_node_iter_init(trans, &iter, BTREE_ID_backpointers, start,
1040c738866eSKent Overstreet 				  0, 1, BTREE_ITER_prefetch);
1041c738866eSKent Overstreet 	ret = for_each_btree_key_continue(trans, iter, 0, k, ({
1042c738866eSKent Overstreet 		if (!backpointer_node_has_missing(c, k))
1043c738866eSKent Overstreet 			continue;
1044c738866eSKent Overstreet 
1045c738866eSKent Overstreet 		mem_may_pin -= c->opts.btree_node_size;
1046c738866eSKent Overstreet 		if (mem_may_pin <= 0) {
1047c738866eSKent Overstreet 			*end = pinned;
1048c738866eSKent Overstreet 			break;
1049c738866eSKent Overstreet 		}
1050c738866eSKent Overstreet 
1051c738866eSKent Overstreet 		bch2_bkey_buf_reassemble(&tmp, c, k);
1052c738866eSKent Overstreet 		struct btree_path *path = btree_iter_path(trans, &iter);
1053c738866eSKent Overstreet 
1054c738866eSKent Overstreet 		BUG_ON(path->level != 1);
1055c738866eSKent Overstreet 
1056c738866eSKent Overstreet 		int ret2 = btree_node_get_and_pin(trans, tmp.k, path->btree_id, path->level - 1);
1057c738866eSKent Overstreet 
1058c738866eSKent Overstreet 		if (!ret2)
1059c738866eSKent Overstreet 			pinned = tmp.k->k.p;
1060c738866eSKent Overstreet 
1061c738866eSKent Overstreet 		ret;
1062c738866eSKent Overstreet 	}));
1063c738866eSKent Overstreet 	if (ret)
1064c738866eSKent Overstreet 		return ret;
1065c738866eSKent Overstreet 
1066c738866eSKent Overstreet 	return ret;
1067c738866eSKent Overstreet }
1068c738866eSKent Overstreet 
bch2_check_extents_to_backpointers(struct bch_fs * c)1069b32f9a57SKent Overstreet int bch2_check_extents_to_backpointers(struct bch_fs *c)
1070b32f9a57SKent Overstreet {
1071c738866eSKent Overstreet 	int ret = 0;
1072c738866eSKent Overstreet 
1073c738866eSKent Overstreet 	/*
1074c738866eSKent Overstreet 	 * Can't allow devices to come/go/resize while we have bucket bitmaps
1075c738866eSKent Overstreet 	 * allocated
1076c738866eSKent Overstreet 	 */
10772dd202dbSKent Overstreet 	down_read(&c->state_lock);
1078c738866eSKent Overstreet 
1079c738866eSKent Overstreet 	for_each_member_device(c, ca) {
1080c738866eSKent Overstreet 		BUG_ON(ca->bucket_backpointer_mismatches);
1081c738866eSKent Overstreet 		ca->bucket_backpointer_mismatches = kvcalloc(BITS_TO_LONGS(ca->mi.nbuckets),
1082c738866eSKent Overstreet 							     sizeof(unsigned long),
1083c738866eSKent Overstreet 							     GFP_KERNEL);
1084c738866eSKent Overstreet 		ca->bucket_backpointer_empty = kvcalloc(BITS_TO_LONGS(ca->mi.nbuckets),
1085c738866eSKent Overstreet 							sizeof(unsigned long),
1086c738866eSKent Overstreet 							GFP_KERNEL);
1087c738866eSKent Overstreet 		if (!ca->bucket_backpointer_mismatches ||
1088c738866eSKent Overstreet 		    !ca->bucket_backpointer_empty) {
1089c738866eSKent Overstreet 			bch2_dev_put(ca);
1090c738866eSKent Overstreet 			ret = -BCH_ERR_ENOMEM_backpointer_mismatches_bitmap;
1091c738866eSKent Overstreet 			goto err_free_bitmaps;
1092c738866eSKent Overstreet 		}
1093c738866eSKent Overstreet 	}
1094c738866eSKent Overstreet 
10956bd68ec2SKent Overstreet 	struct btree_trans *trans = bch2_trans_get(c);
1096e48fda6cSKent Overstreet 	struct extents_to_bp_state s = { .bp_start = POS_MIN };
1097b32f9a57SKent Overstreet 
10981a503904SKent Overstreet 	bch2_bkey_buf_init(&s.last_flushed);
10991a503904SKent Overstreet 	bkey_init(&s.last_flushed.k->k);
11001a503904SKent Overstreet 
1101c738866eSKent Overstreet 	ret = for_each_btree_key(trans, iter, BTREE_ID_alloc,
1102c738866eSKent Overstreet 				 POS_MIN, BTREE_ITER_prefetch, k, ({
1103c738866eSKent Overstreet 		check_bucket_backpointer_mismatch(trans, k, &s.last_flushed);
1104c738866eSKent Overstreet 	}));
1105c738866eSKent Overstreet 	if (ret)
1106c738866eSKent Overstreet 		goto err;
1107c738866eSKent Overstreet 
1108c738866eSKent Overstreet 	u64 nr_buckets = 0, nr_mismatches = 0, nr_empty = 0;
1109c738866eSKent Overstreet 	for_each_member_device(c, ca) {
1110c738866eSKent Overstreet 		nr_buckets	+= ca->mi.nbuckets;
1111c738866eSKent Overstreet 		nr_mismatches	+= bitmap_weight(ca->bucket_backpointer_mismatches, ca->mi.nbuckets);
1112c738866eSKent Overstreet 		nr_empty	+= bitmap_weight(ca->bucket_backpointer_empty, ca->mi.nbuckets);
1113c738866eSKent Overstreet 	}
1114c738866eSKent Overstreet 
1115c738866eSKent Overstreet 	if (!nr_mismatches && !nr_empty)
1116c738866eSKent Overstreet 		goto err;
1117c738866eSKent Overstreet 
1118c738866eSKent Overstreet 	bch_info(c, "scanning for missing backpointers in %llu/%llu buckets",
1119c738866eSKent Overstreet 		 nr_mismatches + nr_empty, nr_buckets);
1120c738866eSKent Overstreet 
1121b32f9a57SKent Overstreet 	while (1) {
1122c738866eSKent Overstreet 		ret = bch2_pin_backpointer_nodes_with_missing(trans, s.bp_start, &s.bp_end);
1123b32f9a57SKent Overstreet 		if (ret)
1124b32f9a57SKent Overstreet 			break;
1125b32f9a57SKent Overstreet 
1126e48fda6cSKent Overstreet 		if ( bpos_eq(s.bp_start, POS_MIN) &&
1127e48fda6cSKent Overstreet 		    !bpos_eq(s.bp_end, SPOS_MAX))
1128b32f9a57SKent Overstreet 			bch_verbose(c, "%s(): alloc info does not fit in ram, running in multiple passes with %zu nodes per pass",
1129b32f9a57SKent Overstreet 				    __func__, btree_nodes_fit_in_ram(c));
1130b32f9a57SKent Overstreet 
1131e48fda6cSKent Overstreet 		if (!bpos_eq(s.bp_start, POS_MIN) ||
1132e48fda6cSKent Overstreet 		    !bpos_eq(s.bp_end, SPOS_MAX)) {
1133b32f9a57SKent Overstreet 			struct printbuf buf = PRINTBUF;
1134b32f9a57SKent Overstreet 
1135b32f9a57SKent Overstreet 			prt_str(&buf, "check_extents_to_backpointers(): ");
1136e48fda6cSKent Overstreet 			bch2_bpos_to_text(&buf, s.bp_start);
1137b32f9a57SKent Overstreet 			prt_str(&buf, "-");
1138e48fda6cSKent Overstreet 			bch2_bpos_to_text(&buf, s.bp_end);
1139b32f9a57SKent Overstreet 
1140b32f9a57SKent Overstreet 			bch_verbose(c, "%s", buf.buf);
1141b32f9a57SKent Overstreet 			printbuf_exit(&buf);
1142b32f9a57SKent Overstreet 		}
1143b32f9a57SKent Overstreet 
11441a503904SKent Overstreet 		ret = bch2_check_extents_to_backpointers_pass(trans, &s);
1145e48fda6cSKent Overstreet 		if (ret || bpos_eq(s.bp_end, SPOS_MAX))
1146b32f9a57SKent Overstreet 			break;
1147b32f9a57SKent Overstreet 
1148e48fda6cSKent Overstreet 		s.bp_start = bpos_successor(s.bp_end);
1149b32f9a57SKent Overstreet 	}
1150c738866eSKent Overstreet err:
11516bd68ec2SKent Overstreet 	bch2_trans_put(trans);
11521a503904SKent Overstreet 	bch2_bkey_buf_exit(&s.last_flushed, c);
11537a51608dSKent Overstreet 	bch2_btree_cache_unpin(c);
1154c738866eSKent Overstreet err_free_bitmaps:
1155c738866eSKent Overstreet 	for_each_member_device(c, ca) {
1156c738866eSKent Overstreet 		kvfree(ca->bucket_backpointer_empty);
1157c738866eSKent Overstreet 		ca->bucket_backpointer_empty = NULL;
1158c738866eSKent Overstreet 		kvfree(ca->bucket_backpointer_mismatches);
1159c738866eSKent Overstreet 		ca->bucket_backpointer_mismatches = NULL;
1160c738866eSKent Overstreet 	}
116191dcad18SKent Overstreet 
11622dd202dbSKent Overstreet 	up_read(&c->state_lock);
11631bb3c2a9SKent Overstreet 	bch_err_fn(c, ret);
1164a8c752bbSKent Overstreet 	return ret;
1165a8c752bbSKent Overstreet }
1166a8c752bbSKent Overstreet 
check_one_backpointer(struct btree_trans * trans,struct bbpos start,struct bbpos end,struct bkey_s_c bp_k,struct bkey_buf * last_flushed)1167a8c752bbSKent Overstreet static int check_one_backpointer(struct btree_trans *trans,
116823792a71SKent Overstreet 				 struct bbpos start,
1169e07cb974SKent Overstreet 				 struct bbpos end,
11702642084fSKent Overstreet 				 struct bkey_s_c bp_k,
117192e1c29aSKent Overstreet 				 struct bkey_buf *last_flushed)
1172a8c752bbSKent Overstreet {
11732642084fSKent Overstreet 	if (bp_k.k->type != KEY_TYPE_backpointer)
11742642084fSKent Overstreet 		return 0;
11752642084fSKent Overstreet 
11762642084fSKent Overstreet 	struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(bp_k);
117762a03559SKent Overstreet 	struct bbpos pos = bp_to_bbpos(*bp.v);
1178a8c752bbSKent Overstreet 
117923792a71SKent Overstreet 	if (bbpos_cmp(pos, start) < 0 ||
118023792a71SKent Overstreet 	    bbpos_cmp(pos, end) > 0)
118123792a71SKent Overstreet 		return 0;
118223792a71SKent Overstreet 
11839e92d6e9SKent Overstreet 	struct btree_iter iter;
1184056cae1cSKent Overstreet 	struct bkey_s_c k = bch2_backpointer_get_key(trans, bp, &iter, 0, last_flushed);
11859e92d6e9SKent Overstreet 	int ret = bkey_err(k);
1186a8c752bbSKent Overstreet 	if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node)
1187a8c752bbSKent Overstreet 		return 0;
1188a8c752bbSKent Overstreet 	if (ret)
1189a8c752bbSKent Overstreet 		return ret;
1190a8c752bbSKent Overstreet 
1191e07cb974SKent Overstreet 	bch2_trans_iter_exit(trans, &iter);
1192a8c752bbSKent Overstreet 	return ret;
1193a8c752bbSKent Overstreet }
1194a8c752bbSKent Overstreet 
check_bucket_backpointers_to_extents(struct btree_trans * trans,struct bch_dev * ca,struct bpos bucket)1195c738866eSKent Overstreet static int check_bucket_backpointers_to_extents(struct btree_trans *trans,
1196c738866eSKent Overstreet 						struct bch_dev *ca, struct bpos bucket)
1197c738866eSKent Overstreet {
1198c738866eSKent Overstreet 	u32 restart_count = trans->restart_count;
1199c738866eSKent Overstreet 	struct bkey_buf last_flushed;
1200c738866eSKent Overstreet 	bch2_bkey_buf_init(&last_flushed);
1201c738866eSKent Overstreet 	bkey_init(&last_flushed.k->k);
1202c738866eSKent Overstreet 
1203c738866eSKent Overstreet 	int ret = for_each_btree_key_max(trans, iter, BTREE_ID_backpointers,
1204c738866eSKent Overstreet 				      bucket_pos_to_bp_start(ca, bucket),
1205c738866eSKent Overstreet 				      bucket_pos_to_bp_end(ca, bucket),
1206c738866eSKent Overstreet 				      0, k,
1207c738866eSKent Overstreet 		check_one_backpointer(trans, BBPOS_MIN, BBPOS_MAX, k, &last_flushed)
1208c738866eSKent Overstreet 	);
1209c738866eSKent Overstreet 
1210c738866eSKent Overstreet 	bch2_bkey_buf_exit(&last_flushed, trans->c);
1211c738866eSKent Overstreet 	return ret ?: trans_was_restarted(trans, restart_count);
1212c738866eSKent Overstreet }
1213c738866eSKent Overstreet 
bch2_check_backpointers_to_extents_pass(struct btree_trans * trans,struct bbpos start,struct bbpos end)121423792a71SKent Overstreet static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
121523792a71SKent Overstreet 						   struct bbpos start,
121623792a71SKent Overstreet 						   struct bbpos end)
1217a8c752bbSKent Overstreet {
1218b99a94fdSKent Overstreet 	struct bch_fs *c = trans->c;
121992e1c29aSKent Overstreet 	struct bkey_buf last_flushed;
1220b99a94fdSKent Overstreet 	struct progress_indicator_state progress;
1221a8c752bbSKent Overstreet 
122292e1c29aSKent Overstreet 	bch2_bkey_buf_init(&last_flushed);
122392e1c29aSKent Overstreet 	bkey_init(&last_flushed.k->k);
1224baabeb49SKent Overstreet 	bch2_progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_backpointers));
122592e1c29aSKent Overstreet 
1226c2c2a4d6SKent Overstreet 	int ret = for_each_btree_key(trans, iter, BTREE_ID_backpointers,
1227c2c2a4d6SKent Overstreet 				     POS_MIN, BTREE_ITER_prefetch, k, ({
1228baabeb49SKent Overstreet 			bch2_progress_update_iter(trans, &progress, &iter, "backpointers_to_extents");
12292642084fSKent Overstreet 			check_one_backpointer(trans, start, end, k, &last_flushed);
1230b99a94fdSKent Overstreet 	}));
123192e1c29aSKent Overstreet 
1232b99a94fdSKent Overstreet 	bch2_bkey_buf_exit(&last_flushed, c);
123392e1c29aSKent Overstreet 	return ret;
1234a8c752bbSKent Overstreet }
123523792a71SKent Overstreet 
bch2_check_backpointers_to_extents(struct bch_fs * c)123623792a71SKent Overstreet int bch2_check_backpointers_to_extents(struct bch_fs *c)
123723792a71SKent Overstreet {
12386bd68ec2SKent Overstreet 	struct btree_trans *trans = bch2_trans_get(c);
123923792a71SKent Overstreet 	struct bbpos start = (struct bbpos) { .btree = 0, .pos = POS_MIN, }, end;
124023792a71SKent Overstreet 	int ret;
124123792a71SKent Overstreet 
124223792a71SKent Overstreet 	while (1) {
12436bd68ec2SKent Overstreet 		ret = bch2_get_btree_in_memory_pos(trans,
124452fd0f96SKent Overstreet 						   BIT_ULL(BTREE_ID_extents)|
124552fd0f96SKent Overstreet 						   BIT_ULL(BTREE_ID_reflink),
124623792a71SKent Overstreet 						   ~0,
124723792a71SKent Overstreet 						   start, &end);
124823792a71SKent Overstreet 		if (ret)
124923792a71SKent Overstreet 			break;
125023792a71SKent Overstreet 
125123792a71SKent Overstreet 		if (!bbpos_cmp(start, BBPOS_MIN) &&
125223792a71SKent Overstreet 		    bbpos_cmp(end, BBPOS_MAX))
125323792a71SKent Overstreet 			bch_verbose(c, "%s(): extents do not fit in ram, running in multiple passes with %zu nodes per pass",
125423792a71SKent Overstreet 				    __func__, btree_nodes_fit_in_ram(c));
125523792a71SKent Overstreet 
125623792a71SKent Overstreet 		if (bbpos_cmp(start, BBPOS_MIN) ||
125723792a71SKent Overstreet 		    bbpos_cmp(end, BBPOS_MAX)) {
125823792a71SKent Overstreet 			struct printbuf buf = PRINTBUF;
125923792a71SKent Overstreet 
126023792a71SKent Overstreet 			prt_str(&buf, "check_backpointers_to_extents(): ");
126123792a71SKent Overstreet 			bch2_bbpos_to_text(&buf, start);
126223792a71SKent Overstreet 			prt_str(&buf, "-");
126323792a71SKent Overstreet 			bch2_bbpos_to_text(&buf, end);
126423792a71SKent Overstreet 
126523792a71SKent Overstreet 			bch_verbose(c, "%s", buf.buf);
126623792a71SKent Overstreet 			printbuf_exit(&buf);
126723792a71SKent Overstreet 		}
126823792a71SKent Overstreet 
12696bd68ec2SKent Overstreet 		ret = bch2_check_backpointers_to_extents_pass(trans, start, end);
127023792a71SKent Overstreet 		if (ret || !bbpos_cmp(end, BBPOS_MAX))
127123792a71SKent Overstreet 			break;
127223792a71SKent Overstreet 
127323792a71SKent Overstreet 		start = bbpos_successor(end);
127423792a71SKent Overstreet 	}
12756bd68ec2SKent Overstreet 	bch2_trans_put(trans);
127623792a71SKent Overstreet 
12777a51608dSKent Overstreet 	bch2_btree_cache_unpin(c);
127891dcad18SKent Overstreet 
12791bb3c2a9SKent Overstreet 	bch_err_fn(c, ret);
128023792a71SKent Overstreet 	return ret;
128123792a71SKent Overstreet }
1282