Skip to content

Commit f6963ab

Browse files
committed
Merge tag 'bcachefs-2024-07-10' of https://evilpiepirate.org/git/bcachefs
Pull bcachefs fixes from Kent Overstreet: - Switch some asserts to WARN() - Fix a few "transaction not locked" asserts in the data read retry paths and backpointers gc - Fix a race that would cause the journal to get stuck on a flush commit - Add missing fsck checks for the fragmentation LRU - The usual assorted ssorted syzbot fixes * tag 'bcachefs-2024-07-10' of https://evilpiepirate.org/git/bcachefs: (22 commits) bcachefs: Add missing bch2_trans_begin() bcachefs: Fix missing error check in journal_entry_btree_keys_validate() bcachefs: Warn on attempting a move with no replicas bcachefs: bch2_data_update_to_text() bcachefs: Log mount failure error code bcachefs: Fix undefined behaviour in eytzinger1_first() bcachefs: Mark bch_inode_info as SLAB_ACCOUNT bcachefs: Fix bch2_inode_insert() race path for tmpfiles closures: fix closure_sync + closure debugging bcachefs: Fix journal getting stuck on a flush commit bcachefs: io clock: run timer fns under clock lock bcachefs: Repair fragmentation_lru in alloc_write_key() bcachefs: add check for missing fragmentation in check_alloc_to_lru_ref() bcachefs: bch2_btree_write_buffer_maybe_flush() bcachefs: Add missing printbuf_tabstops_reset() calls bcachefs: Fix loop restart in bch2_btree_transactions_read() bcachefs: Fix bch2_read_retry_nodecode() bcachefs: Don't use the new_fs() bucket alloc path on an initialized fs bcachefs: Fix shift greater than integer size bcachefs: Change bch2_fs_journal_stop() BUG_ON() to warning ...
2 parents a19ea42 + 7d7f71c commit f6963ab

25 files changed

+266
-142
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "alloc_background.h"
44
#include "alloc_foreground.h"
55
#include "backpointers.h"
6+
#include "bkey_buf.h"
67
#include "btree_cache.h"
78
#include "btree_io.h"
89
#include "btree_key_cache.h"
@@ -1553,13 +1554,13 @@ int bch2_check_alloc_info(struct bch_fs *c)
15531554
}
15541555

15551556
static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
1556-
struct btree_iter *alloc_iter)
1557+
struct btree_iter *alloc_iter,
1558+
struct bkey_buf *last_flushed)
15571559
{
15581560
struct bch_fs *c = trans->c;
1559-
struct btree_iter lru_iter;
15601561
struct bch_alloc_v4 a_convert;
15611562
const struct bch_alloc_v4 *a;
1562-
struct bkey_s_c alloc_k, lru_k;
1563+
struct bkey_s_c alloc_k;
15631564
struct printbuf buf = PRINTBUF;
15641565
int ret;
15651566

@@ -1573,6 +1574,14 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
15731574

15741575
a = bch2_alloc_to_v4(alloc_k, &a_convert);
15751576

1577+
if (a->fragmentation_lru) {
1578+
ret = bch2_lru_check_set(trans, BCH_LRU_FRAGMENTATION_START,
1579+
a->fragmentation_lru,
1580+
alloc_k, last_flushed);
1581+
if (ret)
1582+
return ret;
1583+
}
1584+
15761585
if (a->data_type != BCH_DATA_cached)
15771586
return 0;
15781587

@@ -1597,41 +1606,30 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
15971606
a = &a_mut->v;
15981607
}
15991608

1600-
lru_k = bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
1601-
lru_pos(alloc_k.k->p.inode,
1602-
bucket_to_u64(alloc_k.k->p),
1603-
a->io_time[READ]), 0);
1604-
ret = bkey_err(lru_k);
1609+
ret = bch2_lru_check_set(trans, alloc_k.k->p.inode, a->io_time[READ],
1610+
alloc_k, last_flushed);
16051611
if (ret)
1606-
return ret;
1607-
1608-
if (fsck_err_on(lru_k.k->type != KEY_TYPE_set, c,
1609-
alloc_key_to_missing_lru_entry,
1610-
"missing lru entry\n"
1611-
" %s",
1612-
(printbuf_reset(&buf),
1613-
bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
1614-
ret = bch2_lru_set(trans,
1615-
alloc_k.k->p.inode,
1616-
bucket_to_u64(alloc_k.k->p),
1617-
a->io_time[READ]);
1618-
if (ret)
1619-
goto err;
1620-
}
1612+
goto err;
16211613
err:
16221614
fsck_err:
1623-
bch2_trans_iter_exit(trans, &lru_iter);
16241615
printbuf_exit(&buf);
16251616
return ret;
16261617
}
16271618

16281619
int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
16291620
{
1621+
struct bkey_buf last_flushed;
1622+
1623+
bch2_bkey_buf_init(&last_flushed);
1624+
bkey_init(&last_flushed.k->k);
1625+
16301626
int ret = bch2_trans_run(c,
16311627
for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
16321628
POS_MIN, BTREE_ITER_prefetch, k,
16331629
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
1634-
bch2_check_alloc_to_lru_ref(trans, &iter)));
1630+
bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed)));
1631+
1632+
bch2_bkey_buf_exit(&last_flushed, c);
16351633
bch_err_fn(c, ret);
16361634
return ret;
16371635
}

fs/bcachefs/alloc_foreground.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,7 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
17031703
for (unsigned i = 0; i < ARRAY_SIZE(c->open_buckets); i++)
17041704
nr[c->open_buckets[i].data_type]++;
17051705

1706+
printbuf_tabstops_reset(out);
17061707
printbuf_tabstop_push(out, 24);
17071708

17081709
percpu_down_read(&c->mark_lock);
@@ -1736,6 +1737,7 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca)
17361737
for (unsigned i = 0; i < ARRAY_SIZE(c->open_buckets); i++)
17371738
nr[c->open_buckets[i].data_type]++;
17381739

1740+
printbuf_tabstops_reset(out);
17391741
printbuf_tabstop_push(out, 12);
17401742
printbuf_tabstop_push(out, 16);
17411743
printbuf_tabstop_push(out, 16);

fs/bcachefs/backpointers.c

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -434,13 +434,6 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
434434
return ret;
435435
}
436436

437-
static inline bool bkey_and_val_eq(struct bkey_s_c l, struct bkey_s_c r)
438-
{
439-
return bpos_eq(l.k->p, r.k->p) &&
440-
bkey_bytes(l.k) == bkey_bytes(r.k) &&
441-
!memcmp(l.v, r.v, bkey_val_bytes(l.k));
442-
}
443-
444437
struct extents_to_bp_state {
445438
struct bpos bucket_start;
446439
struct bpos bucket_end;
@@ -536,11 +529,8 @@ static int check_bp_exists(struct btree_trans *trans,
536529
struct btree_iter other_extent_iter = {};
537530
struct printbuf buf = PRINTBUF;
538531
struct bkey_s_c bp_k;
539-
struct bkey_buf tmp;
540532
int ret = 0;
541533

542-
bch2_bkey_buf_init(&tmp);
543-
544534
struct bch_dev *ca = bch2_dev_bucket_tryget(c, bucket);
545535
if (!ca) {
546536
prt_str(&buf, "extent for nonexistent device:bucket ");
@@ -565,22 +555,9 @@ static int check_bp_exists(struct btree_trans *trans,
565555

566556
if (bp_k.k->type != KEY_TYPE_backpointer ||
567557
memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) {
568-
bch2_bkey_buf_reassemble(&tmp, c, orig_k);
569-
570-
if (!bkey_and_val_eq(orig_k, bkey_i_to_s_c(s->last_flushed.k))) {
571-
if (bp.level) {
572-
bch2_trans_unlock(trans);
573-
bch2_btree_interior_updates_flush(c);
574-
}
575-
576-
ret = bch2_btree_write_buffer_flush_sync(trans);
577-
if (ret)
578-
goto err;
579-
580-
bch2_bkey_buf_copy(&s->last_flushed, c, tmp.k);
581-
ret = -BCH_ERR_transaction_restart_write_buffer_flush;
582-
goto out;
583-
}
558+
ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed);
559+
if (ret)
560+
goto err;
584561

585562
goto check_existing_bp;
586563
}
@@ -589,7 +566,6 @@ static int check_bp_exists(struct btree_trans *trans,
589566
fsck_err:
590567
bch2_trans_iter_exit(trans, &other_extent_iter);
591568
bch2_trans_iter_exit(trans, &bp_iter);
592-
bch2_bkey_buf_exit(&tmp, c);
593569
bch2_dev_put(ca);
594570
printbuf_exit(&buf);
595571
return ret;
@@ -794,6 +770,8 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
794770
!((1U << btree) & btree_interior_mask))
795771
continue;
796772

773+
bch2_trans_begin(trans);
774+
797775
__for_each_btree_node(trans, iter, btree,
798776
btree == start.btree ? start.pos : POS_MIN,
799777
0, depth, BTREE_ITER_prefetch, b, ret) {
@@ -905,7 +883,7 @@ static int check_one_backpointer(struct btree_trans *trans,
905883
struct bbpos start,
906884
struct bbpos end,
907885
struct bkey_s_c_backpointer bp,
908-
struct bpos *last_flushed_pos)
886+
struct bkey_buf *last_flushed)
909887
{
910888
struct bch_fs *c = trans->c;
911889
struct btree_iter iter;
@@ -925,20 +903,18 @@ static int check_one_backpointer(struct btree_trans *trans,
925903
if (ret)
926904
return ret;
927905

928-
if (!k.k && !bpos_eq(*last_flushed_pos, bp.k->p)) {
929-
*last_flushed_pos = bp.k->p;
930-
ret = bch2_btree_write_buffer_flush_sync(trans) ?:
931-
-BCH_ERR_transaction_restart_write_buffer_flush;
932-
goto out;
933-
}
906+
if (!k.k) {
907+
ret = bch2_btree_write_buffer_maybe_flush(trans, bp.s_c, last_flushed);
908+
if (ret)
909+
goto out;
934910

935-
if (fsck_err_on(!k.k, c,
936-
backpointer_to_missing_ptr,
937-
"backpointer for missing %s\n %s",
938-
bp.v->level ? "btree node" : "extent",
939-
(bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
940-
ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
941-
goto out;
911+
if (fsck_err(c, backpointer_to_missing_ptr,
912+
"backpointer for missing %s\n %s",
913+
bp.v->level ? "btree node" : "extent",
914+
(bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
915+
ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
916+
goto out;
917+
}
942918
}
943919
out:
944920
fsck_err:
@@ -951,14 +927,20 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
951927
struct bbpos start,
952928
struct bbpos end)
953929
{
954-
struct bpos last_flushed_pos = SPOS_MAX;
930+
struct bkey_buf last_flushed;
955931

956-
return for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
932+
bch2_bkey_buf_init(&last_flushed);
933+
bkey_init(&last_flushed.k->k);
934+
935+
int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
957936
POS_MIN, BTREE_ITER_prefetch, k,
958937
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
959938
check_one_backpointer(trans, start, end,
960939
bkey_s_c_to_backpointer(k),
961-
&last_flushed_pos));
940+
&last_flushed));
941+
942+
bch2_bkey_buf_exit(&last_flushed, trans->c);
943+
return ret;
962944
}
963945

964946
int bch2_check_backpointers_to_extents(struct bch_fs *c)

fs/bcachefs/bkey.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,9 @@ int bch2_bkey_format_invalid(struct bch_fs *c,
660660
bch2_bkey_format_field_overflows(f, i)) {
661661
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
662662
u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
663-
u64 packed_max = f->bits_per_field[i]
664-
? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
663+
unsigned packed_bits = min(64, f->bits_per_field[i]);
664+
u64 packed_max = packed_bits
665+
? ~((~0ULL << 1) << (packed_bits - 1))
665666
: 0;
666667

667668
prt_printf(err, "field %u too large: %llu + %llu > %llu",

fs/bcachefs/bkey.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ static inline struct bpos bkey_max(struct bpos l, struct bpos r)
194194
return bkey_gt(l, r) ? l : r;
195195
}
196196

197+
static inline bool bkey_and_val_eq(struct bkey_s_c l, struct bkey_s_c r)
198+
{
199+
return bpos_eq(l.k->p, r.k->p) &&
200+
bkey_bytes(l.k) == bkey_bytes(r.k) &&
201+
!memcmp(l.v, r.v, bkey_val_bytes(l.k));
202+
}
203+
197204
void bch2_bpos_swab(struct bpos *);
198205
void bch2_bkey_swab_key(const struct bkey_format *, struct bkey_packed *);
199206

fs/bcachefs/btree_gc.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,8 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
903903
bch2_dev_usage_update(c, ca, &old_gc, &gc, 0, true);
904904
percpu_up_read(&c->mark_lock);
905905

906+
gc.fragmentation_lru = alloc_lru_idx_fragmentation(gc, ca);
907+
906908
if (fsck_err_on(new.data_type != gc.data_type, c,
907909
alloc_key_data_type_wrong,
908910
"bucket %llu:%llu gen %u has wrong data_type"
@@ -916,23 +918,19 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
916918
#define copy_bucket_field(_errtype, _f) \
917919
if (fsck_err_on(new._f != gc._f, c, _errtype, \
918920
"bucket %llu:%llu gen %u data type %s has wrong " #_f \
919-
": got %u, should be %u", \
921+
": got %llu, should be %llu", \
920922
iter->pos.inode, iter->pos.offset, \
921923
gc.gen, \
922924
bch2_data_type_str(gc.data_type), \
923-
new._f, gc._f)) \
925+
(u64) new._f, (u64) gc._f)) \
924926
new._f = gc._f; \
925927

926-
copy_bucket_field(alloc_key_gen_wrong,
927-
gen);
928-
copy_bucket_field(alloc_key_dirty_sectors_wrong,
929-
dirty_sectors);
930-
copy_bucket_field(alloc_key_cached_sectors_wrong,
931-
cached_sectors);
932-
copy_bucket_field(alloc_key_stripe_wrong,
933-
stripe);
934-
copy_bucket_field(alloc_key_stripe_redundancy_wrong,
935-
stripe_redundancy);
928+
copy_bucket_field(alloc_key_gen_wrong, gen);
929+
copy_bucket_field(alloc_key_dirty_sectors_wrong, dirty_sectors);
930+
copy_bucket_field(alloc_key_cached_sectors_wrong, cached_sectors);
931+
copy_bucket_field(alloc_key_stripe_wrong, stripe);
932+
copy_bucket_field(alloc_key_stripe_redundancy_wrong, stripe_redundancy);
933+
copy_bucket_field(alloc_key_fragmentation_lru_wrong, fragmentation_lru);
936934
#undef copy_bucket_field
937935

938936
if (!bch2_alloc_v4_cmp(*old, new))
@@ -946,7 +944,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
946944
a->v = new;
947945

948946
/*
949-
* The trigger normally makes sure this is set, but we're not running
947+
* The trigger normally makes sure these are set, but we're not running
950948
* triggers:
951949
*/
952950
if (a->v.data_type == BCH_DATA_cached && !a->v.io_time[READ])

fs/bcachefs/btree_write_buffer.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
#include "bcachefs.h"
4+
#include "bkey_buf.h"
45
#include "btree_locking.h"
56
#include "btree_update.h"
67
#include "btree_update_interior.h"
78
#include "btree_write_buffer.h"
89
#include "error.h"
10+
#include "extents.h"
911
#include "journal.h"
1012
#include "journal_io.h"
1113
#include "journal_reclaim.h"
@@ -492,6 +494,41 @@ int bch2_btree_write_buffer_tryflush(struct btree_trans *trans)
492494
return ret;
493495
}
494496

497+
/**
498+
* In check and repair code, when checking references to write buffer btrees we
499+
* need to issue a flush before we have a definitive error: this issues a flush
500+
* if this is a key we haven't yet checked.
501+
*/
502+
int bch2_btree_write_buffer_maybe_flush(struct btree_trans *trans,
503+
struct bkey_s_c referring_k,
504+
struct bkey_buf *last_flushed)
505+
{
506+
struct bch_fs *c = trans->c;
507+
struct bkey_buf tmp;
508+
int ret = 0;
509+
510+
bch2_bkey_buf_init(&tmp);
511+
512+
if (!bkey_and_val_eq(referring_k, bkey_i_to_s_c(last_flushed->k))) {
513+
bch2_bkey_buf_reassemble(&tmp, c, referring_k);
514+
515+
if (bkey_is_btree_ptr(referring_k.k)) {
516+
bch2_trans_unlock(trans);
517+
bch2_btree_interior_updates_flush(c);
518+
}
519+
520+
ret = bch2_btree_write_buffer_flush_sync(trans);
521+
if (ret)
522+
goto err;
523+
524+
bch2_bkey_buf_copy(last_flushed, c, tmp.k);
525+
ret = -BCH_ERR_transaction_restart_write_buffer_flush;
526+
}
527+
err:
528+
bch2_bkey_buf_exit(&tmp, c);
529+
return ret;
530+
}
531+
495532
static void bch2_btree_write_buffer_flush_work(struct work_struct *work)
496533
{
497534
struct bch_fs *c = container_of(work, struct bch_fs, btree_write_buffer.flush_work);

fs/bcachefs/btree_write_buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ int bch2_btree_write_buffer_flush_sync(struct btree_trans *);
2323
int bch2_btree_write_buffer_flush_nocheck_rw(struct btree_trans *);
2424
int bch2_btree_write_buffer_tryflush(struct btree_trans *);
2525

26+
struct bkey_buf;
27+
int bch2_btree_write_buffer_maybe_flush(struct btree_trans *, struct bkey_s_c, struct bkey_buf *);
28+
2629
struct journal_keys_to_wb {
2730
struct btree_write_buffer_keys *wb;
2831
size_t room;

0 commit comments

Comments
 (0)