Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Aug 2011 14:29:20 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r224635 - stable/8/sys/fs/devfs
Message-ID:  <201108031429.p73ETK2X017231@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Aug  3 14:29:20 2011
New Revision: 224635
URL: http://svn.freebsd.org/changeset/base/224635

Log:
  MFC r223988:
  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.

Modified:
  stable/8/sys/fs/devfs/devfs_vnops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- stable/8/sys/fs/devfs/devfs_vnops.c	Wed Aug  3 13:39:11 2011	(r224634)
+++ stable/8/sys/fs/devfs/devfs_vnops.c	Wed Aug  3 14:29:20 2011	(r224635)
@@ -346,6 +346,7 @@ devfs_allocv(struct devfs_dirent *de, st
 		sx_xunlock(&dmp->dm_lock);
 		return (ENOENT);
 	}
+loop:
 	DEVFS_DE_HOLD(de);
 	DEVFS_DMP_HOLD(dmp);
 	mtx_lock(&devfs_de_interlock);
@@ -354,16 +355,21 @@ devfs_allocv(struct devfs_dirent *de, st
 		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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108031429.p73ETK2X017231>