Skip to content

Commit ff0905b

Browse files
committed
Merge tag 'bcachefs-2025-06-04' of git://evilpiepirate.org/bcachefs
Pull more bcachefs updates from Kent Overstreet: "More bcachefs updates: - More stack usage improvements (~600 bytes) - Define CLASS()es for some commonly used types, and convert most rcu_read_lock() uses to the new lock guards - New introspection: - Superblock error counters are now available in sysfs: previously, they were only visible with 'show-super', which doesn't provide a live view - New tracepoint, error_throw(), which is called any time we return an error and start to unwind - Repair - check_fix_ptrs() can now repair btree node roots - We can now repair when we've somehow ended up with the journal using a superblock bucket - Revert some leftovers from the aborted directory i_size feature, and add repair code: some userspace programs (e.g. sshfs) were getting confused It seems in 6.15 there's a bug where i_nlink on the vfs inode has been getting incorrectly set to 0, with some unfortunate results; list_journal analysis showed bch2_inode_rm() being called (by bch2_evict_inode()) when it clearly should not have been. - bch2_inode_rm() now runs "should we be deleting this inode?" checks that were previously only run when deleting unlinked inodes in recovery - check_subvol() was treating a dangling subvol (pointing to a missing root inode) like a dangling dirent, and deleting it. This was the really unfortunate one: check_subvol() will now recreate the root inode if necessary This took longer to debug than it should have, and we lost several filesystems unnecessarily, because users have been ignoring the release notes and blindly running 'fsck -y'. Debugging required reconstructing what happened through analyzing the journal, when ideally someone would have noticed 'hey, fsck is asking me if I want to repair this: it usually doesn't, maybe I should run this in dry run mode and check what's going on?' As a reminder, fsck errors are being marked as autofix once we've verified, in real world usage, that they're working correctly; blindly running 'fsck -y' on an experimental filesystem is playing with fire Up to this incident we've had an excellent track record of not losing data, so let's try to learn from this one This is a community effort, I wouldn't be able to get this done without the help of all the people QAing and providing excellent bug reports and feedback based on real world usage. But please don't ignore advice and expect me to pick up the pieces If an error isn't marked as autofix, and it /is/ happening in the wild, that's also something I need to know about so we can check it out and add it to the autofix list if repair looks good. I haven't been getting those reports, and I should be; since we don't have any sort of telemetry yet I am absolutely dependent on user reports Now I'll be spending the weekend working on new repair code to see if I can get a filesystem back for a user who didn't have backups" * tag 'bcachefs-2025-06-04' of git://evilpiepirate.org/bcachefs: (69 commits) bcachefs: add cond_resched() to handle_overwrites() bcachefs: Make journal read log message a bit quieter bcachefs: Fix subvol to missing root repair bcachefs: Run may_delete_deleted_inode() checks in bch2_inode_rm() bcachefs: delete dead code from may_delete_deleted_inode() bcachefs: Add flags to subvolume_to_text() bcachefs: Fix oops in btree_node_seq_matches() bcachefs: Fix dirent_casefold_mismatch repair bcachefs: Fix bch2_fsck_rename_dirent() for casefold bcachefs: Redo bch2_dirent_init_name() bcachefs: Fix -Wc23-extensions in bch2_check_dirents() bcachefs: Run check_dirents second time if required bcachefs: Run snapshot deletion out of system_long_wq bcachefs: Make check_key_has_snapshot safer bcachefs: BCH_RECOVERY_PASS_NO_RATELIMIT bcachefs: bch2_require_recovery_pass() bcachefs: bch_err_throw() bcachefs: Repair code for directory i_size bcachefs: Kill un-reverted directory i_size code bcachefs: Delete redundant fsck_err() ...
2 parents 16b7069 + 3d11125 commit ff0905b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+2323
-1757
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "error.h"
2222
#include "lru.h"
2323
#include "recovery.h"
24-
#include "trace.h"
2524
#include "varint.h"
2625

2726
#include <linux/kthread.h>
@@ -337,11 +336,10 @@ void bch2_alloc_v4_swab(struct bkey_s k)
337336
a->stripe_sectors = swab32(a->stripe_sectors);
338337
}
339338

340-
void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
339+
static inline void __bch2_alloc_v4_to_text(struct printbuf *out, struct bch_fs *c,
340+
unsigned dev, const struct bch_alloc_v4 *a)
341341
{
342-
struct bch_alloc_v4 _a;
343-
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a);
344-
struct bch_dev *ca = c ? bch2_dev_bucket_tryget_noerror(c, k.k->p) : NULL;
342+
struct bch_dev *ca = c ? bch2_dev_tryget_noerror(c, dev) : NULL;
345343

346344
prt_newline(out);
347345
printbuf_indent_add(out, 2);
@@ -369,6 +367,19 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
369367
bch2_dev_put(ca);
370368
}
371369

370+
void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
371+
{
372+
struct bch_alloc_v4 _a;
373+
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a);
374+
375+
__bch2_alloc_v4_to_text(out, c, k.k->p.inode, a);
376+
}
377+
378+
void bch2_alloc_v4_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
379+
{
380+
__bch2_alloc_v4_to_text(out, c, k.k->p.inode, bkey_s_c_to_alloc_v4(k).v);
381+
}
382+
372383
void __bch2_alloc_to_v4(struct bkey_s_c k, struct bch_alloc_v4 *out)
373384
{
374385
if (k.k->type == KEY_TYPE_alloc_v4) {
@@ -697,8 +708,8 @@ static int __need_discard_or_freespace_err(struct btree_trans *trans,
697708
set ? "" : "un",
698709
bch2_btree_id_str(btree),
699710
buf.buf);
700-
if (ret == -BCH_ERR_fsck_ignore ||
701-
ret == -BCH_ERR_fsck_errors_not_fixed)
711+
if (bch2_err_matches(ret, BCH_ERR_fsck_ignore) ||
712+
bch2_err_matches(ret, BCH_ERR_fsck_errors_not_fixed))
702713
ret = 0;
703714

704715
printbuf_exit(&buf);
@@ -854,7 +865,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
854865

855866
struct bch_dev *ca = bch2_dev_bucket_tryget(c, new.k->p);
856867
if (!ca)
857-
return -BCH_ERR_trigger_alloc;
868+
return bch_err_throw(c, trigger_alloc);
858869

859870
struct bch_alloc_v4 old_a_convert;
860871
const struct bch_alloc_v4 *old_a = bch2_alloc_to_v4(old, &old_a_convert);
@@ -988,14 +999,11 @@ int bch2_trigger_alloc(struct btree_trans *trans,
988999
}
9891000

9901001
if (new_a->gen != old_a->gen) {
991-
rcu_read_lock();
1002+
guard(rcu)();
9921003
u8 *gen = bucket_gen(ca, new.k->p.offset);
993-
if (unlikely(!gen)) {
994-
rcu_read_unlock();
1004+
if (unlikely(!gen))
9951005
goto invalid_bucket;
996-
}
9971006
*gen = new_a->gen;
998-
rcu_read_unlock();
9991007
}
10001008

10011009
#define eval_state(_a, expr) ({ const struct bch_alloc_v4 *a = _a; expr; })
@@ -1021,15 +1029,12 @@ int bch2_trigger_alloc(struct btree_trans *trans,
10211029
}
10221030

10231031
if ((flags & BTREE_TRIGGER_gc) && (flags & BTREE_TRIGGER_insert)) {
1024-
rcu_read_lock();
1032+
guard(rcu)();
10251033
struct bucket *g = gc_bucket(ca, new.k->p.offset);
1026-
if (unlikely(!g)) {
1027-
rcu_read_unlock();
1034+
if (unlikely(!g))
10281035
goto invalid_bucket;
1029-
}
10301036
g->gen_valid = 1;
10311037
g->gen = new_a->gen;
1032-
rcu_read_unlock();
10331038
}
10341039
err:
10351040
fsck_err:
@@ -1039,7 +1044,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
10391044
invalid_bucket:
10401045
bch2_fs_inconsistent(c, "reference to invalid bucket\n%s",
10411046
(bch2_bkey_val_to_text(&buf, c, new.s_c), buf.buf));
1042-
ret = -BCH_ERR_trigger_alloc;
1047+
ret = bch_err_throw(c, trigger_alloc);
10431048
goto err;
10441049
}
10451050

@@ -1105,13 +1110,12 @@ static bool next_bucket(struct bch_fs *c, struct bch_dev **ca, struct bpos *buck
11051110
bucket->offset = 0;
11061111
}
11071112

1108-
rcu_read_lock();
1113+
guard(rcu)();
11091114
*ca = __bch2_next_dev_idx(c, bucket->inode, NULL);
11101115
if (*ca) {
11111116
*bucket = POS((*ca)->dev_idx, (*ca)->mi.first_bucket);
11121117
bch2_dev_get(*ca);
11131118
}
1114-
rcu_read_unlock();
11151119

11161120
return *ca != NULL;
11171121
}
@@ -1454,7 +1458,7 @@ int bch2_check_discard_freespace_key(struct btree_trans *trans, struct btree_ite
14541458
ret = bch2_btree_bit_mod_iter(trans, iter, false) ?:
14551459
bch2_trans_commit(trans, NULL, NULL,
14561460
BCH_TRANS_COMMIT_no_enospc) ?:
1457-
-BCH_ERR_transaction_restart_commit;
1461+
bch_err_throw(c, transaction_restart_commit);
14581462
goto out;
14591463
} else {
14601464
/*
@@ -1777,14 +1781,16 @@ int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
17771781

17781782
static int discard_in_flight_add(struct bch_dev *ca, u64 bucket, bool in_progress)
17791783
{
1784+
struct bch_fs *c = ca->fs;
17801785
int ret;
17811786

17821787
mutex_lock(&ca->discard_buckets_in_flight_lock);
1783-
darray_for_each(ca->discard_buckets_in_flight, i)
1784-
if (i->bucket == bucket) {
1785-
ret = -BCH_ERR_EEXIST_discard_in_flight_add;
1786-
goto out;
1787-
}
1788+
struct discard_in_flight *i =
1789+
darray_find_p(ca->discard_buckets_in_flight, i, i->bucket == bucket);
1790+
if (i) {
1791+
ret = bch_err_throw(c, EEXIST_discard_in_flight_add);
1792+
goto out;
1793+
}
17881794

17891795
ret = darray_push(&ca->discard_buckets_in_flight, ((struct discard_in_flight) {
17901796
.in_progress = in_progress,
@@ -1798,14 +1804,11 @@ static int discard_in_flight_add(struct bch_dev *ca, u64 bucket, bool in_progres
17981804
static void discard_in_flight_remove(struct bch_dev *ca, u64 bucket)
17991805
{
18001806
mutex_lock(&ca->discard_buckets_in_flight_lock);
1801-
darray_for_each(ca->discard_buckets_in_flight, i)
1802-
if (i->bucket == bucket) {
1803-
BUG_ON(!i->in_progress);
1804-
darray_remove_item(&ca->discard_buckets_in_flight, i);
1805-
goto found;
1806-
}
1807-
BUG();
1808-
found:
1807+
struct discard_in_flight *i =
1808+
darray_find_p(ca->discard_buckets_in_flight, i, i->bucket == bucket);
1809+
BUG_ON(!i || !i->in_progress);
1810+
1811+
darray_remove_item(&ca->discard_buckets_in_flight, i);
18091812
mutex_unlock(&ca->discard_buckets_in_flight_lock);
18101813
}
18111814

@@ -2504,7 +2507,7 @@ void bch2_recalc_capacity(struct bch_fs *c)
25042507

25052508
lockdep_assert_held(&c->state_lock);
25062509

2507-
rcu_read_lock();
2510+
guard(rcu)();
25082511
for_each_member_device_rcu(c, ca, NULL) {
25092512
struct block_device *bdev = READ_ONCE(ca->disk_sb.bdev);
25102513
if (bdev)
@@ -2549,7 +2552,6 @@ void bch2_recalc_capacity(struct bch_fs *c)
25492552
bucket_size_max = max_t(unsigned, bucket_size_max,
25502553
ca->mi.bucket_size);
25512554
}
2552-
rcu_read_unlock();
25532555

25542556
bch2_set_ra_pages(c, ra_pages);
25552557

@@ -2574,10 +2576,9 @@ u64 bch2_min_rw_member_capacity(struct bch_fs *c)
25742576
{
25752577
u64 ret = U64_MAX;
25762578

2577-
rcu_read_lock();
2579+
guard(rcu)();
25782580
for_each_rw_member_rcu(c, ca)
25792581
ret = min(ret, ca->mi.nbuckets * ca->mi.bucket_size);
2580-
rcu_read_unlock();
25812582
return ret;
25822583
}
25832584

fs/bcachefs/alloc_background.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@
1313

1414
static inline bool bch2_dev_bucket_exists(struct bch_fs *c, struct bpos pos)
1515
{
16-
rcu_read_lock();
16+
guard(rcu)();
1717
struct bch_dev *ca = bch2_dev_rcu_noerror(c, pos.inode);
18-
bool ret = ca && bucket_valid(ca, pos.offset);
19-
rcu_read_unlock();
20-
return ret;
18+
return ca && bucket_valid(ca, pos.offset);
2119
}
2220

2321
static inline u64 bucket_to_u64(struct bpos bucket)
@@ -253,6 +251,7 @@ int bch2_alloc_v4_validate(struct bch_fs *, struct bkey_s_c,
253251
struct bkey_validate_context);
254252
void bch2_alloc_v4_swab(struct bkey_s);
255253
void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
254+
void bch2_alloc_v4_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
256255

257256
#define bch2_bkey_ops_alloc ((struct bkey_ops) { \
258257
.key_validate = bch2_alloc_v1_validate, \
@@ -277,7 +276,7 @@ void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
277276

278277
#define bch2_bkey_ops_alloc_v4 ((struct bkey_ops) { \
279278
.key_validate = bch2_alloc_v4_validate, \
280-
.val_to_text = bch2_alloc_to_text, \
279+
.val_to_text = bch2_alloc_v4_to_text, \
281280
.swab = bch2_alloc_v4_swab, \
282281
.trigger = bch2_trigger_alloc, \
283282
.min_val_size = 48, \

0 commit comments

Comments
 (0)