No, we can't elide the fs-wide rename lock for same-directory rename.

rename("a/b", "a/c") and rename("a/c/x", "a/b/y") will deadlock.

Darn.
This commit is contained in:
riastradh 2012-10-19 02:07:22 +00:00
parent fc7d559bb7
commit 8db30059ca
1 changed files with 7 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_syscalls.c,v 1.458 2012/10/12 02:37:20 riastradh Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.459 2012/10/19 02:07:22 riastradh Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.458 2012/10/12 02:37:20 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.459 2012/10/19 02:07:22 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_fileassoc.h"
@ -4041,11 +4041,9 @@ do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain)
* Take the vfs rename lock to avoid cross-directory screw cases.
* Nothing is locked currently, so taking this lock is safe.
*/
if (fdvp != tdvp) {
error = VFS_RENAMELOCK_ENTER(mp);
if (error)
goto abort1;
}
error = VFS_RENAMELOCK_ENTER(mp);
if (error)
goto abort1;
/*
* Now fdvp, fvp, tdvp, and (if nonnull) tvp are referenced,
@ -4186,15 +4184,13 @@ do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain)
* So all we have left to do is to drop the rename lock and
* destroy the pathbufs.
*/
if (fdvp != tdvp)
VFS_RENAMELOCK_EXIT(mp);
VFS_RENAMELOCK_EXIT(mp);
goto out2;
abort3: if ((tvp != NULL) && (tvp != tdvp))
VOP_UNLOCK(tvp);
abort2: VOP_UNLOCK(tdvp);
if (fdvp != tdvp)
VFS_RENAMELOCK_EXIT(mp);
VFS_RENAMELOCK_EXIT(mp);
abort1: VOP_ABORTOP(tdvp, &tnd.ni_cnd);
vrele(tdvp);
if (tvp != NULL)