Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/tmpfs - tmpfs_construct_node: prevent from the new no...



details:   https://anonhg.NetBSD.org/src/rev/4b209f804b52
branches:  trunk
changeset: 791593:4b209f804b52
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Nov 24 17:16:29 2013 +0000

description:
- 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.

diffstat:

 sys/fs/tmpfs/tmpfs_subr.c  |  13 +++++++++++--
 sys/fs/tmpfs/tmpfs_vnops.c |  25 +++++++++++++------------
 2 files changed, 24 insertions(+), 14 deletions(-)

diffs (93 lines):

diff -r 6bbc21fcb1a4 -r 4b209f804b52 sys/fs/tmpfs/tmpfs_subr.c
--- a/sys/fs/tmpfs/tmpfs_subr.c Sun Nov 24 17:16:28 2013 +0000
+++ b/sys/fs/tmpfs/tmpfs_subr.c Sun Nov 24 17:16:29 2013 +0000
@@ -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 @@
        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. */
diff -r 6bbc21fcb1a4 -r 4b209f804b52 sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Sun Nov 24 17:16:28 2013 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Sun Nov 24 17:16:29 2013 +0000
@@ -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 @@
 
                /*
                 * 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 @@
        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;
+
+       mutex_enter(&node->tn_vlock);
+       VOP_LOCK(vp, LK_EXCLUSIVE);
 
        /* Disassociate inode from vnode. */
-       mutex_enter(&node->tn_vlock);
        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;



Home | Main Index | Thread Index | Old Index