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

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

unix.superglobalmegacorp.com

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