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

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

unix.superglobalmegacorp.com

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