Module Name:    src
Committed By:   rmind
Date:           Tue Oct  6 00:17:24 UTC 2009

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

Log Message:
tmpfs_rename: handle hard-links correctly.  Fixes PR/41236.


To generate a diff of this commit:
cvs rdiff -u -r1.62 -r1.63 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_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.62 src/sys/fs/tmpfs/tmpfs_vnops.c:1.63
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.62	Thu Sep  3 04:45:28 2009
+++ src/sys/fs/tmpfs/tmpfs_vnops.c	Tue Oct  6 00:17:24 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vnops.c,v 1.62 2009/09/03 04:45:28 elad Exp $	*/
+/*	$NetBSD: tmpfs_vnops.c,v 1.63 2009/10/06 00:17:24 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.62 2009/09/03 04:45:28 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.63 2009/10/06 00:17:24 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -746,9 +746,7 @@
 
 	/* Lock vp because we will need to run tmpfs_update over it, which
 	 * needs the vnode to be locked. */
-	error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-	if (error != 0)
-		goto out1;
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 
 	/* XXX: Why aren't the following two tests done by the caller? */
 
@@ -795,16 +793,24 @@
 
 out:
 	VOP_UNLOCK(vp, 0);
-out1:
 	PNBUF_PUT(cnp->cn_pnbuf);
-
 	vput(dvp);
 
 	return error;
 }
 
-/* --------------------------------------------------------------------- */
-
+/*
+ * tmpfs_rename: rename routine.
+ *
+ * Arguments: fdvp (from-parent vnode), fvp (from-leaf), tdvp (to-parent)
+ * and tvp (to-leaf), if exists (NULL if not).
+ *
+ * => Caller holds a reference on fdvp and fvp, they are unlocked.
+ *    Note: fdvp and fvp can refer to the same object (i.e. when it is root).
+ *
+ * => Both tdvp and tvp are referenced and locked.  It is our responsibility
+ *    to release the references and unlock them (or destroy).
+ */
 int
 tmpfs_rename(void *v)
 {
@@ -857,9 +863,7 @@
 
 	/* XXX: this is a potential locking order violation! */
 	if (fdnode != tdnode) {
-		error = vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
-		if (error != 0)
-			goto out_unlocked;
+		vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
 	}
 
 	/*
@@ -871,10 +875,16 @@
 		goto out;
 	}
 
-	/* If source and target are the same file, there is nothing to do. */
+	/* If source and target is the same vnode, remove the source link. */
 	if (fvp == tvp) {
-		error = 0;
-		goto out;
+		/*
+		 * Detach and free the directory entry.  Drops the link
+		 * count on the node.
+		 */
+		tmpfs_dir_detach(fdvp, de);
+		tmpfs_free_dirent(VFS_TO_TMPFS(fvp->v_mount), de, true);
+		VN_KNOTE(fdvp, NOTE_WRITE);
+		goto out_ok;
 	}
 
 	/* If replacing an existing entry, ensure we can do the operation. */
@@ -986,7 +996,7 @@
 		fnode->tn_status |= TMPFS_NODE_CHANGED;
 		tdnode->tn_status |= TMPFS_NODE_MODIFIED;
 	}
-
+ out_ok:
 	/* Notify listeners of tdvp about the change in the directory (either
 	 * because a new entry was added or because one was removed) and
 	 * listeners of fvp about the rename. */

Reply via email to