Re: [PATCH] vfs: keep the mount pinned while waiting for a parent delegation break
From: Al Viro
Date: Fri Oct 16 2026 - 14:39:00 EST
On Fri, Oct 16, 2026 at 07:29:27PM +0100, Al Viro wrote:
> On Fri, Oct 16, 2026 at 05:34:21PM +0800, Zhao Gongyi wrote:
> > filename_mknodat(), filename_mkdirat(), filename_symlinkat() and
> > filename_rmdir() can call break_deleg_wait() on a delegated parent
> > directory after dropping the struct path that pins the mount.
> > try_break_deleg() only takes an inode reference, and an inode reference
> > does not keep the superblock active.
>
> So why not have it acquire an active superblock reference at the
> same time? We don't need struct mount reference there - all it
> takes in increment of inode->i_sb->s_active on try_break_deleg()
> side and deactivate_super() on ->i_sb fetched *before* iput()
> of ->di_inode on the break_deleg_wait() side...
>
> No need to mess with every user of that thing...
I mean, something like
static inline int try_break_deleg(struct inode *inode, unsigned int flags,
struct delegated_inode *di)
{
int ret;
ret = break_deleg(inode, flags | LEASE_BREAK_NONBLOCK);
if (ret == -EWOULDBLOCK && di) {
di->di_inode = inode;
ihold(inode);
// make sure that extra reference we've just
// grabbed wont outlive the superblock
atomic_inc(inode->i_sb->s_active);
}
return ret;
}
static inline int break_deleg_wait(struct delegated_inode *di)
{
struct inode *inode = di->di_inode;
struct super_block *sb = inode->i_sb;
int ret = break_deleg(inode, 0);
iput(inode);
deactivate_super(sb);
di->di_inode = NULL;
return ret;
}