X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1db7a2252e6ca0e5e2c114aef6a2293d47e40c4d..fbe2138c7e7593fbf68001b27b1e0613abae14a3:/usr/src/sbin/dump/tape.c diff --git a/usr/src/sbin/dump/tape.c b/usr/src/sbin/dump/tape.c index 090485d811..129fb369a9 100644 --- a/usr/src/sbin/dump/tape.c +++ b/usr/src/sbin/dump/tape.c @@ -1,15 +1,28 @@ -/* - * Copyright (c) 1980 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% */ #ifndef lint -static char sccsid[] = "@(#)tape.c 5.11 (Berkeley) %G%"; -#endif not lint - -#include +static char sccsid[] = "@(#)tape.c 5.18 (Berkeley) %G%"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include #include +#include +#include +#ifdef __STDC__ +#include +#include +#include +#endif #include "dump.h" #include "pathnames.h" @@ -17,19 +30,26 @@ char (*tblock)[TP_BSIZE]; /* pointer to malloc()ed buffer for tape */ int writesize; /* size of malloc()ed buffer for tape */ long lastspclrec = -1; /* tape block number of last written header */ int trecno = 0; /* next record to write in current block */ -extern int ntrec; /* blocking factor on tape */ -extern int cartridge; -extern int read(), write(); +extern long blocksperfile; /* number of blocks per output file */ +long blocksthisvol; /* number of blocks on current output file */ +extern int ntrec; /* blocking factor on tape */ +extern int cartridge; +char *nexttape; #ifdef RDUMP extern char *host; +int rmtopen(), rmtwrite(); +void rmtclose(); #endif RDUMP +int atomic(); +void doslave(), enslave(), flushtape(), killall(); + /* * Concurrent dump mods (Caltech) - disk block reading and tape writing * are exported to several slave processes. While one slave writes the * tape, the others read disk blocks; they pass control of the tape in * a ring via flock(). The parent process traverses the filesystem and - * sends spclrec()'s and lists of daddr's to the slaves via pipes. + * sends writeheader()'s and lists of daddr's to the slaves via pipes. */ struct req { /* instruction packets sent to slaves */ daddr_t dblk; @@ -44,6 +64,7 @@ int rotor; /* next slave to be instructed */ int master; /* pid of master, for sending error signals */ int tenths; /* length of tape used per block written */ +int alloctape() { int pgoff = getpagesize() - 1; @@ -56,10 +77,12 @@ alloctape() * repositioning after stopping, i.e, streaming mode, where the gap is * variable, 0.30" to 0.45". The gap is maximal when the tape stops. */ - tenths = writesize/density + (cartridge ? 16 : density == 625 ? 5 : 8); + if (blocksperfile == 0) + tenths = writesize / density + + (cartridge ? 16 : density == 625 ? 5 : 8); /* * Allocate tape buffer contiguous with the array of instruction - * packets, so flusht() can write them together with one write(). + * packets, so flushtape() can write them together with one write(). * Align tape buffer on page boundary to speed up tape write(). */ req = (struct req *)malloc(reqsiz + writesize + pgoff); @@ -71,7 +94,8 @@ alloctape() } -taprec(dp) +void +writerec(dp) char *dp; { req[trecno].dblk = (daddr_t)0; @@ -80,45 +104,46 @@ taprec(dp) lastspclrec = spcl.c_tapea; trecno++; spcl.c_tapea++; - if(trecno >= ntrec) - flusht(); + if (trecno >= ntrec) + flushtape(); } -dmpblk(blkno, size) +void +dumpblock(blkno, size) daddr_t blkno; int size; { int avail, tpblks, dblkno; dblkno = fsbtodb(sblock, blkno); - tpblks = size / TP_BSIZE; + tpblks = size >> tp_bshift; while ((avail = MIN(tpblks, ntrec - trecno)) > 0) { req[trecno].dblk = dblkno; req[trecno].count = avail; trecno += avail; spcl.c_tapea += avail; if (trecno >= ntrec) - flusht(); - dblkno += avail * (TP_BSIZE / dev_bsize); + flushtape(); + dblkno += avail << (tp_bshift - dev_bshift); tpblks -= avail; } } int nogripe = 0; -tperror() { +void +tperror() +{ if (pipeout) { - msg("Tape write error on %s\n", tape); - msg("Cannot recover\n"); - dumpabort(); + msg("write error on %s\n", tape); + quit("Cannot recover\n"); /* NOTREACHED */ } - msg("Tape write error %d feet into tape %d\n", asize/120L, tapeno); - broadcast("TAPE ERROR!\n"); + msg("write error %d blocks into volume %d\n", blocksthisvol, tapeno); + broadcast("DUMP WRITE ERROR!\n"); if (!query("Do you want to restart?")) dumpabort(); - msg("This tape will rewind. After it is rewound,\n"); - msg("replace the faulty tape with a new one;\n"); + msg("Closing this volume. Prepare to restart with new media;\n"); msg("this dump volume will be rewritten.\n"); killall(); nogripe = 1; @@ -126,46 +151,40 @@ tperror() { Exit(X_REWRITE); } +void sigpipe() { - msg("Broken pipe\n"); - dumpabort(); + quit("Broken pipe\n"); } -#ifdef RDUMP -/* - * compatibility routine - */ -tflush(i) - int i; +void +flushtape() { +#ifndef __STDC__ + int write(); +#endif - for (i = 0; i < ntrec; i++) - spclrec(); -} -#endif RDUMP - -flusht() -{ int siz = (char *)tblock - (char *)req; - if (atomic(write, slavefd[rotor], req, siz) != siz) { - perror(" DUMP: error writing command pipe"); - dumpabort(); - } - if (++rotor >= SLAVES) rotor = 0; + if (atomic(write, slavefd[rotor], req, siz) != siz) + quit("error writing command pipe: %s\n", strerror(errno)); + if (++rotor >= SLAVES) + rotor = 0; tblock = (char (*)[TP_BSIZE]) &req[ntrec]; trecno = 0; asize += tenths; blockswritten += ntrec; - if (!pipeout && asize > tsize) { + blocksthisvol += ntrec; + if (!pipeout && (blocksperfile ? + (blocksthisvol >= blocksperfile) : (asize > tsize))) { close_rewind(); - otape(); + startnewtape(); } timeest(); } +void trewind() { int f; @@ -174,8 +193,9 @@ trewind() return; for (f = 0; f < SLAVES; f++) close(slavefd[f]); - while (wait(NULL) >= 0) ; /* wait for any signals from slaves */ - msg("Tape rewinding\n"); + while (wait((int *)NULL) >= 0) /* wait for any signals from slaves */ + /* void */; + msg("Closing %s\n", tape); #ifdef RDUMP if (host) { rmtclose(); @@ -185,20 +205,23 @@ trewind() return; } #endif RDUMP - close(to); + close(tapefd); while ((f = open(tape, 0)) < 0) sleep (10); close(f); } +void close_rewind() { trewind(); + if (nexttape) + return; if (!nogripe) { - msg("Change Tapes: Mount tape #%d\n", tapeno+1); - broadcast("CHANGE TAPES!\7\7\n"); + msg("Change Volumes: Mount volume #%d\n", tapeno+1); + broadcast("CHANGE DUMP VOLUMES!\7\7\n"); } - while (!query("Is the new tape mounted and ready to go?")) + while (!query("Is the new volume mounted and ready to go?")) if (query("Do you want to abort?")) { dumpabort(); /*NOTREACHED*/ @@ -215,7 +238,8 @@ close_rewind() * everything continues as if nothing had happened. */ -otape() +void +startnewtape() { int parentpid; int childpid; @@ -223,6 +247,7 @@ otape() int waitpid; sig_t interrupt; int blks, i; + char *p; interrupt = signal(SIGINT, SIG_IGN); parentpid = getpid(); @@ -292,14 +317,31 @@ otape() msg("Child on Tape %d has parent %d, my pid = %d\n", tapeno+1, parentpid, getpid()); #endif TDEBUG + /* + * If we have a name like "/dev/rmt0,/dev/rmt1", + * use the name before the comma first, and save + * the remaining names for subsequent volumes. + */ + tapeno++; /* current tape sequence */ + if (nexttape || index(tape, ',')) { + if (nexttape && *nexttape) + tape = nexttape; + if (p = index(tape, ',')) { + *p = '\0'; + nexttape = p + 1; + } else + nexttape = NULL; + msg("Dumping volume %d on %s\n", tapeno, tape); + } #ifdef RDUMP - while ((to = (host ? rmtopen(tape, 2) : - pipeout ? 1 : creat(tape, 0666))) < 0) + while ((tapefd = (host ? rmtopen(tape, 2) : + pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else RDUMP - while ((to = pipeout ? 1 : creat(tape, 0666)) < 0) + while ((tapefd = + pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666)) < 0) #endif RDUMP { - msg("Cannot open tape \"%s\".\n", tape); + msg("Cannot open output \"%s\".\n", tape); if (!query("Do you want to retry the open?")) dumpabort(); } @@ -307,7 +349,7 @@ otape() enslave(); /* Share open tape file descriptor with slaves */ asize = 0; - tapeno++; /* current tape sequence */ + blocksthisvol = 0; newtape++; /* new tape signal */ blks = 0; if (spcl.c_type != TS_END) @@ -318,14 +360,15 @@ otape() spcl.c_volume++; spcl.c_type = TS_TAPE; spcl.c_flags |= DR_NEWHEADER; - spclrec(); + writeheader(curino); spcl.c_flags &=~ DR_NEWHEADER; if (tapeno > 1) - msg("Tape %d begins with blocks from ino %d\n", - tapeno, ino); + msg("Volume %d begins with blocks from inode %d\n", + tapeno, curino); } } +void dumpabort() { if (master != 0 && master != getpid()) @@ -337,6 +380,7 @@ dumpabort() Exit(X_ABORT); } +void Exit(status) int status; { @@ -349,6 +393,7 @@ Exit(status) /* * could use pipe() for this if flock() worked on pipes */ +void lockfile(fd) int fd[2]; { @@ -356,19 +401,16 @@ lockfile(fd) strcpy(tmpname, _PATH_LOCK); mktemp(tmpname); - if ((fd[1] = creat(tmpname, 0400)) < 0) { - msg("Could not create lockfile "); - perror(tmpname); - dumpabort(); - } - if ((fd[0] = open(tmpname, 0)) < 0) { - msg("Could not reopen lockfile "); - perror(tmpname); - dumpabort(); - } - unlink(tmpname); + if ((fd[1] = creat(tmpname, 0400)) < 0) + quit("cannot create lockfile %s: %s\n", + tmpname, strerror(errno)); + if ((fd[0] = open(tmpname, 0)) < 0) + quit("cannot reopen lockfile %s: %s\n", + tmpname, strerror(errno)); + (void) unlink(tmpname); } +void enslave() { int first[2], prev[2], next[2], cmd[2]; /* file descriptors */ @@ -394,11 +436,9 @@ enslave() next[0] = first[0]; next[1] = first[1]; /* Last slave loops back */ } - if (pipe(cmd) < 0 || (slavepid[i] = fork()) < 0) { - msg("too many slaves, %d (recompile smaller) ", i); - perror(""); - dumpabort(); - } + if (pipe(cmd) < 0 || (slavepid[i] = fork()) < 0) + quit("too many slaves, %d (recompile smaller): %s\n", + i, strerror(errno)); slavefd[i] = cmd[1]; if (slavepid[i] == 0) { /* Slave starts up here */ for (j = 0; j <= i; j++) @@ -418,6 +458,7 @@ enslave() master = 0; rotor = 0; } +void killall() { register int i; @@ -434,16 +475,22 @@ killall() * file, allowing the following process to lock it and proceed. We * get the lock back for the next cycle by swapping descriptors. */ +void doslave(cmd, prev, next) register int cmd, prev[2], next[2]; { register int nread, toggle = 0; + int nwrite; +#ifndef __STDC__ + int read(); +#endif - close(fi); - if ((fi = open(disk, 0)) < 0) { /* Need our own seek pointer */ - perror(" DUMP: slave couldn't reopen disk"); - dumpabort(); - } + /* + * Need our own seek pointer. + */ + close(diskfd); + if ((diskfd = open(disk, O_RDONLY)) < 0) + quit("slave couldn't reopen disk: %s\n", strerror(errno)); /* * Get list of blocks to dump, read the blocks into tape buffer */ @@ -455,20 +502,24 @@ doslave(cmd, prev, next) p->count * TP_BSIZE); } else { if (p->count != 1 || atomic(read, cmd, - tblock[trecno], TP_BSIZE) != TP_BSIZE) { - msg("Master/slave protocol botched.\n"); - dumpabort(); - } + tblock[trecno], TP_BSIZE) != TP_BSIZE) + quit("master/slave protocol botched.\n"); } } flock(prev[toggle], LOCK_EX); /* Wait our turn */ #ifdef RDUMP - if ((host ? rmtwrite(tblock[0], writesize) - : write(to, tblock[0], writesize)) != writesize) { + if ((nwrite = (host ? rmtwrite(tblock[0], writesize) + : write(tapefd, tblock[0], writesize))) != writesize) { #else RDUMP - if (write(to, tblock[0], writesize) != writesize) { + if ((nwrite = write(tapefd, tblock[0], writesize)) + != writesize) { #endif RDUMP + if (nwrite == -1) + perror("write"); + else + msg("short write: got %d instead of %d\n", + nwrite, writesize); kill(master, SIGUSR1); for (;;) sigpause(0); @@ -476,10 +527,8 @@ doslave(cmd, prev, next) toggle ^= 1; flock(next[toggle], LOCK_UN); /* Next slave's turn */ } /* Also jolts him awake */ - if (nread != 0) { - perror(" DUMP: error reading command pipe"); - dumpabort(); - } + if (nread != 0) + quit("error reading command pipe: %s\n", strerror(errno)); } /* @@ -487,6 +536,7 @@ doslave(cmd, prev, next) * or a write may not write all we ask if we get a signal, * loop until the count is satisfied (or error). */ +int atomic(func, fd, buf, count) int (*func)(), fd, count; char *buf;