mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-05 09:14:03 +00:00
While fixing the looping of a thread while devfs vnode is reclaimed,
r179247 introduced a possibility of devfs_allocv() returning spurious ENOENT. If the vnode is selected by vnlru daemon for reclamation, then devfs_allocv() can get ENOENT from vget() due to devfs_close() dropping vnode lock around the call to cdevsw d_close method. Use LK_RETRY in the vget() call, and do some part of the devfs_reclaim() work in devfs_allocv(), clearing vp->v_data and de->de_vnode. Retry the allocation of the vnode, now with de->de_vnode == NULL. The check vp->v_data == NULL at the start of devfs_close() cannot be affected by the change, since vnode lock must be held while VI_DOOMED is set, and only dropped after the check. Reported and tested by: Kohji Okuno <okuno.kohji jp panasonic com> Reviewed by: attilio MFC after: 3 weeks
This commit is contained in:
parent
fcdbb666c0
commit
724ce55b5b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223988
@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
|
||||
sx_xunlock(&dmp->dm_lock);
|
||||
return (ENOENT);
|
||||
}
|
||||
loop:
|
||||
DEVFS_DE_HOLD(de);
|
||||
DEVFS_DMP_HOLD(dmp);
|
||||
mtx_lock(&devfs_de_interlock);
|
||||
@ -405,16 +406,21 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
|
||||
VI_LOCK(vp);
|
||||
mtx_unlock(&devfs_de_interlock);
|
||||
sx_xunlock(&dmp->dm_lock);
|
||||
error = vget(vp, lockmode | LK_INTERLOCK, curthread);
|
||||
vget(vp, lockmode | LK_INTERLOCK | LK_RETRY, curthread);
|
||||
sx_xlock(&dmp->dm_lock);
|
||||
if (devfs_allocv_drop_refs(0, dmp, de)) {
|
||||
if (error == 0)
|
||||
vput(vp);
|
||||
vput(vp);
|
||||
return (ENOENT);
|
||||
}
|
||||
else if (error) {
|
||||
sx_xunlock(&dmp->dm_lock);
|
||||
return (error);
|
||||
else if ((vp->v_iflag & VI_DOOMED) != 0) {
|
||||
mtx_lock(&devfs_de_interlock);
|
||||
if (de->de_vnode == vp) {
|
||||
de->de_vnode = NULL;
|
||||
vp->v_data = NULL;
|
||||
}
|
||||
mtx_unlock(&devfs_de_interlock);
|
||||
vput(vp);
|
||||
goto loop;
|
||||
}
|
||||
sx_xunlock(&dmp->dm_lock);
|
||||
*vpp = vp;
|
||||
|
Loading…
Reference in New Issue
Block a user