Annotation of 42BSD/etc/dump/dumptape.c, revision 1.1.1.1

1.1       root        1: static char *sccsid = "@(#)dumptape.c  1.7 (Berkeley) 5/8/83";
                      2: #include "dump.h"
                      3: 
                      4: char   (*tblock)[TP_BSIZE];    /* Pointer to malloc()ed buffer for tape */
                      5: int    writesize;              /* Size of malloc()ed buffer for tape */
                      6: int    trecno = 0;
                      7: extern int ntrec;              /* blocking factor on tape */
                      8: 
                      9: /*
                     10:  * Allocate the buffer for tape operations.
                     11:  *
                     12:  * Depends on global variable ntrec, set from 'b' option in command line.
                     13:  * Returns 1 if successful, 0 if failed.
                     14:  *
                     15:  * For later kernel performance improvement, this buffer should be allocated
                     16:  * on a page boundary.
                     17:  */
                     18: alloctape()
                     19: {
                     20: 
                     21:        writesize = ntrec * TP_BSIZE;
                     22:        tblock = (char (*)[TP_BSIZE])malloc(writesize);
                     23:        return (tblock != NULL);
                     24: }
                     25: 
                     26: 
                     27: taprec(dp)
                     28:        char *dp;
                     29: {
                     30:        register i;
                     31: 
                     32:        for (i=0; i < TP_BSIZE; i++)
                     33:                tblock[trecno][i] = *dp++;
                     34:        trecno++;
                     35:        spcl.c_tapea++;
                     36:        if(trecno >= ntrec)
                     37:                flusht();
                     38: }
                     39: 
                     40: dmpblk(blkno, size)
                     41:        daddr_t blkno;
                     42:        int size;
                     43: {
                     44:        int avail, tpblks, dblkno;
                     45: 
                     46:        if (size % TP_BSIZE != 0)
                     47:                msg("bad size to dmpblk: %d\n", size);
                     48:        avail = ntrec - trecno;
                     49:        dblkno = fsbtodb(sblock, blkno);
                     50:        for (tpblks = size / TP_BSIZE; tpblks > avail; ) {
                     51:                bread(dblkno, tblock[trecno], TP_BSIZE * avail);
                     52:                trecno += avail;
                     53:                spcl.c_tapea += avail;
                     54:                flusht();
                     55:                dblkno += avail * (TP_BSIZE / DEV_BSIZE);
                     56:                tpblks -= avail;
                     57:                avail = ntrec - trecno;
                     58:        }
                     59:        bread(dblkno, tblock[trecno], TP_BSIZE * tpblks);
                     60:        trecno += tpblks;
                     61:        spcl.c_tapea += tpblks;
                     62:        if(trecno >= ntrec)
                     63:                flusht();
                     64: }
                     65: 
                     66: int    nogripe = 0;
                     67: 
                     68: flusht()
                     69: {
                     70:        register i, si;
                     71:        daddr_t d;
                     72: 
                     73:        trecno = 0;
                     74:        if (write(to, tblock[0], writesize) != writesize){
                     75:                if (pipeout) {
                     76:                        msg("Tape write error on %s\n", tape);
                     77:                        msg("Cannot recover\n");
                     78:                        dumpabort();
                     79:                        /* NOTREACHED */
                     80:                }
                     81:                msg("Tape write error on tape %d\n", tapeno);
                     82:                broadcast("TAPE ERROR!\n");
                     83:                if (query("Do you want to restart?")){
                     84:                        msg("This tape will rewind.  After it is rewound,\n");
                     85:                        msg("replace the faulty tape with a new one;\n");
                     86:                        msg("this dump volume will be rewritten.\n");
                     87:                        /*
                     88:                         *      Temporarily change the tapeno identification
                     89:                         */
                     90:                        tapeno--;
                     91:                        nogripe = 1;
                     92:                        close_rewind();
                     93:                        nogripe = 0;
                     94:                        tapeno++;
                     95:                        Exit(X_REWRITE);
                     96:                } else {
                     97:                        dumpabort();
                     98:                        /*NOTREACHED*/
                     99:                }
                    100:        }
                    101: 
                    102:        asize += writesize/density;
                    103:        asize += 7;
                    104:        blockswritten += ntrec;
                    105:        if (!pipeout && asize > tsize) {
                    106:                close_rewind();
                    107:                otape();
                    108:        }
                    109:        timeest();
                    110: }
                    111: 
                    112: rewind()
                    113: {
                    114:        int     secs;
                    115:        int f;
                    116: 
                    117:        if (pipeout)
                    118:                return;
                    119: #ifdef DEBUG
                    120:        msg("Waiting 10 seconds to rewind.\n");
                    121:        sleep(10);
                    122: #else
                    123:        /*
                    124:         *      It takes about 3 minutes, 25secs to rewind 2300' of tape
                    125:         */
                    126:        msg("Tape rewinding\n", secs);
                    127:        close(to);
                    128:        while ((f = open(tape, 0)) < 0)
                    129:                sleep (10);
                    130:        close(f);
                    131: #endif
                    132: }
                    133: 
                    134: close_rewind()
                    135: {
                    136: 
                    137:        if (pipeout)
                    138:                return;
                    139:        close(to);
                    140:        if (!nogripe){
                    141:                rewind();
                    142:                msg("Change Tapes: Mount tape #%d\n", tapeno+1);
                    143:                broadcast("CHANGE TAPES!\7\7\n");
                    144:        }
                    145:        do{
                    146:                if (query ("Is the new tape mounted and ready to go?"))
                    147:                        break;
                    148:                if (query ("Do you want to abort?")){
                    149:                        dumpabort();
                    150:                        /*NOTREACHED*/
                    151:                }
                    152:        } while (1);
                    153: }
                    154: 
                    155: /*
                    156:  *     We implement taking and restoring checkpoints on
                    157:  *     the tape level.
                    158:  *     When each tape is opened, a new process is created by forking; this
                    159:  *     saves all of the necessary context in the parent.  The child
                    160:  *     continues the dump; the parent waits around, saving the context.
                    161:  *     If the child returns X_REWRITE, then it had problems writing that tape;
                    162:  *     this causes the parent to fork again, duplicating the context, and
                    163:  *     everything continues as if nothing had happened.
                    164:  */
                    165: 
                    166: otape()
                    167: {
                    168:        int     parentpid;
                    169:        int     childpid;
                    170:        int     status;
                    171:        int     waitpid;
                    172:        int     sig_ign_parent();
                    173:        int     interrupt();
                    174: 
                    175:        /*
                    176:         *      Force the tape to be closed
                    177:         */
                    178:        close(to);
                    179:        parentpid = getpid();
                    180: 
                    181:     restore_check_point:
                    182:        signal(SIGINT, interrupt);
                    183:        /*
                    184:         *      All signals are inherited...
                    185:         */
                    186:        childpid = fork();
                    187:        if (childpid < 0){
                    188:                msg("Context save fork fails in parent %d\n", parentpid);
                    189:                Exit(X_ABORT);
                    190:        }
                    191:        if (childpid != 0){
                    192:                /*
                    193:                 *      PARENT:
                    194:                 *      save the context by waiting
                    195:                 *      until the child doing all of the work returns.
                    196:                 *      don't catch the interrupt 
                    197:                 */
                    198:                signal(SIGINT, SIG_IGN);
                    199: #ifdef TDEBUG
                    200:                msg("Tape: %d; parent process: %d child process %d\n",
                    201:                        tapeno+1, parentpid, childpid);
                    202: #endif TDEBUG
                    203:                for (;;){
                    204:                        waitpid = wait(&status);
                    205:                        if (waitpid != childpid){
                    206:                                msg("Parent %d waiting for child %d has another child %d return\n",
                    207:                                        parentpid, childpid, waitpid);
                    208:                        } else
                    209:                                break;
                    210:                }
                    211:                if (status & 0xFF){
                    212:                        msg("Child %d returns LOB status %o\n",
                    213:                                childpid, status&0xFF);
                    214:                }
                    215:                status = (status >> 8) & 0xFF;
                    216: #ifdef TDEBUG
                    217:                switch(status){
                    218:                        case X_FINOK:
                    219:                                msg("Child %d finishes X_FINOK\n", childpid);
                    220:                                break;
                    221:                        case X_ABORT:
                    222:                                msg("Child %d finishes X_ABORT\n", childpid);
                    223:                                break;
                    224:                        case X_REWRITE:
                    225:                                msg("Child %d finishes X_REWRITE\n", childpid);
                    226:                                break;
                    227:                        default:
                    228:                                msg("Child %d finishes unknown %d\n", childpid,status);
                    229:                                break;
                    230:                }
                    231: #endif TDEBUG
                    232:                switch(status){
                    233:                        case X_FINOK:
                    234:                                Exit(X_FINOK);
                    235:                        case X_ABORT:
                    236:                                Exit(X_ABORT);
                    237:                        case X_REWRITE:
                    238:                                goto restore_check_point;
                    239:                        default:
                    240:                                msg("Bad return code from dump: %d\n", status);
                    241:                                Exit(X_ABORT);
                    242:                }
                    243:                /*NOTREACHED*/
                    244:        } else {        /* we are the child; just continue */
                    245: #ifdef TDEBUG
                    246:                sleep(4);       /* allow time for parent's message to get out */
                    247:                msg("Child on Tape %d has parent %d, my pid = %d\n",
                    248:                        tapeno+1, parentpid, getpid());
                    249: #endif
                    250:                do{
                    251:                        if (pipeout)
                    252:                                to = 1;
                    253:                        else
                    254:                                to = creat(tape, 0666);
                    255:                        if (to < 0) {
                    256:                                if (!query("Cannot open tape. Do you want to retry the open?"))
                    257:                                        dumpabort();
                    258:                        } else break;
                    259:                } while (1);
                    260: 
                    261:                asize = 0;
                    262:                tapeno++;               /* current tape sequence */
                    263:                newtape++;              /* new tape signal */
                    264:                spcl.c_volume++;
                    265:                spcl.c_type = TS_TAPE;
                    266:                spclrec();
                    267:                if (tapeno > 1)
                    268:                        msg("Tape %d begins with blocks from ino %d\n",
                    269:                                tapeno, ino);
                    270:        }
                    271: }
                    272: 
                    273: /*
                    274:  *     The parent still catches interrupts, but does nothing with them
                    275:  */
                    276: sig_ign_parent()
                    277: {
                    278:        msg("Waiting parent receives interrupt\n");
                    279:        signal(SIGINT, sig_ign_parent);
                    280: }
                    281: 
                    282: dumpabort()
                    283: {
                    284:        msg("The ENTIRE dump is aborted.\n");
                    285:        Exit(X_ABORT);
                    286: }
                    287: 
                    288: Exit(status)
                    289: {
                    290: #ifdef TDEBUG
                    291:        msg("pid = %d exits with status %d\n", getpid(), status);
                    292: #endif TDEBUG
                    293:        exit(status);
                    294: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.