Module Name:    src
Committed By:   rmind
Date:           Sun Nov 24 17:16:29 UTC 2013

Modified Files:
        src/sys/fs/tmpfs: tmpfs_subr.c tmpfs_vnops.c

Log Message:
- tmpfs_construct_node: prevent from the new node construction if the
  directory was removed.  Fixes the crash reported by Nicolas Joly.
- tmpfs_reclaim: avoid race by checking tn_links with the vnode locked.


To generate a diff of this commit:
cvs rdiff -u -r1.91 -r1.92 src/sys/fs/tmpfs/tmpfs_subr.c
cvs rdiff -u -r1.108 -r1.109 src/sys/fs/tmpfs/tmpfs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/tmpfs/tmpfs_subr.c
diff -u src/sys/fs/tmpfs/tmpfs_subr.c:1.91 src/sys/fs/tmpfs/tmpfs_subr.c:1.92
--- src/sys/fs/tmpfs/tmpfs_subr.c:1.91	Sat Nov 23 21:53:27 2013
+++ src/sys/fs/tmpfs/tmpfs_subr.c	Sun Nov 24 17:16:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_subr.c,v 1.91 2013/11/23 21:53:27 rmind Exp $	*/
+/*	$NetBSD: tmpfs_subr.c,v 1.92 2013/11/24 17:16:29 rmind Exp $	*/
 
 /*
  * Copyright (c) 2005-2013 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.91 2013/11/23 21:53:27 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.92 2013/11/24 17:16:29 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -358,6 +358,15 @@ tmpfs_construct_node(vnode_t *dvp, vnode
 	KASSERT(VOP_ISLOCKED(dvp));
 	*vpp = NULL;
 
+	/*
+	 * If directory was removed, prevent from node creation.  The vnode
+	 * might still be referenced, but it is about to be reclaimed.
+	 */
+	if (dnode->tn_links == 0) {
+		error = ENOENT;
+		goto out;
+	}
+
 	/* Check for the maximum number of links limit. */
 	if (vap->va_type == VDIR) {
 		/* Check for maximum links limit. */

Index: src/sys/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.108 src/sys/fs/tmpfs/tmpfs_vnops.c:1.109
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.108	Sat Nov 23 17:01:07 2013
+++ src/sys/fs/tmpfs/tmpfs_vnops.c	Sun Nov 24 17:16:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vnops.c,v 1.108 2013/11/23 17:01:07 rmind Exp $	*/
+/*	$NetBSD: tmpfs_vnops.c,v 1.109 2013/11/24 17:16:29 rmind Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.108 2013/11/23 17:01:07 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.109 2013/11/24 17:16:29 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -195,7 +195,7 @@ tmpfs_lookup(void *v)
 
 		/*
 		 * Lock the parent tn_vlock before releasing the vnode lock,
-		 * and thus prevents parent from disappearing.
+		 * and thus prevent parent from disappearing.
 		 */
 		mutex_enter(&pnode->tn_vlock);
 		VOP_UNLOCK(dvp);
@@ -1066,21 +1066,22 @@ tmpfs_reclaim(void *v)
 	vnode_t *vp = ap->a_vp;
 	tmpfs_mount_t *tmp = VFS_TO_TMPFS(vp->v_mount);
 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
-	bool racing;
+	bool recycle;
 
-	/* Disassociate inode from vnode. */
 	mutex_enter(&node->tn_vlock);
+	VOP_LOCK(vp, LK_EXCLUSIVE);
+
+	/* Disassociate inode from vnode. */
 	node->tn_vnode = NULL;
 	vp->v_data = NULL;
-	/* Check if tmpfs_vnode_get() is racing with us. */
-	racing = TMPFS_NODE_RECLAIMING(node);
+
+	/* If inode is not referenced, i.e. no links, then destroy it. */
+	recycle = node->tn_links == 0 && TMPFS_NODE_RECLAIMING(node) == 0;
+
+	VOP_UNLOCK(vp);
 	mutex_exit(&node->tn_vlock);
 
-	/*
-	 * If inode is not referenced, i.e. no links, then destroy it.
-	 * Note: if racing - inode is about to get a new vnode, leave it.
-	 */
-	if (node->tn_links == 0 && !racing) {
+	if (recycle) {
 		tmpfs_free_node(tmp, node);
 	}
 	return 0;

Reply via email to