Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Bracket do_sys_renameat() and nfsrv_rename() with fstrans.
details: https://anonhg.NetBSD.org/src/rev/68f945c02ff1
branches: trunk
changeset: 449058:68f945c02ff1
user: hannken <hannken%NetBSD.org@localhost>
date: Wed Feb 20 10:05:20 2019 +0000
description:
Bracket do_sys_renameat() and nfsrv_rename() with fstrans.
The v_mount field for vnodes on the same file system as "from"
is now stable for referenced vnodes.
VFS_RENAMELOCK no longer may use lock from an unreferenced and
freed "struct mount".
diffstat:
sys/kern/vfs_syscalls.c | 53 +++++++++++++++++++-----------------------------
sys/nfs/nfs_serv.c | 10 ++++++--
2 files changed, 28 insertions(+), 35 deletions(-)
diffs (157 lines):
diff -r 2854ca2bc214 -r 68f945c02ff1 sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c Wed Feb 20 10:04:28 2019 +0000
+++ b/sys/kern/vfs_syscalls.c Wed Feb 20 10:05:20 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_syscalls.c,v 1.525 2019/02/19 06:55:28 mlelstv Exp $ */
+/* $NetBSD: vfs_syscalls.c,v 1.526 2019/02/20 10:05:20 hannken 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.525 2019/02/19 06:55:28 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.526 2019/02/20 10:05:20 hannken Exp $");
#ifdef _KERNEL_OPT
#include "opt_fileassoc.h"
@@ -4224,9 +4224,18 @@
*/
fdvp = fnd.ni_dvp;
fvp = fnd.ni_vp;
+ mp = fdvp->v_mount;
KASSERT(fdvp != NULL);
KASSERT(fvp != NULL);
KASSERT((fdvp == fvp) || (VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE));
+ /*
+ * Bracket the operation with fstrans_start()/fstrans_done().
+ *
+ * Inside the bracket this file system cannot be unmounted so
+ * a vnode on this file system cannot change its v_mount.
+ * A vnode on another file system may still change to dead mount.
+ */
+ fstrans_start(mp);
/*
* Make sure neither fdvp nor fvp is locked.
@@ -4311,38 +4320,16 @@
}
/*
- * Get the mount point. If the file system has been unmounted,
- * which it may be because we're not holding any vnode locks,
- * then v_mount will be NULL. We're not really supposed to
- * read v_mount without holding the vnode lock, but since we
- * have fdvp referenced, if fdvp->v_mount changes then at worst
- * it will be set to NULL, not changed to another mount point.
- * And, of course, since it is up to the file system to
- * determine the real lock order, we can't lock both fdvp and
- * tdvp at the same time.
+ * Make sure the mount points match. Although we don't hold
+ * any vnode locks, the v_mount on fdvp file system are stable.
+ *
+ * Unmounting another file system at an inopportune moment may
+ * cause tdvp to disappear and change its v_mount to dead.
+ *
+ * So in either case different v_mount means cross-device rename.
*/
- mp = fdvp->v_mount;
- if (mp == NULL) {
- error = ENOENT;
- goto abort1;
- }
-
- /*
- * Make sure the mount points match. Again, although we don't
- * hold any vnode locks, the v_mount fields may change -- but
- * at worst they will change to NULL, so this will never become
- * a cross-device rename, because we hold vnode references.
- *
- * XXX Because nothing is locked and the compiler may reorder
- * things here, unmounting the file system at an inopportune
- * moment may cause rename to fail with EXDEV when it really
- * should fail with ENOENT.
- */
+ KASSERT(mp != NULL);
tmp = tdvp->v_mount;
- if (tmp == NULL) {
- error = ENOENT;
- goto abort1;
- }
if (mp != tmp) {
error = EXDEV;
@@ -4497,6 +4484,7 @@
* destroy the pathbufs.
*/
VFS_RENAMELOCK_EXIT(mp);
+ fstrans_done(mp);
goto out2;
abort3: if ((tvp != NULL) && (tvp != tdvp))
@@ -4510,6 +4498,7 @@
abort0: VOP_ABORTOP(fdvp, &fnd.ni_cnd);
vrele(fdvp);
vrele(fvp);
+ fstrans_done(mp);
out2: pathbuf_destroy(tpb);
out1: pathbuf_destroy(fpb);
out0: return error;
diff -r 2854ca2bc214 -r 68f945c02ff1 sys/nfs/nfs_serv.c
--- a/sys/nfs/nfs_serv.c Wed Feb 20 10:04:28 2019 +0000
+++ b/sys/nfs/nfs_serv.c Wed Feb 20 10:05:20 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_serv.c,v 1.176 2019/02/03 03:19:28 mrg Exp $ */
+/* $NetBSD: nfs_serv.c,v 1.177 2019/02/20 10:05:20 hannken Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.176 2019/02/03 03:19:28 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.177 2019/02/20 10:05:20 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -64,6 +64,7 @@
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/mount.h>
+#include <sys/fstrans.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
@@ -1957,12 +1958,13 @@
}
return (0);
}
+ localfs = fromnd.ni_dvp->v_mount;
+ fstrans_start(localfs);
if (fromnd.ni_dvp != fromnd.ni_vp) {
VOP_UNLOCK(fromnd.ni_dvp);
}
fvp = fromnd.ni_vp;
- localfs = fvp->v_mount;
error = VFS_RENAMELOCK_ENTER(localfs);
if (error) {
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
@@ -2130,6 +2132,7 @@
pathbuf_destroy(fromnd.ni_pathbuf);
fromnd.ni_pathbuf = NULL;
fromnd.ni_cnd.cn_nameiop = 0;
+ fstrans_done(localfs);
localfs = NULL;
nfsm_reply(2 * NFSX_WCCDATA(v3));
if (v3) {
@@ -2153,6 +2156,7 @@
}
if (localfs) {
VFS_RENAMELOCK_EXIT(localfs);
+ fstrans_done(localfs);
}
if (fromnd.ni_cnd.cn_nameiop) {
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
Home |
Main Index |
Thread Index |
Old Index