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. */