kern/150143: [patch][tmpfs] Source directory vnode can disappear before locking it in tmpfs_rename

Gleb Kurtsou gk at FreeBSD.org
Tue Aug 31 10:50:03 UTC 2010


>Number:         150143
>Category:       kern
>Synopsis:       [patch][tmpfs] Source directory vnode can disappear before locking it in tmpfs_rename
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 31 10:50:02 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Gleb Kurtsou
>Release:        FreeBSD 9.0-CURRENT
>Organization:
>Environment:
>Description:
Source directory vnode can disappear before locking it in tmpfs_rename.

Fixes panic triggered by blogbench.

Also note that fdvp vnode locking order may be incorrect in tmpfs_rename, and thus rename is deadlock prone. It was initially incorrect, possible solution could be to lock all necessary vnodes similarly to ufs, but it seems not to work well with tmpfs.
>How-To-Repeat:

>Fix:
Patch attached, tested by Ivan Voras

Patch attached with submission follows:

commit 82d1664e6831dbc44d380170ed5590ff67113749
Author: Gleb Kurtsou <gleb.kurtsou at gmail.com>
Date:   Thu Aug 12 13:05:17 2010 +0300

    tmpfs: Source entry can disappear before we lock fdvp in tmpfs_rename()
    
    Fixes panic triggered by blogbench

diff --git a/fs/tmpfs/tmpfs_vnops.c b/fs/tmpfs/tmpfs_vnops.c
index ef54e5e..117700b 100644
--- a/fs/tmpfs/tmpfs_vnops.c
+++ b/fs/tmpfs/tmpfs_vnops.c
@@ -991,10 +991,14 @@ tmpfs_rename(struct vop_rename_args *v)
 	fnode = VP_TO_TMPFS_NODE(fvp);
 	de = tmpfs_dir_lookup(fdnode, fnode, fcnp);
 
-	/* Avoid manipulating '.' and '..' entries. */
+	/* Entry can disappear before we lock fdvp,
+	 * also avoid manipulating '.' and '..' entries. */
 	if (de == NULL) {
-		MPASS(fvp->v_type == VDIR);
-		error = EINVAL;
+		if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
+		    (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
+			error = EINVAL;
+		else
+			error = ENOENT;
 		goto out_locked;
 	}
 	MPASS(de->td_node == fnode);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list