Skip to content

Commit 9f9a534

Browse files
committed
Merge tag 'bcachefs-2024-09-28' of git://evilpiepirate.org/bcachefs
Pull more bcachefs updates from Kent Overstreet: "Assorted minor syzbot fixes, and for bigger stuff: Fix two disk accounting rewrite bugs: - Disk accounting keys use the version field of bkey so that journal replay can tell which updates have been applied to the btree. This is set in the transaction commit path, after we've gotten our journal reservation (and our time ordering), but the BCH_TRANS_COMMIT_skip_accounting_apply flag that journal replay uses was incorrectly skipping this for new updates generated prior to journal replay. This fixes the underlying cause of an assertion pop in disk_accounting_read. - A couple of fixes for disk accounting + device removal. Checking if acocunting replicas entries were marked in the superblock was being done at the wrong point, when deltas in the journal could still zero them out, and then additionally we'd try to add a missing replicas entry to the superblock without checking if it referred to an invalid (removed) device. A whole slew of repair fixes: - fix infinite loop in propagate_key_to_snapshot_leaves(), this fixes an infinite loop when repairing a filesystem with many snapshots - fix incorrect transaction restart handling leading to occasional "fsck counted ..." warnings - fix warning in __bch2_fsck_err() for bkey fsck errors - check_inode() in fsck now correctly checks if the filesystem was clean - there shouldn't be pending logged ops if the fs was clean, we now check for this - remove_backpointer() doesn't remove a dirent that doesn't actually point to the inode - many more fsck errors are AUTOFIX" * tag 'bcachefs-2024-09-28' of git://evilpiepirate.org/bcachefs: (35 commits) bcachefs: check_subvol_path() now prints subvol root inode bcachefs: remove_backpointer() now checks if dirent points to inode bcachefs: dirent_points_to_inode() now warns on mismatch bcachefs: Fix lost wake up bcachefs: Check for logged ops when clean bcachefs: BCH_FS_clean_recovery bcachefs: Convert disk accounting BUG_ON() to WARN_ON() bcachefs: Fix BCH_TRANS_COMMIT_skip_accounting_apply bcachefs: Check for accounting keys with bversion=0 bcachefs: rename version -> bversion bcachefs: Don't delete unlinked inodes before logged op resume bcachefs: Fix BCH_SB_ERRS() so we can reorder bcachefs: Fix fsck warnings from bkey validation bcachefs: Move transaction commit path validation to as late as possible bcachefs: Fix disk accounting attempting to mark invalid replicas entry bcachefs: Fix unlocked access to c->disk_sb.sb in bch2_replicas_entry_validate() bcachefs: Fix accounting read + device removal bcachefs: bch_accounting_mode bcachefs: fix transaction restart handling in check_extents(), check_dirents() bcachefs: kill inode_walker_entry.seen_this_pos ...
2 parents d37421e + 3a5895e commit 9f9a534

39 files changed

+469
-309
lines changed

fs/bcachefs/backpointers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ static int check_extent_checksum(struct btree_trans *trans,
501501
prt_printf(&buf, "\n %s ", bch2_btree_id_str(o_btree));
502502
bch2_bkey_val_to_text(&buf, c, extent2);
503503

504-
struct nonce nonce = extent_nonce(extent.k->version, p.crc);
504+
struct nonce nonce = extent_nonce(extent.k->bversion, p.crc);
505505
struct bch_csum csum = bch2_checksum(c, p.crc.csum_type, nonce, data_buf, bytes);
506506
if (fsck_err_on(bch2_crc_cmp(csum, p.crc.csum),
507507
trans, dup_backpointer_to_bad_csum_extent,

fs/bcachefs/bcachefs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ struct bch_dev {
594594
#define BCH_FS_FLAGS() \
595595
x(new_fs) \
596596
x(started) \
597+
x(clean_recovery) \
597598
x(btree_running) \
598599
x(accounting_replay_done) \
599600
x(may_go_rw) \
@@ -776,7 +777,7 @@ struct bch_fs {
776777
unsigned nsec_per_time_unit;
777778
u64 features;
778779
u64 compat;
779-
unsigned long errors_silent[BITS_TO_LONGS(BCH_SB_ERR_MAX)];
780+
unsigned long errors_silent[BITS_TO_LONGS(BCH_FSCK_ERR_MAX)];
780781
u64 btrees_lost_data;
781782
} sb;
782783

fs/bcachefs/bcachefs_format.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ struct bkey {
217217
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
218218
__u8 pad[1];
219219

220-
struct bversion version;
220+
struct bversion bversion;
221221
__u32 size; /* extent size, in sectors */
222222
struct bpos p;
223223
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -328,8 +328,8 @@ enum bch_bkey_fields {
328328
bkey_format_field(OFFSET, p.offset), \
329329
bkey_format_field(SNAPSHOT, p.snapshot), \
330330
bkey_format_field(SIZE, size), \
331-
bkey_format_field(VERSION_HI, version.hi), \
332-
bkey_format_field(VERSION_LO, version.lo), \
331+
bkey_format_field(VERSION_HI, bversion.hi), \
332+
bkey_format_field(VERSION_LO, bversion.lo), \
333333
}, \
334334
})
335335

fs/bcachefs/bkey.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,9 @@ static __always_inline int bversion_cmp(struct bversion l, struct bversion r)
214214
#define ZERO_VERSION ((struct bversion) { .hi = 0, .lo = 0 })
215215
#define MAX_VERSION ((struct bversion) { .hi = ~0, .lo = ~0ULL })
216216

217-
static __always_inline int bversion_zero(struct bversion v)
217+
static __always_inline bool bversion_zero(struct bversion v)
218218
{
219-
return !bversion_cmp(v, ZERO_VERSION);
219+
return bversion_cmp(v, ZERO_VERSION) == 0;
220220
}
221221

222222
#ifdef CONFIG_BCACHEFS_DEBUG
@@ -554,8 +554,8 @@ static inline void bch2_bkey_pack_test(void) {}
554554
x(BKEY_FIELD_OFFSET, p.offset) \
555555
x(BKEY_FIELD_SNAPSHOT, p.snapshot) \
556556
x(BKEY_FIELD_SIZE, size) \
557-
x(BKEY_FIELD_VERSION_HI, version.hi) \
558-
x(BKEY_FIELD_VERSION_LO, version.lo)
557+
x(BKEY_FIELD_VERSION_HI, bversion.hi) \
558+
x(BKEY_FIELD_VERSION_LO, bversion.lo)
559559

560560
struct bkey_format_state {
561561
u64 field_min[BKEY_NR_FIELDS];

fs/bcachefs/bkey_methods.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
289289

290290
bch2_bpos_to_text(out, k->p);
291291

292-
prt_printf(out, " len %u ver %llu", k->size, k->version.lo);
292+
prt_printf(out, " len %u ver %llu", k->size, k->bversion.lo);
293293
} else {
294294
prt_printf(out, "(null)");
295295
}

fs/bcachefs/bkey_methods.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ bool bch2_bkey_normalize(struct bch_fs *, struct bkey_s);
7070
static inline bool bch2_bkey_maybe_mergable(const struct bkey *l, const struct bkey *r)
7171
{
7272
return l->type == r->type &&
73-
!bversion_cmp(l->version, r->version) &&
73+
!bversion_cmp(l->bversion, r->bversion) &&
7474
bpos_eq(l->p, bkey_start_pos(r));
7575
}
7676

fs/bcachefs/btree_gc.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ int bch2_check_topology(struct bch_fs *c)
513513
struct bpos pulled_from_scan = POS_MIN;
514514
int ret = 0;
515515

516+
bch2_trans_srcu_unlock(trans);
517+
516518
for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) {
517519
struct btree_root *r = bch2_btree_id_root(c, i);
518520
bool reconstructed_root = false;
@@ -599,15 +601,15 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
599601

600602
if (initial) {
601603
BUG_ON(bch2_journal_seq_verify &&
602-
k.k->version.lo > atomic64_read(&c->journal.seq));
604+
k.k->bversion.lo > atomic64_read(&c->journal.seq));
603605

604606
if (fsck_err_on(btree_id != BTREE_ID_accounting &&
605-
k.k->version.lo > atomic64_read(&c->key_version),
607+
k.k->bversion.lo > atomic64_read(&c->key_version),
606608
trans, bkey_version_in_future,
607609
"key version number higher than recorded %llu\n %s",
608610
atomic64_read(&c->key_version),
609611
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
610-
atomic64_set(&c->key_version, k.k->version.lo);
612+
atomic64_set(&c->key_version, k.k->bversion.lo);
611613
}
612614

613615
if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, k),

fs/bcachefs/btree_io.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,10 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
11951195
set_btree_bset(b, b->set, &b->data->keys);
11961196

11971197
b->nr = bch2_key_sort_fix_overlapping(c, &sorted->keys, iter);
1198+
memset((uint8_t *)(sorted + 1) + b->nr.live_u64s * sizeof(u64), 0,
1199+
btree_buf_bytes(b) -
1200+
sizeof(struct btree_node) -
1201+
b->nr.live_u64s * sizeof(u64));
11981202

11991203
u64s = le16_to_cpu(sorted->keys.u64s);
12001204
*sorted = *b->data;
@@ -1219,7 +1223,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
12191223
ret = bch2_bkey_val_validate(c, u.s_c, READ);
12201224
if (ret == -BCH_ERR_fsck_delete_bkey ||
12211225
(bch2_inject_invalid_keys &&
1222-
!bversion_cmp(u.k->version, MAX_VERSION))) {
1226+
!bversion_cmp(u.k->bversion, MAX_VERSION))) {
12231227
btree_keys_account_key_drop(&b->nr, 0, k);
12241228

12251229
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);

fs/bcachefs/btree_node_scan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ static int read_btree_nodes(struct find_btree_nodes *f)
275275
w->ca = ca;
276276

277277
t = kthread_run(read_btree_nodes_worker, w, "read_btree_nodes/%s", ca->name);
278-
ret = IS_ERR_OR_NULL(t);
278+
ret = PTR_ERR_OR_ZERO(t);
279279
if (ret) {
280280
percpu_ref_put(&ca->io_ref);
281281
closure_put(&cl);

fs/bcachefs/btree_trans_commit.c

Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -684,10 +684,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
684684
!(flags & BCH_TRANS_COMMIT_no_journal_res)) {
685685
if (bch2_journal_seq_verify)
686686
trans_for_each_update(trans, i)
687-
i->k->k.version.lo = trans->journal_res.seq;
687+
i->k->k.bversion.lo = trans->journal_res.seq;
688688
else if (bch2_inject_invalid_keys)
689689
trans_for_each_update(trans, i)
690-
i->k->k.version = MAX_VERSION;
690+
i->k->k.bversion = MAX_VERSION;
691691
}
692692

693693
h = trans->hooks;
@@ -700,27 +700,31 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
700700

701701
struct jset_entry *entry = trans->journal_entries;
702702

703-
if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
704-
percpu_down_read(&c->mark_lock);
703+
percpu_down_read(&c->mark_lock);
704+
705+
for (entry = trans->journal_entries;
706+
entry != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
707+
entry = vstruct_next(entry))
708+
if (entry->type == BCH_JSET_ENTRY_write_buffer_keys &&
709+
entry->start->k.type == KEY_TYPE_accounting) {
710+
BUG_ON(!trans->journal_res.ref);
711+
712+
struct bkey_i_accounting *a = bkey_i_to_accounting(entry->start);
705713

706-
for (entry = trans->journal_entries;
707-
entry != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
708-
entry = vstruct_next(entry))
709-
if (jset_entry_is_key(entry) && entry->start->k.type == KEY_TYPE_accounting) {
710-
struct bkey_i_accounting *a = bkey_i_to_accounting(entry->start);
714+
a->k.bversion = journal_pos_to_bversion(&trans->journal_res,
715+
(u64 *) entry - (u64 *) trans->journal_entries);
716+
BUG_ON(bversion_zero(a->k.bversion));
711717

712-
a->k.version = journal_pos_to_bversion(&trans->journal_res,
713-
(u64 *) entry - (u64 *) trans->journal_entries);
714-
BUG_ON(bversion_zero(a->k.version));
715-
ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), false, false);
718+
if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
719+
ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal);
716720
if (ret)
717721
goto revert_fs_usage;
718722
}
719-
percpu_up_read(&c->mark_lock);
723+
}
724+
percpu_up_read(&c->mark_lock);
720725

721-
/* XXX: we only want to run this if deltas are nonzero */
722-
bch2_trans_account_disk_usage_change(trans);
723-
}
726+
/* XXX: we only want to run this if deltas are nonzero */
727+
bch2_trans_account_disk_usage_change(trans);
724728

725729
trans_for_each_update(trans, i)
726730
if (btree_node_type_has_atomic_triggers(i->bkey_type)) {
@@ -735,6 +739,40 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
735739
goto fatal_err;
736740
}
737741

742+
trans_for_each_update(trans, i) {
743+
enum bch_validate_flags invalid_flags = 0;
744+
745+
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
746+
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
747+
748+
ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k),
749+
i->bkey_type, invalid_flags);
750+
if (unlikely(ret)){
751+
bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
752+
trans->fn, (void *) i->ip_allocated);
753+
goto fatal_err;
754+
}
755+
btree_insert_entry_checks(trans, i);
756+
}
757+
758+
for (struct jset_entry *i = trans->journal_entries;
759+
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
760+
i = vstruct_next(i)) {
761+
enum bch_validate_flags invalid_flags = 0;
762+
763+
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
764+
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
765+
766+
ret = bch2_journal_entry_validate(c, NULL, i,
767+
bcachefs_metadata_version_current,
768+
CPU_BIG_ENDIAN, invalid_flags);
769+
if (unlikely(ret)) {
770+
bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n",
771+
trans->fn);
772+
goto fatal_err;
773+
}
774+
}
775+
738776
if (likely(!(flags & BCH_TRANS_COMMIT_no_journal_res))) {
739777
struct journal *j = &c->journal;
740778
struct jset_entry *entry;
@@ -798,7 +836,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
798836
struct bkey_s_accounting a = bkey_i_to_s_accounting(entry2->start);
799837

800838
bch2_accounting_neg(a);
801-
bch2_accounting_mem_mod_locked(trans, a.c, false, false);
839+
bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal);
802840
bch2_accounting_neg(a);
803841
}
804842
percpu_up_read(&c->mark_lock);
@@ -1019,40 +1057,6 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
10191057
if (ret)
10201058
goto out_reset;
10211059

1022-
trans_for_each_update(trans, i) {
1023-
enum bch_validate_flags invalid_flags = 0;
1024-
1025-
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
1026-
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
1027-
1028-
ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k),
1029-
i->bkey_type, invalid_flags);
1030-
if (unlikely(ret)){
1031-
bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
1032-
trans->fn, (void *) i->ip_allocated);
1033-
return ret;
1034-
}
1035-
btree_insert_entry_checks(trans, i);
1036-
}
1037-
1038-
for (struct jset_entry *i = trans->journal_entries;
1039-
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
1040-
i = vstruct_next(i)) {
1041-
enum bch_validate_flags invalid_flags = 0;
1042-
1043-
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
1044-
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
1045-
1046-
ret = bch2_journal_entry_validate(c, NULL, i,
1047-
bcachefs_metadata_version_current,
1048-
CPU_BIG_ENDIAN, invalid_flags);
1049-
if (unlikely(ret)) {
1050-
bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n",
1051-
trans->fn);
1052-
return ret;
1053-
}
1054-
}
1055-
10561060
if (unlikely(!test_bit(BCH_FS_may_go_rw, &c->flags))) {
10571061
ret = do_bch2_trans_commit_to_journal_replay(trans);
10581062
goto out_reset;

fs/bcachefs/btree_update.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ static inline struct bkey_i *__bch2_bkey_make_mut_noupdate(struct btree_trans *t
220220
if (type && k.k->type != type)
221221
return ERR_PTR(-ENOENT);
222222

223-
mut = bch2_trans_kmalloc_nomemzero(trans, bytes);
223+
/* extra padding for varint_decode_fast... */
224+
mut = bch2_trans_kmalloc_nomemzero(trans, bytes + 8);
224225
if (!IS_ERR(mut)) {
225226
bkey_reassemble(mut, k);
226227

fs/bcachefs/data_update.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ int bch2_data_update_init(struct btree_trans *trans,
639639

640640
bch2_write_op_init(&m->op, c, io_opts);
641641
m->op.pos = bkey_start_pos(k.k);
642-
m->op.version = k.k->version;
642+
m->op.version = k.k->bversion;
643643
m->op.target = data_opts.target;
644644
m->op.write_point = wp;
645645
m->op.nr_replicas = 0;

0 commit comments

Comments
 (0)