Skip to content

Commit 9ba6930

Browse files
author
Kent Overstreet
committed
bcachefs: Fix __bch2_inum_to_path() when crossing subvol boundaries
The bch2_subvolume_get_snapshot() call needs to happen before the dirent lookup - the dirent is in the parent subvolume. Also, check for loops. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 1cddad0 commit 9ba6930

1 file changed

Lines changed: 22 additions & 5 deletions

File tree

fs/bcachefs/namei.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -625,14 +625,26 @@ static int __bch2_inum_to_path(struct btree_trans *trans,
625625
{
626626
unsigned orig_pos = path->pos;
627627
int ret = 0;
628+
DARRAY(subvol_inum) inums = {};
629+
630+
if (!snapshot) {
631+
ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot);
632+
if (ret)
633+
goto disconnected;
634+
}
628635

629636
while (true) {
630-
if (!snapshot) {
631-
ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot);
632-
if (ret)
633-
goto disconnected;
637+
subvol_inum n = (subvol_inum) { subvol ?: snapshot, inum };
638+
639+
if (darray_find_p(inums, i, i->subvol == n.subvol && i->inum == n.inum)) {
640+
prt_str_reversed(path, "(loop)");
641+
break;
634642
}
635643

644+
ret = darray_push(&inums, n);
645+
if (ret)
646+
goto err;
647+
636648
struct bch_inode_unpacked inode;
637649
ret = bch2_inode_find_by_inum_snapshot(trans, inum, snapshot, &inode, 0);
638650
if (ret)
@@ -650,7 +662,9 @@ static int __bch2_inum_to_path(struct btree_trans *trans,
650662
inum = inode.bi_dir;
651663
if (inode.bi_parent_subvol) {
652664
subvol = inode.bi_parent_subvol;
653-
snapshot = 0;
665+
ret = bch2_subvolume_get_snapshot(trans, inode.bi_parent_subvol, &snapshot);
666+
if (ret)
667+
goto disconnected;
654668
}
655669

656670
struct btree_iter d_iter;
@@ -662,6 +676,7 @@ static int __bch2_inum_to_path(struct btree_trans *trans,
662676
goto disconnected;
663677

664678
struct qstr dirent_name = bch2_dirent_get_name(d);
679+
665680
prt_bytes_reversed(path, dirent_name.name, dirent_name.len);
666681

667682
prt_char(path, '/');
@@ -677,8 +692,10 @@ static int __bch2_inum_to_path(struct btree_trans *trans,
677692
goto err;
678693

679694
reverse_bytes(path->buf + orig_pos, path->pos - orig_pos);
695+
darray_exit(&inums);
680696
return 0;
681697
err:
698+
darray_exit(&inums);
682699
return ret;
683700
disconnected:
684701
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))

0 commit comments

Comments
 (0)