X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=dump%2Ftape.c;h=125b15884074869ed1d7b4b4adcf0c58bfcf18f0;hp=7851719381ee78f3702acbbe2fc0bc70a2f5c2e7;hb=35952b8fbb9df4f18fe7c470dc62ed318d4ce695;hpb=a1b67fc50f87e9febfd56bd2a7089eb569b852f6 diff --git a/dump/tape.c b/dump/tape.c index 7851719..125b158 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999-2000 - * Stelian Pop - Alcôve , 2000 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 */ /*- @@ -41,16 +41,18 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.36 2001/03/20 10:02:48 stelian Exp $"; + "$Id: tape.c,v 1.63 2002/02/21 09:25:31 stelian Exp $"; #endif /* not lint */ #include +#include #include #include #include #include #include #include +#include #ifdef __STDC__ #include #include @@ -61,16 +63,24 @@ int write(), read(); #ifdef __linux__ #include +#include #include -#include #endif #include #include -#include #include +#include #ifdef __linux__ +#include +#undef atomic_read /* this get wrongly defined in kernel */ + /* headers and we don't want it */ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif #include +#include #include #elif defined sunos #include @@ -88,6 +98,10 @@ int write(), read(); #include #endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB +#include +#endif /* HAVE_BZLIB */ + #include "dump.h" int writesize; /* size of malloc()ed buffer for tape */ @@ -97,20 +111,23 @@ 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; -extern char *host; char *nexttape; extern pid_t rshpid; int eot_code = 1; long long tapea_bytes = 0; /* bytes_written at start of current volume */ +static int magtapeout; /* output is really a tape */ static ssize_t atomic_read __P((int, void *, size_t)); static ssize_t atomic_write __P((int, const void *, size_t)); -static void doslave __P((int, int)); +static void doslave __P((int, int, int)); static void enslave __P((void)); static void flushtape __P((void)); static void killall __P((void)); static void rollforward __P((void)); -static int system_command __P((const char *, const char *, int)); +#ifdef USE_QFA +static int GetTapePos __P((long long *)); +static void MkTapeString __P((struct s_spcl *, long long)); +#endif /* * Concurrent dump mods (Caltech) - disk block reading and tape writing @@ -158,6 +175,9 @@ static int ready; /* have we reached the lock point without having */ /* received the SIGUSR2 signal from the prev slave? */ static sigjmp_buf jmpbuf; /* where to jump to if we are ready when the */ /* SIGUSR2 arrives from the previous slave */ +#ifdef USE_QFA +static int gtperr = 0; +#endif int alloctape(void) @@ -214,6 +234,30 @@ writerec(const void *dp, int isspcl) slp->req[trecno].count = 1; /* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */ *(union u_spcl *)(*(nextblock)) = *(union u_spcl *)dp; + + /* Need to write it to the archive file */ + if (Afile < 0 && isspcl && (spcl.c_type == TS_END)) + Afile = -Afile; + if (Afile > 0) { + /* When we dump an inode which is not a directory, + * it means we ended the archive contents */ + if (isspcl && (spcl.c_type == TS_INODE) && + ((spcl.c_dinode.di_mode & S_IFMT) != IFDIR)) + Afile = -Afile; + else { + union u_spcl tmp; + tmp = *(union u_spcl *)dp; + /* Write the record, _uncompressed_ */ + if (isspcl) { + tmp.s_spcl.c_flags &= ~DR_COMPRESSED; + mkchecksum(&tmp); + } + if (write(Afile, &tmp, TP_BSIZE) != TP_BSIZE) + msg("error writing archive file: %s\n", + strerror(errno)); + } + } + nextblock++; if (isspcl) lastspclrec = spcl.c_tapea; @@ -253,7 +297,8 @@ tperror(int errnum) quit("Cannot recover\n"); /* NOTREACHED */ } - msg("write error %d blocks into volume %d: %s\n", blocksthisvol, tapeno, strerror(errnum)); + msg("write error %d blocks into volume %d: %s\n", + blocksthisvol, tapeno, strerror(errnum)); broadcast("DUMP WRITE ERROR!\n"); if (query("Do you want to rewrite this volume?")) { msg("Closing this volume. Prepare to restart with new media;\n"); @@ -297,13 +342,13 @@ do_stats(void) long txfrate = volkb / ttaken; msg("Volume %d took %d:%02d:%02d\n", tapeno, ttaken / 3600, (ttaken % 3600) / 60, ttaken % 60); - msg("Volume %d transfer rate: %ld KB/s\n", tapeno, + msg("Volume %d transfer rate: %ld kB/s\n", tapeno, txfrate); xferrate += txfrate; if (compressed) { double rate = .0005 + (double) blocks / (double) volkb; - msg("Volume %d %ldKB uncompressed, %ldKB compressed," - " compression ratio %1.3f\n", + msg("Volume %d %ldkB uncompressed, %ldkB compressed," + " %1.3f:1\n", tapeno, blocks, volkb, rate); } } @@ -326,7 +371,7 @@ mktimeest(time_t tnow) / blockswritten * tapesize; if (tnow > tstart_volume) (void)snprintf(msgbuf, sizeof(msgbuf), - "%3.2f%% done at %ld KB/s, finished in %d:%02d\n", + "%3.2f%% done at %ld kB/s, finished in %d:%02d\n", (blockswritten * 100.0) / tapesize, (spcl.c_tapea - tapea_volume) / (tnow - tstart_volume), (int)(deltat / 3600), (int)((deltat % 3600) / 60)); @@ -435,54 +480,20 @@ flushtape(void) asize += tenths + returned.clen / density; blockswritten += ntrec; blocksthisvol += ntrec; - if (!pipeout && !unlimited && (blocksperfile ? - (blocksthisvol >= blocksperfile) : (asize > tsize))) { - close_rewind(); - startnewtape(0); - } - timeest(); -} - -/* - * Executes the command in a shell. - * Returns -1 if an error occured, the exit status of - * the command on success. - */ -int system_command(const char *command, const char *device, int volnum) { - int pid, status; - char commandstr[4096]; - - pid = fork(); - if (pid == -1) { - perror(" DUMP: unable to fork"); - return -1; - } - if (pid == 0) { - setuid(getuid()); - setgid(getgid()); -#if OLD_STYLE_FSCRIPT - snprintf(commandstr, sizeof(commandstr), "%s", command); -#else - snprintf(commandstr, sizeof(commandstr), "%s %s %d", command, device, volnum); -#endif - commandstr[sizeof(commandstr) - 1] = '\0'; - execl("/bin/sh", "sh", "-c", commandstr, NULL); - perror(" DUMP: unable to execute shell"); - exit(-1); - } - do { - if (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) { - perror(" DUMP: waitpid error"); - return -1; + if (!pipeout && !unlimited) { + if (blocksperfile) { + if ( compressed ? (bytes_written - tapea_bytes + SLAVES * (writesize + sizeof(struct tapebuf))) >= blocksperfile * 1024 + : blocksthisvol >= blocksperfile ) { + close_rewind(); + startnewtape(0); } - } else { - if (WIFEXITED(status)) - return WEXITSTATUS(status); - else - return -1; } - } while(1); + else if (asize > tsize) { + close_rewind(); + startnewtape(0); + } + } + timeest(); } time_t @@ -542,9 +553,11 @@ trewind(void) #endif { (void) close(tapefd); - while ((f = open(tape, 0)) < 0) - sleep (10); - (void) close(f); + if (!fifoout) { + while ((f = OPEN(tape, 0)) < 0) + sleep (10); + (void) close(f); + } } eot_code = 1; if (eot_script && spcl.c_type != TS_END) { @@ -580,8 +593,8 @@ close_rewind(void) void rollforward(void) { - register struct req *p, *q, *prev; - register struct slave *tslp; + struct req *p, *q = NULL, *prev; + struct slave *tslp; int i, size, savedtapea, got; union u_spcl *ntb, *otb; struct slave_results returned; @@ -856,16 +869,27 @@ restore_check_point: #ifdef RDUMP while ((tapefd = (host ? rmtopen(tape, 2) : pipeout ? fileno(stdout) : - open(tape, O_WRONLY|O_CREAT, 0666))) < 0) + OPEN(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else while ((tapefd = (pipeout ? fileno(stdout) : - open(tape, O_WRONLY|O_CREAT, 0666))) < 0) + OPEN(tape, O_RDWR|O_CREAT, 0666))) < 0) #endif { msg("Cannot open output \"%s\".\n", tape); if (!query("Do you want to retry the open?")) dumpabort(0); } +#ifdef RDUMP + if (!host) +#endif + { + struct mtget mt_stat; + magtapeout = ioctl(tapefd, MTIOCGET, (char *)&mt_stat) == 0; + /* + msg("Output is to %s\n", + magtapeout ? "tape" : "file/pipe"); + */ + } enslave(); /* Share open tape file descriptor with slaves */ @@ -882,6 +906,7 @@ restore_check_point: spcl.c_volume++; spcl.c_type = TS_TAPE; spcl.c_flags |= DR_NEWHEADER; + spcl.c_ntrec = ntrec; if (compressed) spcl.c_flags |= DR_COMPRESSED; writeheader((dump_ino_t)slp->inode); @@ -891,6 +916,8 @@ restore_check_point: if (tapeno > 1) msg("Volume %d begins with blocks from inode %d\n", tapeno, slp->inode); + if (tapeno < TP_NINOS) + volinfo[tapeno] = slp->inode; } } @@ -939,7 +966,7 @@ enslave(void) #ifdef LINUX_FORK_BUG int i, j; #else - register int i, j; + int i, j; #endif master = getpid(); @@ -986,9 +1013,11 @@ enslave(void) != sizeof i) quit("master/slave protocol botched 3\n"); #endif - doslave(cmd[0], i); + doslave(cmd[0], i, (slaves[i].pid == slp->pid)); Exit(X_FINOK); } + else + close(cmd[0]); } #ifdef LINUX_FORK_BUG @@ -1013,7 +1042,7 @@ enslave(void) void killall(void) { - register int i; + int i; for (i = 0; i < SLAVES; i++) if (slaves[i].pid > 0) { @@ -1030,29 +1059,46 @@ killall(void) * slaves. */ static void -doslave(int cmd, int slave_number) +doslave(int cmd, int slave_number, int first) { - register int nread; + int nread; int nextslave, size, eot_count, bufsize; volatile int wrote = 0; char *buffer; -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) struct tapebuf *comp_buf = NULL; - int compresult, complevel = 6, do_compress = 0; + int compresult, do_compress = !first; unsigned long worklen; -#endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB + unsigned int worklen2; +#endif +#endif /* HAVE_ZLIB || HAVE_BZLIB */ struct slave_results returns; #ifdef __linux__ errcode_t retval; #endif +#ifdef USE_QFA + long long curtapepos; + union u_spcl *uspclptr; + struct s_spcl *spclptr; +#endif /* USE_QFA */ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigprocmask(SIG_BLOCK, &set, NULL); + sigemptyset(&set); /* * Need our own seek pointer. */ (void) close(diskfd); - if ((diskfd = open(disk, O_RDONLY)) < 0) + if ((diskfd = OPEN(disk, O_RDONLY)) < 0) quit("slave couldn't reopen disk: %s\n", strerror(errno)); #ifdef __linux__ +#ifdef BLKFLSBUF + (void)ioctl(diskfd, BLKFLSBUF); +#endif ext2fs_close(fs); retval = dump_fs_open(disk, &fs); if (retval) @@ -1067,21 +1113,24 @@ doslave(int cmd, int slave_number) quit("master/slave protocol botched - didn't get pid of next slave.\n"); } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) /* if we're doing a compressed dump, allocate the compress buffer */ if (compressed) { comp_buf = malloc(sizeof(struct tapebuf) + TP_BSIZE + writesize); if (comp_buf == NULL) quit("couldn't allocate a compress buffer.\n"); - comp_buf->flags = 0; + if (bzipflag) + comp_buf->flags = COMPRESS_BZLIB; + else + comp_buf->flags = COMPRESS_ZLIB; } -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ /* * Get list of blocks to dump, read the blocks into tape buffer */ while ((nread = atomic_read( cmd, (char *)slp->req, reqsiz)) == reqsiz) { - register struct req *p = slp->req; + struct req *p = slp->req; for (trecno = 0; trecno < ntrec; trecno += p->count, p += p->count) { @@ -1095,13 +1144,6 @@ doslave(int cmd, int slave_number) quit("master/slave protocol botched.\n"); } } - if (sigsetjmp(jmpbuf, 1) == 0) { - ready = 1; - if (!caught) - (void) pause(); - } - ready = 0; - caught = 0; /* Try to write the data... */ wrote = 0; @@ -1111,25 +1153,56 @@ doslave(int cmd, int slave_number) bufsize = writesize; /* length to write */ returns.clen = returns.unclen = bufsize; -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) /* - * The first NR_SLAVE blocks are not compressed. - * When writing a compressed dump, each block is - * written from struct tapebuf with an 4 byte prefix + * When writing a compressed dump, each block except + * the first one on each tape is written + * from struct tapebuf with an 4 byte prefix * followed by the data. This can be less than * writesize. Restore, on a short read, can compare the * length read to the compressed length in the header * to verify that the read was good. Blocks which don't * compress well are written uncompressed. + * The first block written by each slave is not compressed + * and does not have a prefix. */ - if (compressed) { + if (compressed && do_compress) { comp_buf->length = bufsize; worklen = TP_BSIZE + writesize; - if (do_compress) - compresult = compress2(comp_buf->buf, &worklen, - (char *)slp->tblock[0], writesize, complevel); - if (compresult == Z_OK && worklen <= writesize-32) { + compresult = 1; +#ifdef HAVE_ZLIB + if (!bzipflag) { + compresult = compress2(comp_buf->buf, + &worklen, + (char *)slp->tblock[0], + writesize, + compressed); + if (compresult == Z_OK) + compresult = 1; + else + compresult = 0; + } +#endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB + if (bzipflag) { + worklen2 = worklen; + compresult = BZ2_bzBuffToBuffCompress( + comp_buf->buf, + &worklen2, + (char *)slp->tblock[0], + writesize, + compressed, + 0, 30); + worklen = worklen2; + if (compresult == BZ_OK) + compresult = 1; + else + compresult = 0; + } + +#endif /* HAVE_BZLIB */ + if (compresult && worklen <= (writesize - 16)) { /* write the compressed buffer */ comp_buf->length = worklen; comp_buf->compressed = 1; @@ -1146,10 +1219,39 @@ doslave(int cmd, int slave_number) memcpy(comp_buf->buf, (char *)slp->tblock[0], writesize); } } - /* compress the remaining blocks */ + /* compress the remaining blocks if we're compressing */ do_compress = compressed; -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ + if (sigsetjmp(jmpbuf, 1) == 0) { + ready = 1; + if (!caught) + sigsuspend(&set); + } + ready = 0; + caught = 0; + +#ifdef USE_QFA + if (gTapeposfd >= 0) { + int i; + for (i = 0; i < ntrec; ++i) { + uspclptr = (union u_spcl *)&slp->tblock[i]; + spclptr = &uspclptr->s_spcl; + if ((spclptr->c_magic == NFS_MAGIC) && + (spclptr->c_type == TS_INODE) && + ((spclptr->c_dinode.di_mode & S_IFMT) != IFDIR) && + (spclptr->c_date == gThisDumpDate)) { + /* if an error occured previously don't + * try again */ + if (gtperr == 0) { + if ((gtperr = GetTapePos(&curtapepos)) == 0) + MkTapeString(spclptr, curtapepos); + } + } + } + } +#endif /* USE_QFA */ + while (eot_count < 10 && size < bufsize) { #ifdef RDUMP if (host) @@ -1238,3 +1340,59 @@ atomic_write(int fd, const void *buf, size_t count) } while (got == -1 && errno == EINTR); return (got < 0 ? got : count - need); } + + +#ifdef USE_QFA +/* + * read the current tape position + */ +static int +GetTapePos(long long *pos) +{ + int err = 0; + +#ifdef RDUMP + if (host) { + *pos = (long long) rmtseek(0, SEEK_CUR); + err = *pos < 0; + } + else +#endif + { + if (magtapeout) { + long mtpos; + *pos = 0; + err = (ioctl(tapefd, MTIOCPOS, &mtpos) < 0); + *pos = (long long)mtpos; + } + else { + *pos = LSEEK(tapefd, 0, SEEK_CUR); + err = (*pos < 0); + } + } + if (err) { + err = errno; + msg("[%ld] error: %d (getting tapepos: %lld)\n", getpid(), + err, *pos); + return err; + } + return err; +} + +static void +MkTapeString(struct s_spcl *spclptr, long long curtapepos) { + +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %lld\n", spclptr->c_inumber, curtapepos); +#endif + + snprintf(gTps, sizeof(gTps), "%ld\t%d\t%lld\n", + (unsigned long)spclptr->c_inumber, + tapeno, + curtapepos); + gTps[sizeof(gTps) - 1] = '\0'; + if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) { + warn("error writing tapepos file.\n"); + } +} +#endif /* USE_QFA */