Skip to content

Commit 4abcd80

Browse files
committed
Merge tag 'bcachefs-2024-11-13' of git://evilpiepirate.org/bcachefs
Pull bcachefs fixes from Kent Overstreet: "This fixes one minor regression from the btree cache fixes (in the scan_for_btree_nodes repair path) - and the shutdown path fix is the big one here, in terms of bugs closed: - Assorted tiny syzbot fixes - Shutdown path fix: "bch2_btree_write_buffer_flush_going_ro()" The shutdown path wasn't flushing the btree write buffer, leading to shutting down while we still had operations in flight. This fixes a whole slew of syzbot bugs, and undoubtedly other strange heisenbugs. * tag 'bcachefs-2024-11-13' of git://evilpiepirate.org/bcachefs: bcachefs: Fix assertion pop in bch2_ptr_swab() bcachefs: Fix journal_entry_dev_usage_to_text() overrun bcachefs: Allow for unknown key types in backpointers fsck bcachefs: Fix assertion pop in topology repair bcachefs: Fix hidden btree errors when reading roots bcachefs: Fix validate_bset() repair path bcachefs: Fix missing validation for bch_backpointer.level bcachefs: Fix bch_member.btree_bitmap_shift validation bcachefs: bch2_btree_write_buffer_flush_going_ro()
2 parents 0a9b9d1 + 840c2fb commit 4abcd80

14 files changed

+72
-19
lines changed

fs/bcachefs/backpointers.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
5252
enum bch_validate_flags flags)
5353
{
5454
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
55+
int ret = 0;
56+
57+
bkey_fsck_err_on(bp.v->level > BTREE_MAX_DEPTH,
58+
c, backpointer_level_bad,
59+
"backpointer level bad: %u >= %u",
60+
bp.v->level, BTREE_MAX_DEPTH);
5561

5662
rcu_read_lock();
5763
struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp.k->p.inode);
@@ -64,7 +70,6 @@ int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
6470
struct bpos bucket = bp_pos_to_bucket(ca, bp.k->p);
6571
struct bpos bp_pos = bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset);
6672
rcu_read_unlock();
67-
int ret = 0;
6873

6974
bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
7075
!bpos_eq(bp.k->p, bp_pos),
@@ -947,9 +952,13 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
947952
static int check_one_backpointer(struct btree_trans *trans,
948953
struct bbpos start,
949954
struct bbpos end,
950-
struct bkey_s_c_backpointer bp,
955+
struct bkey_s_c bp_k,
951956
struct bkey_buf *last_flushed)
952957
{
958+
if (bp_k.k->type != KEY_TYPE_backpointer)
959+
return 0;
960+
961+
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(bp_k);
953962
struct bch_fs *c = trans->c;
954963
struct btree_iter iter;
955964
struct bbpos pos = bp_to_bbpos(*bp.v);
@@ -1004,9 +1013,7 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
10041013
POS_MIN, BTREE_ITER_prefetch, k,
10051014
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
10061015
progress_update_iter(trans, &progress, &iter, "backpointers_to_extents");
1007-
check_one_backpointer(trans, start, end,
1008-
bkey_s_c_to_backpointer(k),
1009-
&last_flushed);
1016+
check_one_backpointer(trans, start, end, k, &last_flushed);
10101017
}));
10111018

10121019
bch2_bkey_buf_exit(&last_flushed, c);

fs/bcachefs/btree_gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static int set_node_max(struct bch_fs *c, struct btree *b, struct bpos new_max)
182182
bch2_btree_node_drop_keys_outside_node(b);
183183

184184
mutex_lock(&c->btree_cache.lock);
185-
bch2_btree_node_hash_remove(&c->btree_cache, b);
185+
__bch2_btree_node_hash_remove(&c->btree_cache, b);
186186

187187
bkey_copy(&b->key, &new->k_i);
188188
ret = __bch2_btree_node_hash_insert(&c->btree_cache, b);

fs/bcachefs/btree_io.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,8 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
733733
c, ca, b, i, NULL,
734734
bset_past_end_of_btree_node,
735735
"bset past end of btree node (offset %u len %u but written %zu)",
736-
offset, sectors, ptr_written ?: btree_sectors(c))) {
736+
offset, sectors, ptr_written ?: btree_sectors(c)))
737737
i->u64s = 0;
738-
ret = 0;
739-
goto out;
740-
}
741738

742739
btree_err_on(offset && !i->u64s,
743740
-BCH_ERR_btree_node_read_err_fixable,
@@ -829,7 +826,6 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
829826
BSET_BIG_ENDIAN(i), write,
830827
&bn->format);
831828
}
832-
out:
833829
fsck_err:
834830
printbuf_exit(&buf2);
835831
printbuf_exit(&buf1);

fs/bcachefs/btree_update_interior.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2398,7 +2398,8 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
23982398
if (new_hash) {
23992399
mutex_lock(&c->btree_cache.lock);
24002400
bch2_btree_node_hash_remove(&c->btree_cache, new_hash);
2401-
bch2_btree_node_hash_remove(&c->btree_cache, b);
2401+
2402+
__bch2_btree_node_hash_remove(&c->btree_cache, b);
24022403

24032404
bkey_copy(&b->key, new_key);
24042405
ret = __bch2_btree_node_hash_insert(&c->btree_cache, b);

fs/bcachefs/btree_write_buffer.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
277277
bool accounting_replay_done = test_bit(BCH_FS_accounting_replay_done, &c->flags);
278278
int ret = 0;
279279

280+
ret = bch2_journal_error(&c->journal);
281+
if (ret)
282+
return ret;
283+
280284
bch2_trans_unlock(trans);
281285
bch2_trans_begin(trans);
282286

@@ -491,7 +495,8 @@ static int fetch_wb_keys_from_journal(struct bch_fs *c, u64 seq)
491495
return ret;
492496
}
493497

494-
static int btree_write_buffer_flush_seq(struct btree_trans *trans, u64 seq)
498+
static int btree_write_buffer_flush_seq(struct btree_trans *trans, u64 seq,
499+
bool *did_work)
495500
{
496501
struct bch_fs *c = trans->c;
497502
struct btree_write_buffer *wb = &c->btree_write_buffer;
@@ -502,6 +507,8 @@ static int btree_write_buffer_flush_seq(struct btree_trans *trans, u64 seq)
502507

503508
fetch_from_journal_err = fetch_wb_keys_from_journal(c, seq);
504509

510+
*did_work |= wb->inc.keys.nr || wb->flushing.keys.nr;
511+
505512
/*
506513
* On memory allocation failure, bch2_btree_write_buffer_flush_locked()
507514
* is not guaranteed to empty wb->inc:
@@ -521,17 +528,34 @@ static int bch2_btree_write_buffer_journal_flush(struct journal *j,
521528
struct journal_entry_pin *_pin, u64 seq)
522529
{
523530
struct bch_fs *c = container_of(j, struct bch_fs, journal);
531+
bool did_work = false;
524532

525-
return bch2_trans_run(c, btree_write_buffer_flush_seq(trans, seq));
533+
return bch2_trans_run(c, btree_write_buffer_flush_seq(trans, seq, &did_work));
526534
}
527535

528536
int bch2_btree_write_buffer_flush_sync(struct btree_trans *trans)
529537
{
530538
struct bch_fs *c = trans->c;
539+
bool did_work = false;
531540

532541
trace_and_count(c, write_buffer_flush_sync, trans, _RET_IP_);
533542

534-
return btree_write_buffer_flush_seq(trans, journal_cur_seq(&c->journal));
543+
return btree_write_buffer_flush_seq(trans, journal_cur_seq(&c->journal), &did_work);
544+
}
545+
546+
/*
547+
* The write buffer requires flushing when going RO: keys in the journal for the
548+
* write buffer don't have a journal pin yet
549+
*/
550+
bool bch2_btree_write_buffer_flush_going_ro(struct bch_fs *c)
551+
{
552+
if (bch2_journal_error(&c->journal))
553+
return false;
554+
555+
bool did_work = false;
556+
bch2_trans_run(c, btree_write_buffer_flush_seq(trans,
557+
journal_cur_seq(&c->journal), &did_work));
558+
return did_work;
535559
}
536560

537561
int bch2_btree_write_buffer_flush_nocheck_rw(struct btree_trans *trans)

fs/bcachefs/btree_write_buffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static inline bool bch2_btree_write_buffer_must_wait(struct bch_fs *c)
2121

2222
struct btree_trans;
2323
int bch2_btree_write_buffer_flush_sync(struct btree_trans *);
24+
bool bch2_btree_write_buffer_flush_going_ro(struct bch_fs *);
2425
int bch2_btree_write_buffer_flush_nocheck_rw(struct btree_trans *);
2526
int bch2_btree_write_buffer_tryflush(struct btree_trans *);
2627

fs/bcachefs/extents.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,7 @@ void bch2_ptr_swab(struct bkey_s k)
13641364
for (entry = ptrs.start;
13651365
entry < ptrs.end;
13661366
entry = extent_entry_next(entry)) {
1367-
switch (extent_entry_type(entry)) {
1367+
switch (__extent_entry_type(entry)) {
13681368
case BCH_EXTENT_ENTRY_ptr:
13691369
break;
13701370
case BCH_EXTENT_ENTRY_crc32:
@@ -1384,6 +1384,9 @@ void bch2_ptr_swab(struct bkey_s k)
13841384
break;
13851385
case BCH_EXTENT_ENTRY_rebalance:
13861386
break;
1387+
default:
1388+
/* Bad entry type: will be caught by validate() */
1389+
return;
13871390
}
13881391
}
13891392
}

fs/bcachefs/journal_io.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,9 @@ static void journal_entry_dev_usage_to_text(struct printbuf *out, struct bch_fs
708708
container_of(entry, struct jset_entry_dev_usage, entry);
709709
unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
710710

711+
if (vstruct_bytes(entry) < sizeof(*u))
712+
return;
713+
711714
prt_printf(out, "dev=%u", le32_to_cpu(u->dev));
712715

713716
printbuf_indent_add(out, 2);

fs/bcachefs/recovery_passes.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ const char * const bch2_recovery_passes[] = {
2727
NULL
2828
};
2929

30+
/* Fake recovery pass, so that scan_for_btree_nodes isn't 0: */
31+
static int bch2_recovery_pass_empty(struct bch_fs *c)
32+
{
33+
return 0;
34+
}
35+
3036
static int bch2_set_may_go_rw(struct bch_fs *c)
3137
{
3238
struct journal_keys *keys = &c->journal_keys;

fs/bcachefs/recovery_passes_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* must never change:
1414
*/
1515
#define BCH_RECOVERY_PASSES() \
16+
x(recovery_pass_empty, 41, PASS_SILENT) \
1617
x(scan_for_btree_nodes, 37, 0) \
1718
x(check_topology, 4, 0) \
1819
x(accounting_read, 39, PASS_ALWAYS) \

0 commit comments

Comments
 (0)