*BSD News Article 70455


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.EDU.AU!munnari.OZ.AU!news.hawaii.edu!news.uoregon.edu!vixen.cso.uiuc.edu!newsfeed.internetmci.com!salliemae!europa.chnt.gtegsc.com!wlbr!moe!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: TMSCP bug, standalone xon/xoff, tcopy errors, fsck strings (#323)
Archive-Name: comp.bugs.2bsd
Organization: 2BSD, Simi Valley CA USA
Message-ID: <Dso2xr.EAF@moe.2bsd.com>
Date: Sat, 8 Jun 1996 05:51:26 GMT
Lines: 658

Subject: TMSCP bug, standalone xon/xoff, tcopy errors, fsck strings (#323)
Index: pdpuba/tmscp.c,pdpstand/prf.c,ucb/tcopy.c,etc/fsck/Makefile,dir.c 2.11BSD

Description:
	1. Multiple TMSCP drives in a system were not being handled correctly.  

	2. The standalone disklabel program's output would become scrambled
	if the console device needed to use XON/XOFF.

	3. If tcopy(1) encountered any form of error it would simply print
	"write error" or something equally informative.  No indication was
	giving as to the exact error returned from the kernel.

	4. Fsck(8) had multiple repeated strings scattered thruout causing
	almost 1kb of data space to be wasted.

Repeat-By:
	1.  mt -f /dev/rmt0 rew; mt -f /dev/rmt8 rew
	    An error ('busy') will be returned for the second command.

	2.  Have an LA120 or similar device as the system console and running
	    at 9600 baud.  Run a standalone utility which produces copious 
	    output and note that the printout becomes scrambled.

	3.  Copy a tape with 'tcopy /dev/rmt0 /dev/rmt88' and encounter a
	    error on the output tape.  Note that 'write error, tcopy aborted'
	    is the only information printed out with no indication what error
	    occured.

	4.  Run strings on /etc/fsck ('strings /etc/fsck') and notice that
	    there are repeated instances of the various messages (such as
	    "DIRECTORY %s: LENGTH %ld NOT MULTIPLE of %d") present.

Fix:
	1. It is likely that this bug was introduced during the rewrite of
	   the TMSCP driver to support the TU81+ cache.  It is possible (but
	   somewhat less likely) this is a latent bug that just showed up a
	   couple days ago.  Essentially the 'inuse' bit was being cleared
	   when the drive was close BUT the controller structure still had a
	   reference to the drive.  The system would end up with the same
	   drive assigned to two different controllers.  Ick.

	2. Several of the screens/menus in the standalone disklabel program 
	   produced sufficient output to overrun a hardcopy console device.

	   Thanks to Tim Shoppa for contributing a rudimentary xon/xoff
	   mechanism for the standalone I/O system.  The only drawback
	   (unlikely to be a problem though) is that input from the keyboard
	   is ignored while waiting for the console device to issue the 'xon'.

	3. In the process of trying to fix problem #1 I ran into tcopy's
	   overquiet nature - errors were obviously being encountered by tcopy
	   but the exact error code was not being reported.  The err(3) and
	   strerror(3) routines were used to improve tcopy's error reporting.
	   Record sizes need to be printed using '%u' instead of '%d' in order
	   to handle 32kb records (32768 prints as -32768).

	4. Fsck needs every bit of memory it can get for bitmaps, etc.  No
	   sense wasting D space on repeated strings.  Yes it would be nice
	   if the compiler could collapse shared strings but that still would
	   not obviate the need for xstr(1) because xstr collects shared strings
	   from an entire collection of modules.    One minor change was needed
	   in dir.c for the initialization of a static structure (something
	   xstr can not handle).   Other than that the only change was to the
	   Makefile.

	To install this update: cut where indicated, saving to a file (/tmp/323)
	and then:

		patch -p0 < /tmp/323
		cd /usr/src/ucb
		make tcopy
		install -m 755 -s tcopy /usr/ucb/tcopy

		cd /usr/src/etc/fsck
		make
		install -m 755 -s fsck /etc/fsck
		make clean

		cd /sys/pdpstand
		make
		cp boot /boot

	If you have boot tapes or other standalone boot media around you may
	want to update them with the new standalone utilities at this time.

		cd /sys/GENERIC
		make
		mv unix /genunix

	If you have TMSCP devices present then you will want to recompile
	the current kernel:

		cd /sys/YOUR_KERNEL
		make
		make install
		reboot

	This and previous updates are available via anonymous FTP to either
	FTP.IIPO.GTEGSC.COM or FTP.2BSD.COM in the directory /pub/2.11BSD.

=============================cut here=========================
*** /usr/src/sys/pdpuba/tmscp.c.old	Fri May 17 22:36:05 1996
--- /usr/src/sys/pdpuba/tmscp.c	Wed Jun  5 20:33:45 1996
***************
*** 1,6 ****
  #define	TMSDEBUG	1
  
! /*	@(#)tmscp.c	1.7 (2.11BSD GTE) 1996/5/17 */
  
  #if	!defined(lint) && defined(DOSCCS)
  static	char	*sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86";
--- 1,6 ----
  #define	TMSDEBUG	1
  
! /*	@(#)tmscp.c	1.8 (2.11BSD GTE) 1996/6/5 */
  
  #if	!defined(lint) && defined(DOSCCS)
  static	char	*sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86";
***************
*** 244,250 ****
  	memaddr	tmscp[NTMSCP];		/* click addresses of ctrl comm area */
  
  /*
!  * Bit definitions for Tflags word above.  These take the place of several
   * individual structure members in tms_info.
  */
  
--- 244,250 ----
  	memaddr	tmscp[NTMSCP];		/* click addresses of ctrl comm area */
  
  /*
!  * Tflags definitions.  These take the place of several
   * individual structure members in tms_info.
  */
  
***************
*** 356,372 ****
  
  struct tms_info *
  getdd()
! {
! 	register int i;
  	register struct tms_info *p;
  
! 	for (i = NTMS, p = tms_info; i--; p++) {
! 		if ((p->Tflags & _INUSE) == 0)
  			return(p);
! 	}
  	log(LOG_INFO, "tms: !drives\n");
  	return(NULL);
! }
  
  static int
  wait_step(mask, good, csr, sc)
--- 356,380 ----
  
  struct tms_info *
  getdd()
! 	{
  	register struct tms_info *p;
  
! 	for	(p = tms_info; p < &tms_info[NTMS]; p++)
! 		{
! 		if	(p->tms_type == 0)
! 			{
! /*
!  * Set the type with a placeholder value - we may have to sleep waiting for
!  * the drive to come on line and we don't want this slot to be grabbed again.
!  * The online response will load the real drive type.
! */
! 			p->tms_type = 1;	/* XXX */
  			return(p);
! 			}
! 		}
  	log(LOG_INFO, "tms: !drives\n");
  	return(NULL);
! 	}
  
  static int
  wait_step(mask, good, csr, sc)
***************
*** 578,587 ****
  		tms = getdd();
  		if (!tms)
  			return(ENXIO);
! 		tms->Tflags &= ~_ONLINE;
  		sc->sc_drives[unit] = tms;
  	}
! 	if	(tms->Tflags & _INUSE)
  		return(EBUSY);
  	tms->Tflags |= _INUSE;
  
--- 586,595 ----
  		tms = getdd();
  		if (!tms)
  			return(ENXIO);
! 		tms->Tflags = 0;
  		sc->sc_drives[unit] = tms;
  	}
! 	else if	(tms->Tflags & _INUSE)
  		return(EBUSY);
  	tms->Tflags |= _INUSE;
  
***************
*** 592,597 ****
--- 600,608 ----
  			if	(!tkini(sc))
  				{
  				log(LOG_INFO, "tms%d init fail\n", ctlr);
+ 				sc->sc_drives[unit] = NULL;
+ 				tms->Tflags = 0;
+ 				tms->tms_type = 0;
  				(void) splx(s);
  				return(ENXIO);
  				}
***************
*** 603,609 ****
  		if	(sc->sc_state != S_RUN)
  			{
  			sc->sc_drives[unit] = NULL;
! 			tms->Tflags &= ~(_INUSE | _ONLINE);
  			(void) splx(s);
  			return(EIO);
  			}
--- 614,621 ----
  		if	(sc->sc_state != S_RUN)
  			{
  			sc->sc_drives[unit] = NULL;
! 			tms->Tflags = 0;
! 			tms->tms_type = 0;
  			(void) splx(s);
  			return(EIO);
  			}
***************
*** 647,652 ****
--- 659,665 ----
  	if	(!(tms->Tflags & _ONLINE))
  		{
  oops:		tms->Tflags = 0;
+ 		tms->tms_type = 0;
  		sc->sc_drives[unit] = NULL;
  		return(ENXIO);  /* Didn't go online */
  		}
***************
*** 717,723 ****
  	tms->tms_flags &= ~MTF_CSE;
  	if	(tms->Tflags & _WRITTEN)
  		tms_wrteof(dev, tms);
! 	tms->Tflags &= ~(_WRITTEN | _BUFMARK |_INUSE);
  	if	((dev & T_NOREWIND) == 0)
  		{
  		tmscpcommand(dev, TMS_REW, 0);
--- 730,736 ----
  	tms->tms_flags &= ~MTF_CSE;
  	if	(tms->Tflags & _WRITTEN)
  		tms_wrteof(dev, tms);
! 	tms->Tflags &= ~(_WRITTEN | _BUFMARK | _INUSE);
  	if	((dev & T_NOREWIND) == 0)
  		{
  		tmscpcommand(dev, TMS_REW, 0);
*** /usr/src/sys/pdpstand/prf.c.old	Sun Jun  4 12:02:42 1995
--- /usr/src/sys/pdpstand/prf.c	Tue Jun  4 22:32:48 1996
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)prf.c	1.3 (2.11BSD) 1995/06/04
   */
  
  #include "../machine/cons.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)prf.c	1.4 (2.11BSD) 1996/06/04
   */
  
  #include "../machine/cons.h"
***************
*** 80,90 ****
  	if ((KLADDR->dlrbuf & 0177) == 0)
  		return;
  #endif
- 	timo = 60000;
  	/*
  	 * Try waiting for the console tty to come ready,
  	 * otherwise give up after a reasonable time.
  	 */
  	while ((KLADDR->dlxcsr & DLXCSR_TRDY) == 0)
  		if (--timo == 0)
  			break;
--- 80,97 ----
  	if ((KLADDR->dlrbuf & 0177) == 0)
  		return;
  #endif
  	/*
+          *  If we got a XOFF, wait for a XON
+          */
+ 	if ((KLADDR->dlrcsr & DL_RDONE) != 0)
+ 		if ((KLADDR->dlrbuf & 0177) == 19)
+ 			while ((KLADDR->dlrbuf & 0177) != 17) 
+ 				continue;
+ 	/*
  	 * Try waiting for the console tty to come ready,
  	 * otherwise give up after a reasonable time.
  	 */
+ 	timo=60000;
  	while ((KLADDR->dlxcsr & DLXCSR_TRDY) == 0)
  		if (--timo == 0)
  			break;
*** /usr/src/etc/fsck/Makefile.old	Fri Apr 20 09:33:41 1990
--- /usr/src/etc/fsck/Makefile	Wed May  8 22:06:07 1996
***************
*** 3,13 ****
  # All rights reserved.  The Berkeley software License Agreement
  # specifies the terms and conditions for redistribution.
  #
! #	@(#)Makefile	5.8 (Berkeley) 9/7/85
  #
  DESTDIR=
  CFLAGS=	-O
  LFLAGS=	-i
  
  # The program itself
  #
--- 3,14 ----
  # All rights reserved.  The Berkeley software License Agreement
  # specifies the terms and conditions for redistribution.
  #
! #	@(#)Makefile	5.8.1 (2.11BSD) 1996/5/8
  #
  DESTDIR=
  CFLAGS=	-O
  LFLAGS=	-i
+ XSTR=	/usr/ucb/xstr
  
  # The program itself
  #
***************
*** 28,44 ****
  #
  HDRS=	fsck.h
  
! ${PROG}: ${OBJS} ${HDRS}
! 	cc ${LFLAGS} -o ${PROG} ${OBJS}
  
! ${LOCOBJS}:
! 	cc ${CFLAGS} -c $*.c
  
  install: ${PROG}
  	install -s ${PROG} ${DESTDIR}/etc/${PROG}
  
  clean:
! 	rm -f a.out core ${OBJS} ${PROG}
  
  lint:
  	lint ${INCPATH} ${SRCS}
--- 29,54 ----
  #
  HDRS=	fsck.h
  
! ${PROG}: ${OBJS} ${HDRS} strings.o
! 	cc ${LFLAGS} -o ${PROG} ${OBJS} strings.o
  
! .c.o:
! 	cc -E ${CFLAGS} $*.c | ${XSTR} -c -
! 	cc ${CFLAGS} -c x.c
! 	mv -f x.o $*.o
! 	rm -f x.c
  
+ strings.o: strings
+ 	${XSTR}
+ 	cc -c xs.c
+ 	mv -f xs.o strings.o
+ 	rm -f xs.c
+ 
  install: ${PROG}
  	install -s ${PROG} ${DESTDIR}/etc/${PROG}
  
  clean:
! 	rm -f a.out core ${OBJS} ${PROG} strings.o x.c xs.c strings
  
  lint:
  	lint ${INCPATH} ${SRCS}
*** /usr/src/etc/fsck/dir.c.old	Sat Sep 15 20:16:11 1990
--- /usr/src/etc/fsck/dir.c	Wed May  8 21:54:45 1996
***************
*** 5,11 ****
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)dir.c	5.1 (Berkeley) 6/5/85";
  #endif not lint
  
  #include <sys/param.h>
--- 5,11 ----
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)dir.c	5.1.1 (2.11BSD) 1996/5/8";
  #endif not lint
  
  #include <sys/param.h>
***************
*** 19,25 ****
  char	*endpathname = &pathname[MAXPATHLEN - 2];
  char	*lfname = "lost+found";
  struct	dirtemplate emptydir = { 0, DIRBLKSIZ };
! struct	dirtemplate dirhead = { 0, 8, 1, ".", 0, DIRBLKSIZ - 8, 2, ".." };
  
  DIRECT	*fsck_readdir();
  
--- 19,32 ----
  char	*endpathname = &pathname[MAXPATHLEN - 2];
  char	*lfname = "lost+found";
  struct	dirtemplate emptydir = { 0, DIRBLKSIZ };
! /*
!  * The strange initialization is due to quoted strings causing problems when
!  * 'xstr' is used to preprocess the sources.  The structure has two members
!  * as 'char dot_name[2]' and 'char dotdot_name[6]' which is NOT the same as
!  * 'char *'.
! */
! struct	dirtemplate dirhead = { 0, 8, 1, {'.'}, 0, DIRBLKSIZ - 8, 2, 
! 				{'.', '.' }};
  
  DIRECT	*fsck_readdir();
  
***************
*** 322,329 ****
  			}
  		}
  		if (lfdir == 0) {
! 			pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
! 			printf("\n\n");
  			return (0);
  		}
  	}
--- 329,335 ----
  			}
  		}
  		if (lfdir == 0) {
! 			pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
  			return (0);
  		}
  	}
*** /usr/src/ucb/tcopy.c.old	Sat Jan  1 02:14:53 1994
--- /usr/src/ucb/tcopy.c	Fri Jun  7 20:14:18 1996
***************
*** 9,15 ****
  "@(#) Copyright (c) 1985 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)tcopy.c	1.3 (2.11BSD GTE) 1/1/94";
  #endif
  
  #include <stdio.h>
--- 9,15 ----
  "@(#) Copyright (c) 1985 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)tcopy.c	1.4 (2.11BSD GTE) 1996/6/4";
  #endif
  
  #include <stdio.h>
***************
*** 18,40 ****
  #include <sys/types.h>
  #include <sys/ioctl.h>
  #include <sys/mtio.h>
  
- #ifdef pdp11
  #define SIZE	((unsigned)32 * 1024)
- #else
- #define SIZE	(64 * 1024)
- #endif
  
  char buff[SIZE];
  int filen=1;
  long count, lcount;
  int RUBOUT();
- long itol();
  int nfile;
  long size, tsize;
  int ln;
  char *inf, *outf;
  int copy;
  
  main(argc, argv)
  char **argv;
--- 18,39 ----
  #include <sys/types.h>
  #include <sys/ioctl.h>
  #include <sys/mtio.h>
+ #include <string.h>
+ #include <errno.h>
  
  #define SIZE	((unsigned)32 * 1024)
  
  char buff[SIZE];
  int filen=1;
  long count, lcount;
  int RUBOUT();
  int nfile;
  long size, tsize;
  int ln;
  char *inf, *outf;
  int copy;
+ static char *msg1= "file %d: records %ld to %ld: size %u\n";
+ static char *msg2 = "file %d: record %ld: size %u\n";
  
  main(argc, argv)
  char **argv;
***************
*** 51,65 ****
  		outf = argv[2];
  		copy = 1;
  	}
! 	if ((inp=open(inf, O_RDONLY, 0666)) < 0) {
! 		fprintf(stderr,"Can't open %s\n", inf);
! 		exit(1);
! 	}
  	if (copy) {
! 		if ((outp=open(outf, O_WRONLY, 0666)) < 0) {
! 			fprintf(stderr,"Can't open %s\n", outf);
! 			exit(3);
! 		}
  	}
  	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  		(void) signal(SIGINT, RUBOUT);
--- 50,61 ----
  		outf = argv[2];
  		copy = 1;
  	}
! 	if ((inp=open(inf, O_RDONLY, 0666)) < 0)
! 		err(1, "Can't open %s", inf);
! 
  	if (copy) {
! 		if ((outp=open(outf, O_WRONLY, 0666)) < 0)
! 			err(3, "Can't open %s", outf);
  	}
  	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  		(void) signal(SIGINT, RUBOUT);
***************
*** 71,79 ****
  		    nw = write(outp, buff, n);
  		    if (copy) {
  			    if (nw != n) {
! 				fprintf(stderr, "write (%d) != read (%d)\n",
! 					nw, n);
! 				fprintf(stderr, "COPY Aborted\n");
  				exit(5);
  			    }
  		    }
--- 67,83 ----
  		    nw = write(outp, buff, n);
  		    if (copy) {
  			    if (nw != n) {
! 				int error = errno;
! 				if (nw == -1)
! 					fprintf(stderr, "write error, file %d, record %ld: ",
! 						filen, lcount);
! 				if (nw == -1)
! 					fprintf(stderr, "%s",strerror(error));
! 				else
! 					fprintf(stderr,
! 						"write (%u) != read (%u)\n",
! 						nw, n);
! 				fprintf(stderr, "copy aborted\n");
  				exit(5);
  			    }
  		    }
***************
*** 81,91 ****
  		    if (n != ln) {
  			if (ln > 0)
  			    if (count - lcount > 1)
! 				printf("file %d: records %ld to %ld: size %d\n",
! 					filen, lcount, count-1, ln);
  			    else
! 				printf("file %d: record %ld: size %d\n",
! 					filen, lcount, ln);
  			ln = n;
  			lcount = count;
  		    }
--- 85,93 ----
  		    if (n != ln) {
  			if (ln > 0)
  			    if (count - lcount > 1)
! 				printf(msg1, filen, lcount, count-1, ln);
  			    else
! 				printf(msg2, filen, lcount, ln);
  			ln = n;
  			lcount = count;
  		    }
***************
*** 97,107 ****
  			}
  			if (ln > 0)
  			    if (count - lcount > 1)
! 				printf("file %d: records %ld to %ld: size %d\n",
! 					filen, lcount, count-1, ln);
  			    else
! 				printf("file %d: record %ld: size %d\n",
! 					filen, lcount, ln);
  			printf("file %d: eof after %ld records: %ld bytes\n",
  				filen, count-1, size);
  			if (copy) {
--- 99,107 ----
  			}
  			if (ln > 0)
  			    if (count - lcount > 1)
! 				printf(msg1, filen, lcount, count-1, ln);
  			    else
! 				printf(msg2, filen, lcount, ln);
  			printf("file %d: eof after %ld records: %ld bytes\n",
  				filen, count-1, size);
  			if (copy) {
***************
*** 133,145 ****
  		--count;
  	if (count)
  		if (count > lcount)
! 			printf("file %d: records %ld to %ld: size %d\n",
! 				filen, lcount, count, ln);
  		else
! 			printf("file %d: record %ld: size %d\n",
! 				filen, lcount, ln);
  	printf("rubout at file %d: record %ld\n", filen, count);
  	printf("total length: %ld bytes\n", tsize+size);
  	exit(1);
  }
- 
--- 133,142 ----
  		--count;
  	if (count)
  		if (count > lcount)
! 			printf(msg1, filen, lcount, count, ln);
  		else
! 			printf(msg2, filen, lcount, ln);
  	printf("rubout at file %d: record %ld\n", filen, count);
  	printf("total length: %ld bytes\n", tsize+size);
  	exit(1);
  }
*** /VERSION.old	Fri May 24 22:05:47 1996
--- /VERSION	Fri Jun  7 19:57:45 1996
***************
*** 1,4 ****
! Current Patch Level: 322
  
  2.11 BSD
  ============
--- 1,4 ----
! Current Patch Level: 323
  
  2.11 BSD
  ============