Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Aug 2013 18:54:00 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r253967 - head/sys/fs/tmpfs
Message-ID:  <201308051854.r75Is09Q090977@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Mon Aug  5 18:53:59 2013
New Revision: 253967
URL: http://svnweb.freebsd.org/changeset/base/253967

Log:
  The tmpfs_alloc_vp() is used to instantiate vnode for the tmpfs node,
  in particular, from the tmpfs_lookup VOP method.  If LK_NOWAIT is not
  specified in the lkflags, the lookup is supposed to return an alive
  vnode whenever the underlying node is valid.
  
  Currently, the tmpfs_alloc_vp() returns ENOENT if the vnode attached
  to node exists and is being reclaimed.  This causes spurious ENOENT
  errors from lookup on tmpfs and corresponding random 'No such file'
  failures from syscalls working with tmpfs files.
  
  Fix this by waiting for the doomed vnode to be detached from the tmpfs
  node if sleepable allocation is requested.
  
  Note that filesystems which use vfs_hash.c, correctly handle the case
  due to vfs_hash_get() looping when vget() returns ENOENT for sleepable
  requests.
  
  Reported and tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/fs/tmpfs/tmpfs.h
  head/sys/fs/tmpfs/tmpfs_subr.c

Modified: head/sys/fs/tmpfs/tmpfs.h
==============================================================================
--- head/sys/fs/tmpfs/tmpfs.h	Mon Aug  5 18:11:02 2013	(r253966)
+++ head/sys/fs/tmpfs/tmpfs.h	Mon Aug  5 18:53:59 2013	(r253967)
@@ -307,6 +307,7 @@ LIST_HEAD(tmpfs_node_list, tmpfs_node);
 #define TMPFS_VNODE_ALLOCATING	1
 #define TMPFS_VNODE_WANT	2
 #define TMPFS_VNODE_DOOMED	4
+#define	TMPFS_VNODE_WRECLAIM	8
 /* --------------------------------------------------------------------- */
 
 /*

Modified: head/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_subr.c	Mon Aug  5 18:11:02 2013	(r253966)
+++ head/sys/fs/tmpfs/tmpfs_subr.c	Mon Aug  5 18:53:59 2013	(r253967)
@@ -479,11 +479,32 @@ tmpfs_alloc_vp(struct mount *mp, struct 
 	error = 0;
 loop:
 	TMPFS_NODE_LOCK(node);
+loop1:
 	if ((vp = node->tn_vnode) != NULL) {
 		MPASS((node->tn_vpstate & TMPFS_VNODE_DOOMED) == 0);
 		VI_LOCK(vp);
+		if ((node->tn_type == VDIR && node->tn_dir.tn_parent == NULL) ||
+		    ((vp->v_iflag & VI_DOOMED) != 0 &&
+		    (lkflag & LK_NOWAIT) != 0)) {
+			VI_UNLOCK(vp);
+			TMPFS_NODE_UNLOCK(node);
+			error = ENOENT;
+			vp = NULL;
+			goto out;
+		}
+		if ((vp->v_iflag & VI_DOOMED) != 0) {
+			VI_UNLOCK(vp);
+			node->tn_vpstate |= TMPFS_VNODE_WRECLAIM;
+			while ((node->tn_vpstate & TMPFS_VNODE_WRECLAIM) != 0) {
+				msleep(&node->tn_vnode, TMPFS_NODE_MTX(node),
+				    0, "tmpfsE", 0);
+			}
+			goto loop1;
+		}
 		TMPFS_NODE_UNLOCK(node);
 		error = vget(vp, lkflag | LK_INTERLOCK, curthread);
+		if (error == ENOENT)
+			goto loop;
 		if (error != 0) {
 			vp = NULL;
 			goto out;
@@ -620,6 +641,9 @@ tmpfs_free_vp(struct vnode *vp)
 
 	mtx_assert(TMPFS_NODE_MTX(node), MA_OWNED);
 	node->tn_vnode = NULL;
+	if ((node->tn_vpstate & TMPFS_VNODE_WRECLAIM) != 0)
+		wakeup(&node->tn_vnode);
+	node->tn_vpstate &= ~TMPFS_VNODE_WRECLAIM;
 	vp->v_data = NULL;
 }
 



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