Annotation of 40BSD/cmd/dump/dumptape.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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