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_rename: handle hard-links correctly. Fix...



details:   https://anonhg.NetBSD.org/src/rev/854abac05be3
branches:  trunk
changeset: 747932:854abac05be3
user:      rmind <rmind%NetBSD.org@localhost>
date:      Tue Oct 06 00:17:24 2009 +0000

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

diffstat:

 sys/fs/tmpfs/tmpfs_vnops.c |  42 ++++++++++++++++++++++++++----------------
 1 files changed, 26 insertions(+), 16 deletions(-)

diffs (98 lines):

diff -r 8f18d0b6b274 -r 854abac05be3 sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Mon Oct 05 23:59:30 2009 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Tue Oct 06 00:17:24 2009 +0000
@@ -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. */



Home | Main Index | Thread Index | Old Index