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;