DragonFly bugs List (threaded) for 2007-07
DragonFly BSD
DragonFly bugs List (threaded) for 2007-07
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: [issue715] panic at shutdown using comconsole


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 2 Jul 2007 15:33:19 -0700 (PDT)

:Crash dump uploaded to leaf.
:
:I did try to narrow down when I do/don't see crash:
: - no crash from single user (boot -s)
: - I tried disabling services:
:   reboot after rename /etc/rc.conf & no nfs-mounts: still crash.
: - GENERIC do crash
:
:I did check /usr/src: no problem.
:(comparing to virgin checkout from primary cvs-src)
:
: -thomas

    Please try this patch and tell me if it fixes the crash problem.
    There is definitely a race in the code where blocking on the vnode
    lock can lead to a duplicate operation.

						-Matt

Index: tty_tty.c
===================================================================
RCS file: /cvs/src/sys/kern/tty_tty.c,v
retrieving revision 1.18
diff -u -p -r1.18 tty_tty.c
--- tty_tty.c	10 Sep 2006 01:26:39 -0000	1.18
+++ tty_tty.c	2 Jul 2007 22:32:29 -0000
@@ -84,17 +84,30 @@ 	struct vnode *ttyvp;
 	int error;
 
 	KKASSERT(p);
+again:
 	ttyvp = cttyvp(p);
 	if (ttyvp) {
 		if (ttyvp->v_flag & VCTTYISOPEN) {
 			error = 0;
 		} else {
-			vsetflags(ttyvp, VCTTYISOPEN);
+			vhold(ttyvp);
 			vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY);
+			/* 
+			 * We may have lost the tty while we were blocked
+			 * on the lock.
+			 */
+			if (cttyvp(p) != ttyvp || 
+			    (ttyvp->v_flag & VCTTYISOPEN)) {
+				vn_unlock(ttyvp);
+				vdrop(ttyvp);
+				goto again;
+			}
+			vsetflags(ttyvp, VCTTYISOPEN);
 			error = VOP_OPEN(ttyvp, FREAD|FWRITE, ap->a_cred, NULL);
 			if (error)
 				vclrflags(ttyvp, VCTTYISOPEN);
 			vn_unlock(ttyvp);
+			vdrop(ttyvp);
 		}
 	} else {
 		error = ENXIO;
@@ -115,6 +128,7 @@ 	struct vnode *ttyvp;
 	int error;
 
 	KKASSERT(p);
+again:
 	ttyvp = cttyvp(p);
 	if (ttyvp == NULL) {
 		/*
@@ -124,12 +138,24 @@ 		 */
 		/* error = EIO; */
 		error = 0;
 	} else if (ttyvp->v_flag & VCTTYISOPEN) {
-		vclrflags(ttyvp, VCTTYISOPEN);
+		vhold(ttyvp);
 		error = vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY);
 		if (error == 0) {
+			/* 
+			 * We may have lost the tty while we were blocked
+			 * on the lock.
+			 */
+			if (cttyvp(p) != ttyvp || 
+			    (ttyvp->v_flag & VCTTYISOPEN) == 0) {
+				vn_unlock(ttyvp);
+				vdrop(ttyvp);
+				goto again;
+			}
+			vclrflags(ttyvp, VCTTYISOPEN);
 			error = VOP_CLOSE(ttyvp, FREAD|FWRITE);
 			vn_unlock(ttyvp);
 		}
+		vdrop(ttyvp);
 	} else {
 		error = 0;
 	}



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]