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

bcachefs: bch2_inode_insert()

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

+79 -65
+79 -65
fs/bcachefs/fs.c
··· 176 176 return jhash_3words(inum.subvol, inum.inum >> 32, inum.inum, JHASH_INITVAL); 177 177 } 178 178 179 - struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum) 179 + static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_inode_info *inode) 180 180 { 181 - struct bch_inode_unpacked inode_u; 182 - struct bch_inode_info *inode; 183 - struct btree_trans *trans; 184 - struct bch_subvolume subvol; 185 - int ret; 181 + subvol_inum inum = inode_inum(inode); 182 + struct bch_inode_info *old = to_bch_ei(inode_insert5(&inode->v, 183 + bch2_inode_hash(inum), 184 + bch2_iget5_test, 185 + bch2_iget5_set, 186 + &inum)); 187 + BUG_ON(!old); 186 188 187 - inode = to_bch_ei(iget5_locked(c->vfs_sb, 188 - bch2_inode_hash(inum), 189 - bch2_iget5_test, 190 - bch2_iget5_set, 191 - &inum)); 192 - if (unlikely(!inode)) 193 - return ERR_PTR(-ENOMEM); 194 - if (!(inode->v.i_state & I_NEW)) 195 - return &inode->v; 196 - 197 - trans = bch2_trans_get(c); 198 - ret = lockrestart_do(trans, 199 - bch2_subvolume_get(trans, inum.subvol, true, 0, &subvol) ?: 200 - bch2_inode_find_by_inum_trans(trans, inum, &inode_u)); 201 - 202 - if (!ret) 203 - bch2_vfs_inode_init(trans, inum, inode, &inode_u, &subvol); 204 - bch2_trans_put(trans); 205 - 206 - if (ret) { 207 - iget_failed(&inode->v); 208 - return ERR_PTR(bch2_err_class(ret)); 189 + if (unlikely(old != inode)) { 190 + discard_new_inode(&inode->v); 191 + inode = old; 192 + } else { 193 + mutex_lock(&c->vfs_inodes_lock); 194 + list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list); 195 + mutex_unlock(&c->vfs_inodes_lock); 196 + /* 197 + * we really don't want insert_inode_locked2() to be setting 198 + * I_NEW... 199 + */ 200 + unlock_new_inode(&inode->v); 209 201 } 210 202 211 - mutex_lock(&c->vfs_inodes_lock); 212 - list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list); 213 - mutex_unlock(&c->vfs_inodes_lock); 203 + return inode; 204 + } 214 205 215 - unlock_new_inode(&inode->v); 206 + #define memalloc_flags_do(_flags, _do) \ 207 + ({ \ 208 + unsigned _saved_flags = memalloc_flags_save(_flags); \ 209 + typeof(_do) _ret = _do; \ 210 + memalloc_noreclaim_restore(_saved_flags); \ 211 + _ret; \ 212 + }) 216 213 217 - return &inode->v; 214 + /* 215 + * Allocate a new inode, dropping/retaking btree locks if necessary: 216 + */ 217 + static struct bch_inode_info *bch2_new_inode(struct btree_trans *trans) 218 + { 219 + struct bch_fs *c = trans->c; 220 + 221 + struct bch_inode_info *inode = 222 + memalloc_flags_do(PF_MEMALLOC_NORECLAIM|PF_MEMALLOC_NOWARN, 223 + to_bch_ei(new_inode(c->vfs_sb))); 224 + 225 + if (unlikely(!inode)) { 226 + int ret = drop_locks_do(trans, (inode = to_bch_ei(new_inode(c->vfs_sb))) ? 0 : -ENOMEM); 227 + if (ret && inode) 228 + discard_new_inode(&inode->v); 229 + if (ret) 230 + return ERR_PTR(ret); 231 + } 232 + 233 + return inode; 234 + } 235 + 236 + struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum) 237 + { 238 + struct bch_inode_info *inode = 239 + to_bch_ei(ilookup5_nowait(c->vfs_sb, 240 + bch2_inode_hash(inum), 241 + bch2_iget5_test, 242 + &inum)); 243 + if (inode) 244 + return &inode->v; 245 + 246 + struct btree_trans *trans = bch2_trans_get(c); 247 + 248 + struct bch_inode_unpacked inode_u; 249 + struct bch_subvolume subvol; 250 + int ret = lockrestart_do(trans, 251 + bch2_subvolume_get(trans, inum.subvol, true, 0, &subvol) ?: 252 + bch2_inode_find_by_inum_trans(trans, inum, &inode_u)) ?: 253 + PTR_ERR_OR_ZERO(inode = bch2_new_inode(trans)); 254 + if (!ret) { 255 + bch2_vfs_inode_init(trans, inum, inode, &inode_u, &subvol); 256 + inode = bch2_inode_insert(c, inode); 257 + } 258 + bch2_trans_put(trans); 259 + 260 + return ret ? ERR_PTR(ret) : &inode->v; 218 261 } 219 262 220 263 struct bch_inode_info * ··· 269 226 struct bch_fs *c = dir->v.i_sb->s_fs_info; 270 227 struct btree_trans *trans; 271 228 struct bch_inode_unpacked dir_u; 272 - struct bch_inode_info *inode, *old; 229 + struct bch_inode_info *inode; 273 230 struct bch_inode_unpacked inode_u; 274 231 struct posix_acl *default_acl = NULL, *acl = NULL; 275 232 subvol_inum inum; ··· 336 293 mutex_unlock(&dir->ei_update_lock); 337 294 } 338 295 339 - bch2_iget5_set(&inode->v, &inum); 340 296 bch2_vfs_inode_init(trans, inum, inode, &inode_u, &subvol); 341 297 342 298 set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl); ··· 346 304 * bch2_trans_exit() and dropping locks, else we could race with another 347 305 * thread pulling the inode in and modifying it: 348 306 */ 349 - 350 - inode->v.i_state |= I_CREATING; 351 - 352 - old = to_bch_ei(inode_insert5(&inode->v, 353 - bch2_inode_hash(inum), 354 - bch2_iget5_test, 355 - bch2_iget5_set, 356 - &inum)); 357 - BUG_ON(!old); 358 - 359 - if (unlikely(old != inode)) { 360 - /* 361 - * We raced, another process pulled the new inode into cache 362 - * before us: 363 - */ 364 - make_bad_inode(&inode->v); 365 - iput(&inode->v); 366 - 367 - inode = old; 368 - } else { 369 - mutex_lock(&c->vfs_inodes_lock); 370 - list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list); 371 - mutex_unlock(&c->vfs_inodes_lock); 372 - /* 373 - * we really don't want insert_inode_locked2() to be setting 374 - * I_NEW... 375 - */ 376 - unlock_new_inode(&inode->v); 377 - } 378 - 307 + inode = bch2_inode_insert(c, inode); 379 308 bch2_trans_put(trans); 380 309 err: 381 310 posix_acl_release(default_acl); ··· 1385 1372 struct bch_inode_unpacked *bi, 1386 1373 struct bch_subvolume *subvol) 1387 1374 { 1375 + bch2_iget5_set(&inode->v, &inum); 1388 1376 bch2_inode_update_after_write(trans, inode, bi, ~0); 1389 1377 1390 1378 if (BCH_SUBVOLUME_SNAP(subvol))