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;