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: }

Defined functions

close_rewind defined in line 122; used 3 times
flusht defined in line 46; used 2 times
otape defined in line 153; used 2 times
rewind defined in line 106; used 2 times
sig_ign_parent defined in line 264; used 2 times
taprec defined in line 17; used 2 times
tapsrec defined in line 31; used 1 times

Defined variables

nogripe defined in line 44; used 3 times
sccsid defined in line 8; never used
tblock defined in line 13; used 6 times
tdaddr defined in line 14; used 7 times
trecno defined in line 15; used 10 times
Last modified: 1985-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1162
Valid CSS Valid XHTML 1.0 Strict