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