Skip to content

Commit 495ba89

Browse files
author
Kent Overstreet
committed
bcachefs: fsck: Fix check_path_loop() + snapshots
A path exists in a particular snapshot: we should do the pathwalk in the snapshot ID of the inode we started from, _not_ change snapshot ID as we walk inodes and dirents. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 583ba52 commit 495ba89

1 file changed

Lines changed: 26 additions & 36 deletions

File tree

fs/bcachefs/fsck.c

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,19 +2689,13 @@ int bch2_check_subvolume_structure(struct bch_fs *c)
26892689
return ret;
26902690
}
26912691

2692-
struct pathbuf_entry {
2693-
u64 inum;
2694-
u32 snapshot;
2695-
};
2696-
2697-
typedef DARRAY(struct pathbuf_entry) pathbuf;
2698-
2699-
static int bch2_bi_depth_renumber_one(struct btree_trans *trans, struct pathbuf_entry *p,
2692+
static int bch2_bi_depth_renumber_one(struct btree_trans *trans,
2693+
u64 inum, u32 snapshot,
27002694
u32 new_depth)
27012695
{
27022696
struct btree_iter iter;
27032697
struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
2704-
SPOS(0, p->inum, p->snapshot), 0);
2698+
SPOS(0, inum, snapshot), 0);
27052699

27062700
struct bch_inode_unpacked inode;
27072701
int ret = bkey_err(k) ?:
@@ -2720,14 +2714,15 @@ static int bch2_bi_depth_renumber_one(struct btree_trans *trans, struct pathbuf_
27202714
return ret;
27212715
}
27222716

2723-
static int bch2_bi_depth_renumber(struct btree_trans *trans, pathbuf *path, u32 new_bi_depth)
2717+
static int bch2_bi_depth_renumber(struct btree_trans *trans, darray_u64 *path,
2718+
u32 snapshot, u32 new_bi_depth)
27242719
{
27252720
u32 restart_count = trans->restart_count;
27262721
int ret = 0;
27272722

27282723
darray_for_each_reverse(*path, i) {
27292724
ret = nested_lockrestart_do(trans,
2730-
bch2_bi_depth_renumber_one(trans, i, new_bi_depth));
2725+
bch2_bi_depth_renumber_one(trans, *i, snapshot, new_bi_depth));
27312726
bch_err_fn(trans->c, ret);
27322727
if (ret)
27332728
break;
@@ -2738,26 +2733,19 @@ static int bch2_bi_depth_renumber(struct btree_trans *trans, pathbuf *path, u32
27382733
return ret ?: trans_was_restarted(trans, restart_count);
27392734
}
27402735

2741-
static bool path_is_dup(pathbuf *p, u64 inum, u32 snapshot)
2742-
{
2743-
darray_for_each(*p, i)
2744-
if (i->inum == inum &&
2745-
i->snapshot == snapshot)
2746-
return true;
2747-
return false;
2748-
}
2749-
27502736
static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27512737
{
27522738
struct bch_fs *c = trans->c;
27532739
struct btree_iter inode_iter = {};
2754-
pathbuf path = {};
2740+
darray_u64 path = {};
27552741
struct printbuf buf = PRINTBUF;
27562742
u32 snapshot = inode_k.k->p.snapshot;
27572743
bool redo_bi_depth = false;
27582744
u32 min_bi_depth = U32_MAX;
27592745
int ret = 0;
27602746

2747+
struct bpos start = inode_k.k->p;
2748+
27612749
struct bch_inode_unpacked inode;
27622750
ret = bch2_inode_unpack(inode_k, &inode);
27632751
if (ret)
@@ -2766,9 +2754,9 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27662754
while (!inode.bi_subvol) {
27672755
struct btree_iter dirent_iter;
27682756
struct bkey_s_c_dirent d;
2769-
u32 parent_snapshot = snapshot;
27702757

2771-
d = inode_get_dirent(trans, &dirent_iter, &inode, &parent_snapshot);
2758+
d = dirent_get_by_pos(trans, &dirent_iter,
2759+
SPOS(inode.bi_dir, inode.bi_dir_offset, snapshot));
27722760
ret = bkey_err(d.s_c);
27732761
if (ret && !bch2_err_matches(ret, ENOENT))
27742762
goto out;
@@ -2786,15 +2774,10 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27862774

27872775
bch2_trans_iter_exit(trans, &dirent_iter);
27882776

2789-
ret = darray_push(&path, ((struct pathbuf_entry) {
2790-
.inum = inode.bi_inum,
2791-
.snapshot = snapshot,
2792-
}));
2777+
ret = darray_push(&path, inode.bi_inum);
27932778
if (ret)
27942779
return ret;
27952780

2796-
snapshot = parent_snapshot;
2797-
27982781
bch2_trans_iter_exit(trans, &inode_iter);
27992782
inode_k = bch2_bkey_get_iter(trans, &inode_iter, BTREE_ID_inodes,
28002783
SPOS(0, inode.bi_dir, snapshot), 0);
@@ -2816,15 +2799,22 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
28162799
break;
28172800

28182801
inode = parent_inode;
2819-
snapshot = inode_k.k->p.snapshot;
28202802
redo_bi_depth = true;
28212803

2822-
if (path_is_dup(&path, inode.bi_inum, snapshot)) {
2804+
if (darray_find(path, inode.bi_inum)) {
28232805
printbuf_reset(&buf);
2824-
prt_printf(&buf, "directory structure loop:\n");
2825-
darray_for_each_reverse(path, i)
2826-
prt_printf(&buf, "%llu:%u ", i->inum, i->snapshot);
2827-
prt_printf(&buf, "%llu:%u", inode.bi_inum, snapshot);
2806+
prt_printf(&buf, "directory structure loop in snapshot %u: ",
2807+
snapshot);
2808+
2809+
ret = bch2_inum_snapshot_to_path(trans, start.offset, start.snapshot, NULL, &buf);
2810+
if (ret)
2811+
goto out;
2812+
2813+
if (c->opts.verbose) {
2814+
prt_newline(&buf);
2815+
darray_for_each(path, i)
2816+
prt_printf(&buf, "%llu ", *i);
2817+
}
28282818

28292819
if (fsck_err(trans, dir_loop, "%s", buf.buf)) {
28302820
ret = remove_backpointer(trans, &inode);
@@ -2844,7 +2834,7 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
28442834
min_bi_depth = 0;
28452835

28462836
if (redo_bi_depth)
2847-
ret = bch2_bi_depth_renumber(trans, &path, min_bi_depth);
2837+
ret = bch2_bi_depth_renumber(trans, &path, snapshot, min_bi_depth);
28482838
out:
28492839
fsck_err:
28502840
bch2_trans_iter_exit(trans, &inode_iter);

0 commit comments

Comments
 (0)