Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Prevent deadlock cited in PR4629 from crashing the syste...
details: https://anonhg.NetBSD.org/src/rev/20db819824b4
branches: trunk
changeset: 467447:20db819824b4
user: sommerfe <sommerfe%NetBSD.org@localhost>
date: Thu Mar 25 00:20:35 1999 +0000
description:
Prevent deadlock cited in PR4629 from crashing the system. (copyout
and system call now just return EFAULT). A complete fix will
presumably have to wait for UBC and/or for vnode locking protocols to
be revamped to allow use of shared locks.
diffstat:
sys/kern/kern_lock.c | 11 ++++++++---
sys/kern/vfs_vnops.c | 14 +++++++++++---
sys/sys/lock.h | 7 ++++---
sys/uvm/uvm_vnode.c | 32 +++++++++++++++++++++++---------
4 files changed, 46 insertions(+), 18 deletions(-)
diffs (136 lines):
diff -r 1346ff3f90cd -r 20db819824b4 sys/kern/kern_lock.c
--- a/sys/kern/kern_lock.c Wed Mar 24 23:51:26 1999 +0000
+++ b/sys/kern/kern_lock.c Thu Mar 25 00:20:35 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_lock.c,v 1.15 1999/02/28 14:09:15 fvdl Exp $ */
+/* $NetBSD: kern_lock.c,v 1.16 1999/03/25 00:20:35 sommerfe Exp $ */
/*
* Copyright (c) 1995
@@ -320,8 +320,13 @@
* Recursive lock.
*/
if ((extflags & LK_CANRECURSE) == 0 &&
- lkp->lk_recurselevel == 0)
- panic("lockmgr: locking against myself");
+ lkp->lk_recurselevel == 0) {
+ if (extflags & LK_RECURSEFAIL) {
+ error = EDEADLK;
+ break;
+ } else
+ panic("lockmgr: locking against myself");
+ }
lkp->lk_exclusivecount++;
if (extflags & LK_SETRECURSE &&
lkp->lk_recurselevel == 0)
diff -r 1346ff3f90cd -r 20db819824b4 sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c Wed Mar 24 23:51:26 1999 +0000
+++ b/sys/kern/vfs_vnops.c Thu Mar 25 00:20:35 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_vnops.c,v 1.33 1999/03/24 05:51:26 mrg Exp $ */
+/* $NetBSD: vfs_vnops.c,v 1.34 1999/03/25 00:20:35 sommerfe Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -537,10 +537,13 @@
int flags;
{
int error;
-
+ int have_interlock = 0;
+
do {
- if ((flags & LK_INTERLOCK) == 0)
+ if ((flags & LK_INTERLOCK) == 0) {
simple_lock(&vp->v_interlock);
+ have_interlock++;
+ }
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
simple_unlock(&vp->v_interlock);
@@ -551,6 +554,11 @@
if (error == 0)
return (error);
}
+ if (error == EDEADLK) {
+ if (have_interlock)
+ simple_unlock(&vp->v_interlock);
+ break;
+ }
flags &= ~LK_INTERLOCK;
} while (flags & LK_RETRY);
return (error);
diff -r 1346ff3f90cd -r 20db819824b4 sys/sys/lock.h
--- a/sys/sys/lock.h Wed Mar 24 23:51:26 1999 +0000
+++ b/sys/sys/lock.h Thu Mar 25 00:20:35 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lock.h,v 1.16 1999/03/24 05:51:29 mrg Exp $ */
+/* $NetBSD: lock.h,v 1.17 1999/03/25 00:20:35 sommerfe Exp $ */
/*
* Copyright (c) 1995
@@ -136,12 +136,13 @@
* or passed in as arguments to the lock manager. The LK_REENABLE flag may be
* set only at the release of a lock obtained by drain.
*/
-#define LK_EXTFLG_MASK 0x00000170 /* mask of external flags */
+#define LK_EXTFLG_MASK 0x00300070 /* mask of external flags */
#define LK_NOWAIT 0x00000010 /* do not sleep to await lock */
#define LK_SLEEPFAIL 0x00000020 /* sleep, then return failure */
#define LK_CANRECURSE 0x00000040 /* this may be recursive lock attempt */
#define LK_REENABLE 0x00000080 /* lock is be reenabled after drain */
-#define LK_SETRECURSE 0x00000100 /* other locks while we have it OK */
+#define LK_SETRECURSE 0x00100000 /* other locks while we have it OK */
+#define LK_RECURSEFAIL 0x00200000 /* attempt at recursive lock fails */
/*
* Internal lock flags.
*
diff -r 1346ff3f90cd -r 20db819824b4 sys/uvm/uvm_vnode.c
--- a/sys/uvm/uvm_vnode.c Wed Mar 24 23:51:26 1999 +0000
+++ b/sys/uvm/uvm_vnode.c Thu Mar 25 00:20:35 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_vnode.c,v 1.20 1999/03/24 03:45:28 cgd Exp $ */
+/* $NetBSD: uvm_vnode.c,v 1.21 1999/03/25 00:20:35 sommerfe Exp $ */
/*
* XXXCDC: "ROUGH DRAFT" QUALITY UVM PRE-RELEASE FILE!
@@ -1700,17 +1700,31 @@
UVMHIST_LOG(maphist, "calling VOP",0,0,0,0);
+ /*
+ * This process may already have this vnode locked, if we faulted in
+ * copyin() or copyout() on a region backed by this vnode
+ * while doing I/O to the vnode. If this is the case, don't
+ * panic.. instead, return the error to the user.
+ *
+ * XXX this is a stopgap to prevent a panic.
+ * Ideally, this kind of operation *should* work.
+ */
+ result = 0;
if ((uvn->u_flags & UVM_VNODE_VNISLOCKED) == 0)
- vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
- /* NOTE: vnode now locked! */
+ result = vn_lock(vn, LK_EXCLUSIVE | LK_RETRY | LK_RECURSEFAIL);
- if (rw == UIO_READ)
- result = VOP_READ(vn, &uio, 0, curproc->p_ucred);
- else
- result = VOP_WRITE(vn, &uio, 0, curproc->p_ucred);
+ if (result == 0) {
+ /* NOTE: vnode now locked! */
- if ((uvn->u_flags & UVM_VNODE_VNISLOCKED) == 0)
- VOP_UNLOCK(vn, 0);
+ if (rw == UIO_READ)
+ result = VOP_READ(vn, &uio, 0, curproc->p_ucred);
+ else
+ result = VOP_WRITE(vn, &uio, 0, curproc->p_ucred);
+
+ if ((uvn->u_flags & UVM_VNODE_VNISLOCKED) == 0)
+ VOP_UNLOCK(vn, 0);
+ }
+
/* NOTE: vnode now unlocked (unless vnislocked) */
UVMHIST_LOG(maphist, "done calling VOP",0,0,0,0);
Home |
Main Index |
Thread Index |
Old Index