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