Skip to content

Commit bf0e5ed

Browse files
committed
Merge tag 'bcachefs-2025-02-20' of git://evilpiepirate.org/bcachefs
Pull bcachefs fixes from Kent Overstreet: "Small stuff: - The fsck code for Hongbo's directory i_size patch was wrong, caught by transaction restart injection: we now have the CI running another test variant with restart injection enabled - Another fixup for reflink pointers to missing indirect extents: previous fix was for fsck code, this fixes the normal runtime paths - Another small srcu lock hold time fix, reported by jpsollie" * tag 'bcachefs-2025-02-20' of git://evilpiepirate.org/bcachefs: bcachefs: Fix srcu lock warning in btree_update_nodes_written() bcachefs: Fix bch2_indirect_extent_missing_error() bcachefs: Fix fsck directory i_size checking
2 parents 770b7ee + b04974f commit bf0e5ed

File tree

4 files changed

+42
-58
lines changed

4 files changed

+42
-58
lines changed

fs/bcachefs/btree_update_interior.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,9 +681,11 @@ static void btree_update_nodes_written(struct btree_update *as)
681681

682682
b = as->old_nodes[i];
683683

684+
bch2_trans_begin(trans);
684685
btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
685686
seq = b->data ? b->data->keys.seq : 0;
686687
six_unlock_read(&b->c.lock);
688+
bch2_trans_unlock_long(trans);
687689

688690
if (seq == as->old_nodes_seq[i])
689691
wait_on_bit_io(&b->flags, BTREE_NODE_write_in_flight_inner,

fs/bcachefs/fsck.c

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,7 @@ struct inode_walker_entry {
823823
struct bch_inode_unpacked inode;
824824
u32 snapshot;
825825
u64 count;
826+
u64 i_size;
826827
};
827828

828829
struct inode_walker {
@@ -910,8 +911,9 @@ lookup_inode_for_snapshot(struct bch_fs *c, struct inode_walker *w, struct bkey_
910911
if (k.k->p.snapshot != i->snapshot && !is_whiteout) {
911912
struct inode_walker_entry new = *i;
912913

913-
new.snapshot = k.k->p.snapshot;
914-
new.count = 0;
914+
new.snapshot = k.k->p.snapshot;
915+
new.count = 0;
916+
new.i_size = 0;
915917

916918
struct printbuf buf = PRINTBUF;
917919
bch2_bkey_val_to_text(&buf, c, k);
@@ -1116,37 +1118,6 @@ static int get_snapshot_root_inode(struct btree_trans *trans,
11161118
return ret;
11171119
}
11181120

1119-
static int check_directory_size(struct btree_trans *trans,
1120-
struct bch_inode_unpacked *inode_u,
1121-
struct bkey_s_c inode_k, bool *write_inode)
1122-
{
1123-
struct btree_iter iter;
1124-
struct bkey_s_c k;
1125-
u64 new_size = 0;
1126-
int ret;
1127-
1128-
for_each_btree_key_max_norestart(trans, iter, BTREE_ID_dirents,
1129-
SPOS(inode_k.k->p.offset, 0, inode_k.k->p.snapshot),
1130-
POS(inode_k.k->p.offset, U64_MAX),
1131-
0, k, ret) {
1132-
if (k.k->type != KEY_TYPE_dirent)
1133-
continue;
1134-
1135-
struct bkey_s_c_dirent dirent = bkey_s_c_to_dirent(k);
1136-
struct qstr name = bch2_dirent_get_name(dirent);
1137-
1138-
new_size += dirent_occupied_size(&name);
1139-
}
1140-
bch2_trans_iter_exit(trans, &iter);
1141-
1142-
if (!ret && inode_u->bi_size != new_size) {
1143-
inode_u->bi_size = new_size;
1144-
*write_inode = true;
1145-
}
1146-
1147-
return ret;
1148-
}
1149-
11501121
static int check_inode(struct btree_trans *trans,
11511122
struct btree_iter *iter,
11521123
struct bkey_s_c k,
@@ -1335,16 +1306,6 @@ static int check_inode(struct btree_trans *trans,
13351306
u.bi_journal_seq = journal_cur_seq(&c->journal);
13361307
do_update = true;
13371308
}
1338-
1339-
if (S_ISDIR(u.bi_mode)) {
1340-
ret = check_directory_size(trans, &u, k, &do_update);
1341-
1342-
fsck_err_on(ret,
1343-
trans, directory_size_mismatch,
1344-
"directory inode %llu:%u with the mismatch directory size",
1345-
u.bi_inum, k.k->p.snapshot);
1346-
ret = 0;
1347-
}
13481309
do_update:
13491310
if (do_update) {
13501311
ret = __bch2_fsck_write_inode(trans, &u);
@@ -2017,10 +1978,31 @@ static int check_subdir_count_notnested(struct btree_trans *trans, struct inode_
20171978
return ret;
20181979
}
20191980

2020-
static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
1981+
static int check_dir_i_size_notnested(struct btree_trans *trans, struct inode_walker *w)
1982+
{
1983+
struct bch_fs *c = trans->c;
1984+
int ret = 0;
1985+
1986+
darray_for_each(w->inodes, i)
1987+
if (fsck_err_on(i->inode.bi_size != i->i_size,
1988+
trans, inode_dir_wrong_nlink,
1989+
"directory %llu:%u with wrong i_size: got %llu, should be %llu",
1990+
w->last_pos.inode, i->snapshot, i->inode.bi_size, i->i_size)) {
1991+
i->inode.bi_size = i->i_size;
1992+
ret = bch2_fsck_write_inode(trans, &i->inode);
1993+
if (ret)
1994+
break;
1995+
}
1996+
fsck_err:
1997+
bch_err_fn(c, ret);
1998+
return ret;
1999+
}
2000+
2001+
static int check_subdir_dirents_count(struct btree_trans *trans, struct inode_walker *w)
20212002
{
20222003
u32 restart_count = trans->restart_count;
20232004
return check_subdir_count_notnested(trans, w) ?:
2005+
check_dir_i_size_notnested(trans, w) ?:
20242006
trans_was_restarted(trans, restart_count);
20252007
}
20262008

@@ -2367,7 +2349,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
23672349
goto out;
23682350

23692351
if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) {
2370-
ret = check_subdir_count(trans, dir);
2352+
ret = check_subdir_dirents_count(trans, dir);
23712353
if (ret)
23722354
goto err;
23732355
}
@@ -2457,9 +2439,11 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
24572439
if (ret)
24582440
goto err;
24592441

2460-
if (d.v->d_type == DT_DIR)
2461-
for_each_visible_inode(c, s, dir, d.k->p.snapshot, i)
2442+
for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) {
2443+
if (d.v->d_type == DT_DIR)
24622444
i->count++;
2445+
i->i_size += bkey_bytes(d.k);
2446+
}
24632447
out:
24642448
err:
24652449
fsck_err:

fs/bcachefs/reflink.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static int bch2_indirect_extent_missing_error(struct btree_trans *trans,
172172
bool should_commit)
173173
{
174174
if (REFLINK_P_ERROR(p.v))
175-
return -BCH_ERR_missing_indirect_extent;
175+
return 0;
176176

177177
struct bch_fs *c = trans->c;
178178
u64 live_start = REFLINK_P_IDX(p.v);
@@ -259,23 +259,23 @@ struct bkey_s_c bch2_lookup_indirect_extent(struct btree_trans *trans,
259259
return k;
260260

261261
if (unlikely(!bkey_extent_is_reflink_data(k.k))) {
262-
bch2_trans_iter_exit(trans, iter);
263-
264262
unsigned size = min((u64) k.k->size,
265263
REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad) -
266264
reflink_offset);
267265
bch2_key_resize(&iter->k, size);
268266

269267
int ret = bch2_indirect_extent_missing_error(trans, p, reflink_offset,
270268
k.k->p.offset, should_commit);
271-
if (ret)
269+
if (ret) {
270+
bch2_trans_iter_exit(trans, iter);
272271
return bkey_s_c_err(ret);
272+
}
273273
} else if (unlikely(REFLINK_P_ERROR(p.v))) {
274-
bch2_trans_iter_exit(trans, iter);
275-
276274
int ret = bch2_indirect_extent_not_missing(trans, p, should_commit);
277-
if (ret)
275+
if (ret) {
276+
bch2_trans_iter_exit(trans, iter);
278277
return bkey_s_c_err(ret);
278+
}
279279
}
280280

281281
*offset_into_extent = reflink_offset - bkey_start_offset(k.k);
@@ -300,7 +300,7 @@ static int trans_trigger_reflink_p_segment(struct btree_trans *trans,
300300
if (ret)
301301
return ret;
302302

303-
if (bkey_deleted(k.k)) {
303+
if (!bkey_refcount_c(k)) {
304304
if (!(flags & BTREE_TRIGGER_overwrite))
305305
ret = -BCH_ERR_missing_indirect_extent;
306306
goto next;
@@ -381,8 +381,6 @@ static s64 gc_trigger_reflink_p_segment(struct btree_trans *trans,
381381
not_found:
382382
if (flags & BTREE_TRIGGER_check_repair) {
383383
ret = bch2_indirect_extent_missing_error(trans, p, *idx, next_idx, false);
384-
if (ret == -BCH_ERR_missing_indirect_extent)
385-
ret = 0;
386384
if (ret)
387385
goto err;
388386
}

fs/bcachefs/sb-downgrade.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \
9393
BCH_FSCK_ERR_accounting_key_junk_at_end) \
9494
x(directory_size, \
95-
BIT_ULL(BCH_RECOVERY_PASS_check_inodes), \
95+
BIT_ULL(BCH_RECOVERY_PASS_check_dirents), \
9696
BCH_FSCK_ERR_directory_size_mismatch) \
9797

9898
#define DOWNGRADE_TABLE() \

0 commit comments

Comments
 (0)