diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-03-16 11:04:28 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:57 -0400 |
commit | 2d33036ca9360bacef23ba32e7768ff9ea87f2be (patch) | |
tree | 1c425312eb2896e788276ed19a898c1feb469475 /fs/bcachefs/fs.c | |
parent | 56cc033dfcf002eb8a957097fe7290546829b7c0 (diff) | |
download | linux-2d33036ca9360bacef23ba32e7768ff9ea87f2be.tar.gz linux-2d33036ca9360bacef23ba32e7768ff9ea87f2be.tar.bz2 linux-2d33036ca9360bacef23ba32e7768ff9ea87f2be.zip |
bcachefs: Fix for 'missing subvolume' error
Subvolumes, including their root inodes, get deleted asynchronously
after an unlink. But we still need to ensure that we tell the VFS the
inode has been deleted, otherwise VFS writeback could fire after
asynchronous deletion has finished, and try to write to an
inode/subvolume that no longer exists.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/fs.c')
-rw-r--r-- | fs/bcachefs/fs.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 15ab77ebb8c6..828887abc261 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -442,19 +442,27 @@ int __bch2_unlink(struct inode *vdir, struct dentry *dentry, bch2_trans_init(&trans, c, 4, 1024); ret = commit_do(&trans, NULL, NULL, - BTREE_INSERT_NOFAIL, - bch2_unlink_trans(&trans, - inode_inum(dir), &dir_u, - &inode_u, &dentry->d_name, - deleting_snapshot)); + BTREE_INSERT_NOFAIL, + bch2_unlink_trans(&trans, + inode_inum(dir), &dir_u, + &inode_u, &dentry->d_name, + deleting_snapshot)); + if (unlikely(ret)) + goto err; - if (likely(!ret)) { - bch2_inode_update_after_write(&trans, dir, &dir_u, - ATTR_MTIME|ATTR_CTIME); - bch2_inode_update_after_write(&trans, inode, &inode_u, - ATTR_MTIME); - } + bch2_inode_update_after_write(&trans, dir, &dir_u, + ATTR_MTIME|ATTR_CTIME); + bch2_inode_update_after_write(&trans, inode, &inode_u, + ATTR_MTIME); + if (inode_u.bi_subvol) { + /* + * Subvolume deletion is asynchronous, but we still want to tell + * the VFS that it's been deleted here: + */ + set_nlink(&inode->v, 0); + } +err: bch2_trans_exit(&trans); bch2_unlock_inodes(INODE_UPDATE_LOCK, dir, inode); |