BSD 4_3_Net_2 release
[unix-history] / usr / src / sbin / dump / dumptape.c
index e41b674..6a8144a 100644 (file)
@@ -1,14 +1,54 @@
-/*
- * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)dumptape.c 5.10 (Berkeley) 9/15/89";
-#endif not lint
-
-#include <sys/file.h>
+static char sccsid[] = "@(#)dumptape.c 5.18 (Berkeley) 4/24/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <ufs/dir.h>
+#include <ufs/dinode.h>
+#include <ufs/fs.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <protocols/dumprestore.h>
+#include <errno.h>
+#ifdef __STDC__
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
 #include "dump.h"
 #include "pathnames.h"
 
 #include "dump.h"
 #include "pathnames.h"
 
@@ -16,19 +56,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 */
 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;
 #ifdef RDUMP
 extern char *host;
+int    rmtopen(), rmtwrite();
+void   rmtclose();
 #endif RDUMP
 
 #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
 /*
  * 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;
  */
 struct req {                   /* instruction packets sent to slaves */
        daddr_t dblk;
@@ -43,6 +90,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 master;                    /* pid of master, for sending error signals */
 int tenths;                    /* length of tape used per block written */
 
+int
 alloctape()
 {
        int pgoff = getpagesize() - 1;
 alloctape()
 {
        int pgoff = getpagesize() - 1;
@@ -55,10 +103,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.
         */
         * 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
        /*
         * 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);
         * Align tape buffer on page boundary to speed up tape write().
         */
        req = (struct req *)malloc(reqsiz + writesize + pgoff);
@@ -70,7 +120,8 @@ alloctape()
 }
 
 
 }
 
 
-taprec(dp)
+void
+writerec(dp)
        char *dp;
 {
        req[trecno].dblk = (daddr_t)0;
        char *dp;
 {
        req[trecno].dblk = (daddr_t)0;
@@ -79,45 +130,46 @@ taprec(dp)
        lastspclrec = spcl.c_tapea;
        trecno++;
        spcl.c_tapea++;
        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);
        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)
        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;
 
                tpblks -= avail;
        }
 }
 
 int    nogripe = 0;
 
-tperror() {
+void
+tperror()
+{
        if (pipeout) {
        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 */
        }
                /* 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();
        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;
        msg("this dump volume will be rewritten.\n");
        killall();
        nogripe = 1;
@@ -125,47 +177,41 @@ tperror() {
        Exit(X_REWRITE);
 }
 
        Exit(X_REWRITE);
 }
 
+void
 sigpipe()
 {
 
 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;
 
        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;
        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();
                close_rewind();
-               otape();
+               startnewtape();
        }
        timeest();
 }
 
        }
        timeest();
 }
 
-rewind()
+void
+trewind()
 {
        int f;
 
 {
        int f;
 
@@ -173,8 +219,9 @@ rewind()
                return;
        for (f = 0; f < SLAVES; f++)
                close(slavefd[f]);
                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();
 #ifdef RDUMP
        if (host) {
                rmtclose();
@@ -184,20 +231,23 @@ rewind()
                return;
        }
 #endif RDUMP
                return;
        }
 #endif RDUMP
-       close(to);
+       close(tapefd);
        while ((f = open(tape, 0)) < 0)
                sleep (10);
        close(f);
 }
 
        while ((f = open(tape, 0)) < 0)
                sleep (10);
        close(f);
 }
 
+void
 close_rewind()
 {
 close_rewind()
 {
-       rewind();
+       trewind();
+       if (nexttape)
+               return;
        if (!nogripe) {
        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*/
                if (query("Do you want to abort?")) {
                        dumpabort();
                        /*NOTREACHED*/
@@ -214,7 +264,8 @@ close_rewind()
  *     everything continues as if nothing had happened.
  */
 
  *     everything continues as if nothing had happened.
  */
 
-otape()
+void
+startnewtape()
 {
        int     parentpid;
        int     childpid;
 {
        int     parentpid;
        int     childpid;
@@ -222,6 +273,7 @@ otape()
        int     waitpid;
        sig_t   interrupt;
        int     blks, i;
        int     waitpid;
        sig_t   interrupt;
        int     blks, i;
+       char    *p;
 
        interrupt = signal(SIGINT, SIG_IGN);
        parentpid = getpid();
 
        interrupt = signal(SIGINT, SIG_IGN);
        parentpid = getpid();
@@ -291,14 +343,31 @@ otape()
                msg("Child on Tape %d has parent %d, my pid = %d\n",
                        tapeno+1, parentpid, getpid());
 #endif TDEBUG
                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
 #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
 #else RDUMP
-               while ((to = pipeout ? 1 : creat(tape, 0666)) < 0)
+               while ((tapefd =
+                       pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666)) < 0)
 #endif RDUMP
                    {
 #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();
                }
                        if (!query("Do you want to retry the open?"))
                                dumpabort();
                }
@@ -306,7 +375,7 @@ otape()
                enslave();  /* Share open tape file descriptor with slaves */
 
                asize = 0;
                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)
                newtape++;              /* new tape signal */
                blks = 0;
                if (spcl.c_type != TS_END)
@@ -317,14 +386,15 @@ otape()
                spcl.c_volume++;
                spcl.c_type = TS_TAPE;
                spcl.c_flags |= DR_NEWHEADER;
                spcl.c_volume++;
                spcl.c_type = TS_TAPE;
                spcl.c_flags |= DR_NEWHEADER;
-               spclrec();
+               writeheader(curino);
                spcl.c_flags &=~ DR_NEWHEADER;
                if (tapeno > 1)
                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())
 dumpabort()
 {
        if (master != 0 && master != getpid())
@@ -336,7 +406,9 @@ dumpabort()
        Exit(X_ABORT);
 }
 
        Exit(X_ABORT);
 }
 
+void
 Exit(status)
 Exit(status)
+       int status;
 {
 #ifdef TDEBUG
        msg("pid = %d exits with status %d\n", getpid(), status);
 {
 #ifdef TDEBUG
        msg("pid = %d exits with status %d\n", getpid(), status);
@@ -347,6 +419,7 @@ Exit(status)
 /*
  * could use pipe() for this if flock() worked on pipes
  */
 /*
  * could use pipe() for this if flock() worked on pipes
  */
+void
 lockfile(fd)
        int fd[2];
 {
 lockfile(fd)
        int fd[2];
 {
@@ -354,19 +427,16 @@ lockfile(fd)
 
        strcpy(tmpname, _PATH_LOCK);
        mktemp(tmpname);
 
        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 */
 enslave()
 {
        int first[2], prev[2], next[2], cmd[2];     /* file descriptors */
@@ -392,11 +462,9 @@ enslave()
                        next[0] = first[0];
                        next[1] = first[1];         /* Last slave loops back */
                }
                        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++)
                slavefd[i] = cmd[1];
                if (slavepid[i] == 0) {             /* Slave starts up here */
                        for (j = 0; j <= i; j++)
@@ -416,6 +484,7 @@ enslave()
        master = 0; rotor = 0;
 }
 
        master = 0; rotor = 0;
 }
 
+void
 killall()
 {
        register int i;
 killall()
 {
        register int i;
@@ -432,16 +501,22 @@ killall()
  * file, allowing the following process to lock it and proceed. We
  * get the lock back for the next cycle by swapping descriptors.
  */
  * 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;
 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
         */
        /*
         * Get list of blocks to dump, read the blocks into tape buffer
         */
@@ -453,20 +528,24 @@ doslave(cmd, prev, next)
                                        p->count * TP_BSIZE);
                        } else {
                                if (p->count != 1 || atomic(read, cmd,
                                        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
                        }
                }
                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
 #else RDUMP
-               if (write(to, tblock[0], writesize) != writesize) {
+               if ((nwrite = write(tapefd, tblock[0], writesize))
+                   != writesize) {
 #endif RDUMP
 #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);
                        kill(master, SIGUSR1);
                        for (;;)
                                sigpause(0);
@@ -474,10 +553,8 @@ doslave(cmd, prev, next)
                toggle ^= 1;
                flock(next[toggle], LOCK_UN);   /* Next slave's turn */
        }                                       /* Also jolts him awake */
                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));
 }
 
 /*
 }
 
 /*
@@ -485,6 +562,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).
  */
  * 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;
 atomic(func, fd, buf, count)
        int (*func)(), fd, count;
        char *buf;