|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.