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