fs: assert on ->i_count in iput_final()

Notably make sure the count is 0 after the return from ->drop_inode(),
provided we are going to drop.

Inspired by suspicious games played by f2fs.

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Mateusz Guzik 2025-10-01 03:00:10 +02:00 committed by Christian Brauner
parent dc816f8d92
commit be97a4b63c
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
1 changed files with 7 additions and 0 deletions

View File

@ -1879,6 +1879,7 @@ static void iput_final(struct inode *inode)
int drop; int drop;
WARN_ON(inode->i_state & I_NEW); WARN_ON(inode->i_state & I_NEW);
VFS_BUG_ON_INODE(atomic_read(&inode->i_count) != 0, inode);
if (op->drop_inode) if (op->drop_inode)
drop = op->drop_inode(inode); drop = op->drop_inode(inode);
@ -1893,6 +1894,12 @@ static void iput_final(struct inode *inode)
return; return;
} }
/*
* Re-check ->i_count in case the ->drop_inode() hooks played games.
* Note we only execute this if the verdict was to drop the inode.
*/
VFS_BUG_ON_INODE(atomic_read(&inode->i_count) != 0, inode);
state = inode->i_state; state = inode->i_state;
if (!drop) { if (!drop) {
WRITE_ONCE(inode->i_state, state | I_WILL_FREE); WRITE_ONCE(inode->i_state, state | I_WILL_FREE);