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

bcachefs: __lookup_dirent() works in snapshot, not subvol

Add a new helper, bch2_hash_lookup_in_snapshot(), for when we're not
operating in a subvolume and already have a snapshot ID, and then use it
in lookup_lostfound() -> __lookup_dirent().

This is a bugfix - lookup_lostfound() doesn't take a subvolume ID, we
were passing a nonsense subvolume ID before, and don't have one to pass
since we may be operating in an interior snapshot node that doesn't have
a subvolume ID.

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

+27 -18
+12 -11
fs/bcachefs/fsck.c
··· 119 119 if (!ret) 120 120 *snapshot = iter.pos.snapshot; 121 121 err: 122 - bch_err_msg(trans->c, ret, "fetching inode %llu:%u", inode_nr, *snapshot); 123 122 bch2_trans_iter_exit(trans, &iter); 124 123 return ret; 125 124 } 126 125 127 - static int __lookup_dirent(struct btree_trans *trans, 126 + static int lookup_dirent_in_snapshot(struct btree_trans *trans, 128 127 struct bch_hash_info hash_info, 129 128 subvol_inum dir, struct qstr *name, 130 - u64 *target, unsigned *type) 129 + u64 *target, unsigned *type, u32 snapshot) 131 130 { 132 131 struct btree_iter iter; 133 132 struct bkey_s_c_dirent d; 134 - int ret; 135 - 136 - ret = bch2_hash_lookup(trans, &iter, bch2_dirent_hash_desc, 137 - &hash_info, dir, name, 0); 133 + int ret = bch2_hash_lookup_in_snapshot(trans, &iter, bch2_dirent_hash_desc, 134 + &hash_info, dir, name, 0, snapshot); 138 135 if (ret) 139 136 return ret; 140 137 ··· 222 225 223 226 struct bch_inode_unpacked root_inode; 224 227 struct bch_hash_info root_hash_info; 225 - ret = lookup_inode(trans, root_inum.inum, &root_inode, &snapshot); 228 + u32 root_inode_snapshot = snapshot; 229 + ret = lookup_inode(trans, root_inum.inum, &root_inode, &root_inode_snapshot); 226 230 bch_err_msg(c, ret, "looking up root inode"); 227 231 if (ret) 228 232 return ret; 229 233 230 234 root_hash_info = bch2_hash_info_init(c, &root_inode); 231 235 232 - ret = __lookup_dirent(trans, root_hash_info, root_inum, 233 - &lostfound_str, &inum, &d_type); 236 + ret = lookup_dirent_in_snapshot(trans, root_hash_info, root_inum, 237 + &lostfound_str, &inum, &d_type, snapshot); 234 238 if (bch2_err_matches(ret, ENOENT)) 235 239 goto create_lostfound; 236 240 ··· 248 250 * The bch2_check_dirents pass has already run, dangling dirents 249 251 * shouldn't exist here: 250 252 */ 251 - return lookup_inode(trans, inum, lostfound, &snapshot); 253 + ret = lookup_inode(trans, inum, lostfound, &snapshot); 254 + bch_err_msg(c, ret, "looking up lost+found %llu:%u in (root inode %llu, snapshot root %u)", 255 + inum, snapshot, root_inum.inum, bch2_snapshot_root(c, snapshot)); 256 + return ret; 252 257 253 258 create_lostfound: 254 259 /*
+15 -7
fs/bcachefs/str_hash.h
··· 160 160 } 161 161 162 162 static __always_inline int 163 - bch2_hash_lookup(struct btree_trans *trans, 163 + bch2_hash_lookup_in_snapshot(struct btree_trans *trans, 164 164 struct btree_iter *iter, 165 165 const struct bch_hash_desc desc, 166 166 const struct bch_hash_info *info, 167 167 subvol_inum inum, const void *key, 168 - unsigned flags) 168 + unsigned flags, u32 snapshot) 169 169 { 170 170 struct bkey_s_c k; 171 - u32 snapshot; 172 171 int ret; 173 - 174 - ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot); 175 - if (ret) 176 - return ret; 177 172 178 173 for_each_btree_key_upto_norestart(trans, *iter, desc.btree_id, 179 174 SPOS(inum.inum, desc.hash_key(info, key), snapshot), ··· 187 192 bch2_trans_iter_exit(trans, iter); 188 193 189 194 return ret ?: -BCH_ERR_ENOENT_str_hash_lookup; 195 + } 196 + 197 + static __always_inline int 198 + bch2_hash_lookup(struct btree_trans *trans, 199 + struct btree_iter *iter, 200 + const struct bch_hash_desc desc, 201 + const struct bch_hash_info *info, 202 + subvol_inum inum, const void *key, 203 + unsigned flags) 204 + { 205 + u32 snapshot; 206 + return bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot) ?: 207 + bch2_hash_lookup_in_snapshot(trans, iter, desc, info, inum, key, flags, snapshot); 190 208 } 191 209 192 210 static __always_inline int