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