Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcachefs: check inode->bi_parent_subvol against dirent

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>

+14 -23
+13 -22
fs/bcachefs/fsck.c
··· 1012 1012 if (fsck_err_on(u.bi_parent_subvol && 1013 1013 (u.bi_subvol == 0 || 1014 1014 u.bi_subvol == BCACHEFS_ROOT_SUBVOL), 1015 - c, inode_bi_parent_subvol_nonzero, 1015 + c, inode_bi_parent_nonzero, 1016 1016 "inode %llu:%u has subvol %u but nonzero parent subvol %u", 1017 1017 u.bi_inum, k.k->p.snapshot, u.bi_subvol, u.bi_parent_subvol)) { 1018 1018 u.bi_parent_subvol = 0; ··· 1685 1685 1686 1686 d = dirent_i_to_s_c(n); 1687 1687 } 1688 - 1689 - if (fsck_err_on(d.v->d_type == DT_SUBVOL && 1690 - target->bi_parent_subvol != le32_to_cpu(d.v->d_parent_subvol), 1691 - c, dirent_d_parent_subvol_wrong, 1692 - "dirent has wrong d_parent_subvol field: got %u, should be %u", 1693 - le32_to_cpu(d.v->d_parent_subvol), 1694 - target->bi_parent_subvol)) { 1695 - n = bch2_trans_kmalloc(trans, bkey_bytes(d.k)); 1696 - ret = PTR_ERR_OR_ZERO(n); 1697 - if (ret) 1698 - goto err; 1699 - 1700 - bkey_reassemble(&n->k_i, d.s_c); 1701 - n->v.d_parent_subvol = cpu_to_le32(target->bi_parent_subvol); 1702 - 1703 - ret = bch2_trans_update(trans, iter, &n->k_i, 0); 1704 - if (ret) 1705 - goto err; 1706 - 1707 - d = dirent_i_to_s_c(n); 1708 - } 1709 1688 err: 1710 1689 fsck_err: 1711 1690 printbuf_exit(&buf); ··· 1697 1718 { 1698 1719 struct bch_fs *c = trans->c; 1699 1720 struct bch_inode_unpacked subvol_root; 1721 + u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol); 1700 1722 u32 target_subvol = le32_to_cpu(d.v->d_child_subvol); 1701 1723 u32 target_snapshot; 1702 1724 u64 target_inum; ··· 1717 1737 &subvol_root, &target_snapshot); 1718 1738 if (ret && !bch2_err_matches(ret, ENOENT)) 1719 1739 return ret; 1740 + 1741 + if (fsck_err_on(parent_subvol != subvol_root.bi_parent_subvol, 1742 + c, inode_bi_parent_wrong, 1743 + "subvol root %llu has wrong bi_parent_subvol: got %u, should be %u", 1744 + target_inum, 1745 + subvol_root.bi_parent_subvol, parent_subvol)) { 1746 + subvol_root.bi_parent_subvol = parent_subvol; 1747 + ret = __bch2_fsck_write_inode(trans, &subvol_root, target_snapshot); 1748 + if (ret) 1749 + return ret; 1750 + } 1720 1751 1721 1752 ret = check_dirent_target(trans, iter, d, &subvol_root, 1722 1753 target_snapshot);
+1 -1
fs/bcachefs/sb-errors_types.h
··· 231 231 x(dirent_name_dot_or_dotdot, 223) \ 232 232 x(dirent_name_has_slash, 224) \ 233 233 x(dirent_d_type_wrong, 225) \ 234 - x(dirent_d_parent_subvol_wrong, 226) \ 234 + x(inode_bi_parent_wrong, 226) \ 235 235 x(dirent_in_missing_dir_inode, 227) \ 236 236 x(dirent_in_non_dir_inode, 228) \ 237 237 x(dirent_to_missing_inode, 229) \