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 --- 5,11 ---- */ #if !defined(lint) && defined(DOSCCS) ! static char sccsid[] = "@(#)dir.c 5.1.1 (2.11BSD) 1996/5/8"; #endif not lint #include *************** *** 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 --- 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 *************** *** 18,40 **** #include #include #include - #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 #include #include + #include + #include #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 ============