Skip to content

Commit 633cf06

Browse files
author
Kent Overstreet
committed
bcachefs: Kill bch2_dev_bkey_exists() in backpointer code
Signed-off-by: Kent Overstreet <[email protected]>
1 parent 1f2f92e commit 633cf06

File tree

6 files changed

+102
-52
lines changed

6 files changed

+102
-52
lines changed

fs/bcachefs/alloc_foreground.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
342342
struct bch_backpointer bp;
343343
struct bpos bp_pos = POS_MIN;
344344

345-
ret = bch2_get_next_backpointer(trans, POS(ca->dev_idx, b), -1,
345+
ret = bch2_get_next_backpointer(trans, ca, POS(ca->dev_idx, b), -1,
346346
&bp_pos, &bp,
347347
BTREE_ITER_nopreserve);
348348
if (ret) {

fs/bcachefs/backpointers.c

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,26 @@ static bool extent_matches_bp(struct bch_fs *c,
2323
const union bch_extent_entry *entry;
2424
struct extent_ptr_decoded p;
2525

26+
rcu_read_lock();
2627
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
2728
struct bpos bucket2;
2829
struct bch_backpointer bp2;
2930

3031
if (p.ptr.cached)
3132
continue;
3233

33-
struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
34+
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
35+
if (!ca)
36+
continue;
3437

3538
bch2_extent_ptr_to_bp(c, ca, btree_id, level, k, p, entry, &bucket2, &bp2);
3639
if (bpos_eq(bucket, bucket2) &&
37-
!memcmp(&bp, &bp2, sizeof(bp)))
40+
!memcmp(&bp, &bp2, sizeof(bp))) {
41+
rcu_read_unlock();
3842
return true;
43+
}
3944
}
45+
rcu_read_unlock();
4046

4147
return false;
4248
}
@@ -47,16 +53,21 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
4753
{
4854
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
4955

50-
/* these will be caught by fsck */
51-
if (!bch2_dev_exists(c, bp.k->p.inode))
56+
rcu_read_lock();
57+
struct bch_dev *ca = bch2_dev_rcu(c, bp.k->p.inode);
58+
if (!ca) {
59+
/* these will be caught by fsck */
60+
rcu_read_unlock();
5261
return 0;
62+
}
5363

54-
struct bch_dev *ca = bch2_dev_bkey_exists(c, bp.k->p.inode);
55-
struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
64+
struct bpos bucket = bp_pos_to_bucket(ca, bp.k->p);
65+
struct bpos bp_pos = bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset);
66+
rcu_read_unlock();
5667
int ret = 0;
5768

5869
bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
59-
!bpos_eq(bp.k->p, bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset)),
70+
!bpos_eq(bp.k->p, bp_pos),
6071
c, err,
6172
backpointer_bucket_offset_wrong,
6273
"backpointer bucket_offset wrong");
@@ -77,10 +88,16 @@ void bch2_backpointer_to_text(struct printbuf *out, const struct bch_backpointer
7788

7889
void bch2_backpointer_k_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
7990
{
80-
if (bch2_dev_exists(c, k.k->p.inode)) {
91+
rcu_read_lock();
92+
struct bch_dev *ca = bch2_dev_rcu(c, k.k->p.inode);
93+
if (ca) {
94+
struct bpos bucket = bp_pos_to_bucket(ca, k.k->p);
95+
rcu_read_unlock();
8196
prt_str(out, "bucket=");
82-
bch2_bpos_to_text(out, bp_pos_to_bucket(c, k.k->p));
97+
bch2_bpos_to_text(out, bucket);
8398
prt_str(out, " ");
99+
} else {
100+
rcu_read_unlock();
84101
}
85102

86103
bch2_backpointer_to_text(out, bkey_s_c_to_backpointer(k).v);
@@ -146,6 +163,7 @@ static noinline int backpointer_mod_err(struct btree_trans *trans,
146163
}
147164

148165
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
166+
struct bch_dev *ca,
149167
struct bpos bucket,
150168
struct bch_backpointer bp,
151169
struct bkey_s_c orig_k,
@@ -162,7 +180,7 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
162180
return ret;
163181

164182
bkey_backpointer_init(&bp_k->k_i);
165-
bp_k->k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
183+
bp_k->k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
166184
bp_k->v = bp;
167185

168186
if (!insert) {
@@ -198,13 +216,13 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
198216
* Find the next backpointer >= *bp_offset:
199217
*/
200218
int bch2_get_next_backpointer(struct btree_trans *trans,
219+
struct bch_dev *ca,
201220
struct bpos bucket, int gen,
202221
struct bpos *bp_pos,
203222
struct bch_backpointer *bp,
204223
unsigned iter_flags)
205224
{
206-
struct bch_fs *c = trans->c;
207-
struct bpos bp_end_pos = bucket_pos_to_bp(c, bpos_nosnap_successor(bucket), 0);
225+
struct bpos bp_end_pos = bucket_pos_to_bp(ca, bpos_nosnap_successor(bucket), 0);
208226
struct btree_iter alloc_iter = { NULL }, bp_iter = { NULL };
209227
struct bkey_s_c k;
210228
int ret = 0;
@@ -224,7 +242,7 @@ int bch2_get_next_backpointer(struct btree_trans *trans,
224242
goto done;
225243
}
226244

227-
*bp_pos = bpos_max(*bp_pos, bucket_pos_to_bp(c, bucket, 0));
245+
*bp_pos = bpos_max(*bp_pos, bucket_pos_to_bp(ca, bucket, 0));
228246

229247
for_each_btree_key_norestart(trans, bp_iter, BTREE_ID_backpointers,
230248
*bp_pos, iter_flags, k, ret) {
@@ -250,7 +268,6 @@ static void backpointer_not_found(struct btree_trans *trans,
250268
{
251269
struct bch_fs *c = trans->c;
252270
struct printbuf buf = PRINTBUF;
253-
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
254271

255272
/*
256273
* If we're using the btree write buffer, the backpointer we were
@@ -260,6 +277,10 @@ static void backpointer_not_found(struct btree_trans *trans,
260277
if (likely(!bch2_backpointers_no_use_write_buffer))
261278
return;
262279

280+
struct bpos bucket;
281+
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
282+
return;
283+
263284
prt_printf(&buf, "backpointer doesn't match %s it points to:\n ",
264285
bp.level ? "btree node" : "extent");
265286
prt_printf(&buf, "bucket: ");
@@ -289,15 +310,17 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
289310
{
290311
if (likely(!bp.level)) {
291312
struct bch_fs *c = trans->c;
292-
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
293-
struct bkey_s_c k;
313+
314+
struct bpos bucket;
315+
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
316+
return bkey_s_c_err(-EIO);
294317

295318
bch2_trans_node_iter_init(trans, iter,
296319
bp.btree_id,
297320
bp.pos,
298321
0, 0,
299322
iter_flags);
300-
k = bch2_btree_iter_peek_slot(iter);
323+
struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
301324
if (bkey_err(k)) {
302325
bch2_trans_iter_exit(trans, iter);
303326
return k;
@@ -326,18 +349,20 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
326349
struct bch_backpointer bp)
327350
{
328351
struct bch_fs *c = trans->c;
329-
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
330-
struct btree *b;
331352

332353
BUG_ON(!bp.level);
333354

355+
struct bpos bucket;
356+
if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket))
357+
return ERR_PTR(-EIO);
358+
334359
bch2_trans_node_iter_init(trans, iter,
335360
bp.btree_id,
336361
bp.pos,
337362
0,
338363
bp.level - 1,
339364
0);
340-
b = bch2_btree_iter_peek_node(iter);
365+
struct btree *b = bch2_btree_iter_peek_node(iter);
341366
if (IS_ERR_OR_NULL(b))
342367
goto err;
343368

@@ -368,16 +393,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
368393
struct printbuf buf = PRINTBUF;
369394
int ret = 0;
370395

371-
if (fsck_err_on(!bch2_dev_exists(c, k.k->p.inode), c,
372-
backpointer_to_missing_device,
373-
"backpointer for missing device:\n%s",
374-
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
375-
ret = bch2_btree_delete_at(trans, bp_iter, 0);
396+
struct bpos bucket;
397+
if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
398+
if (fsck_err(c, backpointer_to_missing_device,
399+
"backpointer for missing device:\n%s",
400+
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
401+
ret = bch2_btree_delete_at(trans, bp_iter, 0);
376402
goto out;
377403
}
378404

379-
alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc,
380-
bp_pos_to_bucket(c, k.k->p), 0);
405+
alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc, bucket, 0);
381406
ret = bkey_err(alloc_k);
382407
if (ret)
383408
goto out;
@@ -512,25 +537,27 @@ static int check_bp_exists(struct btree_trans *trans,
512537
struct printbuf buf = PRINTBUF;
513538
struct bkey_s_c bp_k;
514539
struct bkey_buf tmp;
515-
int ret;
540+
int ret = 0;
516541

517542
bch2_bkey_buf_init(&tmp);
518543

519-
if (!bch2_dev_bucket_exists(c, bucket)) {
544+
struct bch_dev *ca = bch2_dev_bucket_tryget(c, bucket);
545+
if (!ca) {
520546
prt_str(&buf, "extent for nonexistent device:bucket ");
521547
bch2_bpos_to_text(&buf, bucket);
522548
prt_str(&buf, "\n ");
523549
bch2_bkey_val_to_text(&buf, c, orig_k);
524550
bch_err(c, "%s", buf.buf);
525-
return -BCH_ERR_fsck_repair_unimplemented;
551+
ret = -BCH_ERR_fsck_repair_unimplemented;
552+
goto err;
526553
}
527554

528555
if (bpos_lt(bucket, s->bucket_start) ||
529556
bpos_gt(bucket, s->bucket_end))
530-
return 0;
557+
goto out;
531558

532559
bp_k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
533-
bucket_pos_to_bp(c, bucket, bp.bucket_offset),
560+
bucket_pos_to_bp(ca, bucket, bp.bucket_offset),
534561
0);
535562
ret = bkey_err(bp_k);
536563
if (ret)
@@ -563,6 +590,7 @@ static int check_bp_exists(struct btree_trans *trans,
563590
bch2_trans_iter_exit(trans, &other_extent_iter);
564591
bch2_trans_iter_exit(trans, &bp_iter);
565592
bch2_bkey_buf_exit(&tmp, c);
593+
bch2_dev_put(ca);
566594
printbuf_exit(&buf);
567595
return ret;
568596
check_existing_bp:
@@ -638,13 +666,13 @@ static int check_bp_exists(struct btree_trans *trans,
638666

639667
struct bkey_i_backpointer n_bp_k;
640668
bkey_backpointer_init(&n_bp_k.k_i);
641-
n_bp_k.k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
669+
n_bp_k.k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
642670
n_bp_k.v = bp;
643671
prt_printf(&buf, "\n want: ");
644672
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&n_bp_k.k_i));
645673

646674
if (fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
647-
ret = bch2_bucket_backpointer_mod(trans, bucket, bp, orig_k, true);
675+
ret = bch2_bucket_backpointer_mod(trans, ca, bucket, bp, orig_k, true);
648676

649677
goto out;
650678
}
@@ -668,8 +696,14 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
668696
if (p.ptr.cached)
669697
continue;
670698

671-
struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
672-
bch2_extent_ptr_to_bp(c, ca, btree, level, k, p, entry, &bucket_pos, &bp);
699+
rcu_read_lock();
700+
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
701+
if (ca)
702+
bch2_extent_ptr_to_bp(c, ca, btree, level, k, p, entry, &bucket_pos, &bp);
703+
rcu_read_unlock();
704+
705+
if (!ca)
706+
continue;
673707

674708
ret = check_bp_exists(trans, s, bucket_pos, bp, k);
675709
if (ret)

fs/bcachefs/backpointers.h

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "btree_iter.h"
77
#include "btree_update.h"
88
#include "buckets.h"
9+
#include "error.h"
910
#include "super.h"
1011

1112
static inline u64 swab40(u64 x)
@@ -36,15 +37,29 @@ void bch2_backpointer_swab(struct bkey_s);
3637
* Convert from pos in backpointer btree to pos of corresponding bucket in alloc
3738
* btree:
3839
*/
39-
static inline struct bpos bp_pos_to_bucket(const struct bch_fs *c,
40-
struct bpos bp_pos)
40+
static inline struct bpos bp_pos_to_bucket(const struct bch_dev *ca, struct bpos bp_pos)
4141
{
42-
struct bch_dev *ca = bch2_dev_bkey_exists(c, bp_pos.inode);
4342
u64 bucket_sector = bp_pos.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT;
4443

4544
return POS(bp_pos.inode, sector_to_bucket(ca, bucket_sector));
4645
}
4746

47+
static inline bool bp_pos_to_bucket_nodev_noerror(struct bch_fs *c, struct bpos bp_pos, struct bpos *bucket)
48+
{
49+
rcu_read_lock();
50+
struct bch_dev *ca = bch2_dev_rcu(c, bp_pos.inode);
51+
if (ca)
52+
*bucket = bp_pos_to_bucket(ca, bp_pos);
53+
rcu_read_unlock();
54+
return ca != NULL;
55+
}
56+
57+
static inline bool bp_pos_to_bucket_nodev(struct bch_fs *c, struct bpos bp_pos, struct bpos *bucket)
58+
{
59+
return !bch2_fs_inconsistent_on(!bp_pos_to_bucket_nodev_noerror(c, bp_pos, bucket),
60+
c, "backpointer for missing device %llu", bp_pos.inode);
61+
}
62+
4863
static inline struct bpos bucket_pos_to_bp_noerror(const struct bch_dev *ca,
4964
struct bpos bucket,
5065
u64 bucket_offset)
@@ -57,32 +72,32 @@ static inline struct bpos bucket_pos_to_bp_noerror(const struct bch_dev *ca,
5772
/*
5873
* Convert from pos in alloc btree + bucket offset to pos in backpointer btree:
5974
*/
60-
static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
75+
static inline struct bpos bucket_pos_to_bp(const struct bch_dev *ca,
6176
struct bpos bucket,
6277
u64 bucket_offset)
6378
{
64-
struct bch_dev *ca = bch2_dev_bkey_exists(c, bucket.inode);
6579
struct bpos ret = bucket_pos_to_bp_noerror(ca, bucket, bucket_offset);
66-
EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));
80+
EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(ca, ret)));
6781
return ret;
6882
}
6983

70-
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *, struct bpos bucket,
71-
struct bch_backpointer, struct bkey_s_c, bool);
84+
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *, struct bch_dev *,
85+
struct bpos bucket, struct bch_backpointer, struct bkey_s_c, bool);
7286

7387
static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
88+
struct bch_dev *ca,
7489
struct bpos bucket,
7590
struct bch_backpointer bp,
7691
struct bkey_s_c orig_k,
7792
bool insert)
7893
{
7994
if (unlikely(bch2_backpointers_no_use_write_buffer))
80-
return bch2_bucket_backpointer_mod_nowritebuffer(trans, bucket, bp, orig_k, insert);
95+
return bch2_bucket_backpointer_mod_nowritebuffer(trans, ca, bucket, bp, orig_k, insert);
8196

8297
struct bkey_i_backpointer bp_k;
8398

8499
bkey_backpointer_init(&bp_k.k_i);
85-
bp_k.k.p = bucket_pos_to_bp(trans->c, bucket, bp.bucket_offset);
100+
bp_k.k.p = bucket_pos_to_bp(ca, bucket, bp.bucket_offset);
86101
bp_k.v = bp;
87102

88103
if (!insert) {
@@ -142,7 +157,7 @@ static inline void bch2_extent_ptr_to_bp(struct bch_fs *c, struct bch_dev *ca,
142157
};
143158
}
144159

145-
int bch2_get_next_backpointer(struct btree_trans *, struct bpos, int,
160+
int bch2_get_next_backpointer(struct btree_trans *, struct bch_dev *ca, struct bpos, int,
146161
struct bpos *, struct bch_backpointer *, unsigned);
147162
struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *, struct btree_iter *,
148163
struct bpos, struct bch_backpointer,

fs/bcachefs/buckets.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
988988
goto err;
989989

990990
if (!p.ptr.cached) {
991-
ret = bch2_bucket_backpointer_mod(trans, bucket, bp, k, insert);
991+
ret = bch2_bucket_backpointer_mod(trans, ca, bucket, bp, k, insert);
992992
if (ret)
993993
goto err;
994994
}

0 commit comments

Comments
 (0)