Subject: bug in wt.c
To: None <netbsd-bugs@NetBSD.ORG>
From: Jan van den Bosch <J.C.F.v.d.Bosch@urc.tue.nl>
List: netbsd-bugs
Date: 01/02/1995 22:40:11
There is a bug in the wt driver (/sys/arch/i386/isa/wt.c).
I also found a (possible) solution (one line of code). After 
applying it, the bug never ocuurred to me again. 
I also added one line of code to enable the mt programm to give 
information about the tape density.
There are still happening strange things if you are using tapes with
different densitys, but most of the time now good back-ups are possible.

Description:
The wt driver sometimes comes in a deadlock state (waiting for an 
wake-up event that never occurs). It sometimes happens when I did a long
remote backup. In that wait state, the tape unit keeps busy doing nothing,
the only way to get out of it was a complete system reboot (:-(...

Reason:
In the Interrupt routine wtintr() there is no provision for 
stopping the timeout() if all i/o (one block) is completed
(state 'i/o finished'). If an interrupt is generated at this moment,
it comes in an unexpected state ('continue i/o'). In this state -
wtwait()- , there is of course no wakeup, so it keeps sleeping eternaly..., 

Patch:
Allways put the timer off if i/o is finished.
Add one line before the last 3 lines of the function body
of wtintr(sc):
 	untimeout(wttimer, sc);


Patch: ----context diff, patch in /sys/arch/i386/isa directory:

*** wt.c	Fri Dec 23 22:43:52 1994
--- wt.c.orig	Tue Mar 29 12:30:00 1994
***************
*** 467,475 ****
  		((struct mtget*)addr)->mt_resid = 0;
  		((struct mtget*)addr)->mt_fileno = 0;		/* file */
  		((struct mtget*)addr)->mt_blkno = 0;		/* block */
- /* JVDB added 941223 , for mt command, to display density */
- 		((struct mtget*)addr)->mt_density = sc->dens; 	/* density */
- /**/
  		return 0;
  	case MTIOCTOP:
  		break;
--- 467,472 ----
***************
*** 488,503 ****
*** 683,692 ****
  	}
  	if (sc->dmacount > sc->dmatotal)	/* short last block */
  		sc->dmacount = sc->dmatotal;
- /* JVDB added 941223 , to prevent endless wtwait() */
- 	/* stop timer going-off */
- 	untimeout(wttimer, sc);
- /**/
  	/* Wake up user level. */
  	wakeup((caddr_t)sc);
  	DEBUG(("i/o finished, %d\n", sc->dmacount));
--- 680,685 ----


J.v.d.Bosch (rcjvdb@urc.tue.nl)