|
|
1.1 ! root 1: static char *sccsid = "@(#)dumptape.c 1.7 (Berkeley) 5/8/83"; ! 2: #include "dump.h" ! 3: ! 4: char (*tblock)[TP_BSIZE]; /* Pointer to malloc()ed buffer for tape */ ! 5: int writesize; /* Size of malloc()ed buffer for tape */ ! 6: int trecno = 0; ! 7: extern int ntrec; /* blocking factor on tape */ ! 8: ! 9: /* ! 10: * Allocate the buffer for tape operations. ! 11: * ! 12: * Depends on global variable ntrec, set from 'b' option in command line. ! 13: * Returns 1 if successful, 0 if failed. ! 14: * ! 15: * For later kernel performance improvement, this buffer should be allocated ! 16: * on a page boundary. ! 17: */ ! 18: alloctape() ! 19: { ! 20: ! 21: writesize = ntrec * TP_BSIZE; ! 22: tblock = (char (*)[TP_BSIZE])malloc(writesize); ! 23: return (tblock != NULL); ! 24: } ! 25: ! 26: ! 27: taprec(dp) ! 28: char *dp; ! 29: { ! 30: register i; ! 31: ! 32: for (i=0; i < TP_BSIZE; i++) ! 33: tblock[trecno][i] = *dp++; ! 34: trecno++; ! 35: spcl.c_tapea++; ! 36: if(trecno >= ntrec) ! 37: flusht(); ! 38: } ! 39: ! 40: dmpblk(blkno, size) ! 41: daddr_t blkno; ! 42: int size; ! 43: { ! 44: int avail, tpblks, dblkno; ! 45: ! 46: if (size % TP_BSIZE != 0) ! 47: msg("bad size to dmpblk: %d\n", size); ! 48: avail = ntrec - trecno; ! 49: dblkno = fsbtodb(sblock, blkno); ! 50: for (tpblks = size / TP_BSIZE; tpblks > avail; ) { ! 51: bread(dblkno, tblock[trecno], TP_BSIZE * avail); ! 52: trecno += avail; ! 53: spcl.c_tapea += avail; ! 54: flusht(); ! 55: dblkno += avail * (TP_BSIZE / DEV_BSIZE); ! 56: tpblks -= avail; ! 57: avail = ntrec - trecno; ! 58: } ! 59: bread(dblkno, tblock[trecno], TP_BSIZE * tpblks); ! 60: trecno += tpblks; ! 61: spcl.c_tapea += tpblks; ! 62: if(trecno >= ntrec) ! 63: flusht(); ! 64: } ! 65: ! 66: int nogripe = 0; ! 67: ! 68: flusht() ! 69: { ! 70: register i, si; ! 71: daddr_t d; ! 72: ! 73: trecno = 0; ! 74: if (write(to, tblock[0], writesize) != writesize){ ! 75: if (pipeout) { ! 76: msg("Tape write error on %s\n", tape); ! 77: msg("Cannot recover\n"); ! 78: dumpabort(); ! 79: /* NOTREACHED */ ! 80: } ! 81: msg("Tape write error on tape %d\n", tapeno); ! 82: broadcast("TAPE ERROR!\n"); ! 83: if (query("Do you want to restart?")){ ! 84: msg("This tape will rewind. After it is rewound,\n"); ! 85: msg("replace the faulty tape with a new one;\n"); ! 86: msg("this dump volume will be rewritten.\n"); ! 87: /* ! 88: * Temporarily change the tapeno identification ! 89: */ ! 90: tapeno--; ! 91: nogripe = 1; ! 92: close_rewind(); ! 93: nogripe = 0; ! 94: tapeno++; ! 95: Exit(X_REWRITE); ! 96: } else { ! 97: dumpabort(); ! 98: /*NOTREACHED*/ ! 99: } ! 100: } ! 101: ! 102: asize += writesize/density; ! 103: asize += 7; ! 104: blockswritten += ntrec; ! 105: if (!pipeout && asize > tsize) { ! 106: close_rewind(); ! 107: otape(); ! 108: } ! 109: timeest(); ! 110: } ! 111: ! 112: rewind() ! 113: { ! 114: int secs; ! 115: int f; ! 116: ! 117: if (pipeout) ! 118: return; ! 119: #ifdef DEBUG ! 120: msg("Waiting 10 seconds to rewind.\n"); ! 121: sleep(10); ! 122: #else ! 123: /* ! 124: * It takes about 3 minutes, 25secs to rewind 2300' of tape ! 125: */ ! 126: msg("Tape rewinding\n", secs); ! 127: close(to); ! 128: while ((f = open(tape, 0)) < 0) ! 129: sleep (10); ! 130: close(f); ! 131: #endif ! 132: } ! 133: ! 134: close_rewind() ! 135: { ! 136: ! 137: if (pipeout) ! 138: return; ! 139: close(to); ! 140: if (!nogripe){ ! 141: rewind(); ! 142: msg("Change Tapes: Mount tape #%d\n", tapeno+1); ! 143: broadcast("CHANGE TAPES!\7\7\n"); ! 144: } ! 145: do{ ! 146: if (query ("Is the new tape mounted and ready to go?")) ! 147: break; ! 148: if (query ("Do you want to abort?")){ ! 149: dumpabort(); ! 150: /*NOTREACHED*/ ! 151: } ! 152: } while (1); ! 153: } ! 154: ! 155: /* ! 156: * We implement taking and restoring checkpoints on ! 157: * the tape level. ! 158: * When each tape is opened, a new process is created by forking; this ! 159: * saves all of the necessary context in the parent. The child ! 160: * continues the dump; the parent waits around, saving the context. ! 161: * If the child returns X_REWRITE, then it had problems writing that tape; ! 162: * this causes the parent to fork again, duplicating the context, and ! 163: * everything continues as if nothing had happened. ! 164: */ ! 165: ! 166: otape() ! 167: { ! 168: int parentpid; ! 169: int childpid; ! 170: int status; ! 171: int waitpid; ! 172: int sig_ign_parent(); ! 173: int interrupt(); ! 174: ! 175: /* ! 176: * Force the tape to be closed ! 177: */ ! 178: close(to); ! 179: parentpid = getpid(); ! 180: ! 181: restore_check_point: ! 182: signal(SIGINT, interrupt); ! 183: /* ! 184: * All signals are inherited... ! 185: */ ! 186: childpid = fork(); ! 187: if (childpid < 0){ ! 188: msg("Context save fork fails in parent %d\n", parentpid); ! 189: Exit(X_ABORT); ! 190: } ! 191: if (childpid != 0){ ! 192: /* ! 193: * PARENT: ! 194: * save the context by waiting ! 195: * until the child doing all of the work returns. ! 196: * don't catch the interrupt ! 197: */ ! 198: signal(SIGINT, SIG_IGN); ! 199: #ifdef TDEBUG ! 200: msg("Tape: %d; parent process: %d child process %d\n", ! 201: tapeno+1, parentpid, childpid); ! 202: #endif TDEBUG ! 203: for (;;){ ! 204: waitpid = wait(&status); ! 205: if (waitpid != childpid){ ! 206: msg("Parent %d waiting for child %d has another child %d return\n", ! 207: parentpid, childpid, waitpid); ! 208: } else ! 209: break; ! 210: } ! 211: if (status & 0xFF){ ! 212: msg("Child %d returns LOB status %o\n", ! 213: childpid, status&0xFF); ! 214: } ! 215: status = (status >> 8) & 0xFF; ! 216: #ifdef TDEBUG ! 217: switch(status){ ! 218: case X_FINOK: ! 219: msg("Child %d finishes X_FINOK\n", childpid); ! 220: break; ! 221: case X_ABORT: ! 222: msg("Child %d finishes X_ABORT\n", childpid); ! 223: break; ! 224: case X_REWRITE: ! 225: msg("Child %d finishes X_REWRITE\n", childpid); ! 226: break; ! 227: default: ! 228: msg("Child %d finishes unknown %d\n", childpid,status); ! 229: break; ! 230: } ! 231: #endif TDEBUG ! 232: switch(status){ ! 233: case X_FINOK: ! 234: Exit(X_FINOK); ! 235: case X_ABORT: ! 236: Exit(X_ABORT); ! 237: case X_REWRITE: ! 238: goto restore_check_point; ! 239: default: ! 240: msg("Bad return code from dump: %d\n", status); ! 241: Exit(X_ABORT); ! 242: } ! 243: /*NOTREACHED*/ ! 244: } else { /* we are the child; just continue */ ! 245: #ifdef TDEBUG ! 246: sleep(4); /* allow time for parent's message to get out */ ! 247: msg("Child on Tape %d has parent %d, my pid = %d\n", ! 248: tapeno+1, parentpid, getpid()); ! 249: #endif ! 250: do{ ! 251: if (pipeout) ! 252: to = 1; ! 253: else ! 254: to = creat(tape, 0666); ! 255: if (to < 0) { ! 256: if (!query("Cannot open tape. Do you want to retry the open?")) ! 257: dumpabort(); ! 258: } else break; ! 259: } while (1); ! 260: ! 261: asize = 0; ! 262: tapeno++; /* current tape sequence */ ! 263: newtape++; /* new tape signal */ ! 264: spcl.c_volume++; ! 265: spcl.c_type = TS_TAPE; ! 266: spclrec(); ! 267: if (tapeno > 1) ! 268: msg("Tape %d begins with blocks from ino %d\n", ! 269: tapeno, ino); ! 270: } ! 271: } ! 272: ! 273: /* ! 274: * The parent still catches interrupts, but does nothing with them ! 275: */ ! 276: sig_ign_parent() ! 277: { ! 278: msg("Waiting parent receives interrupt\n"); ! 279: signal(SIGINT, sig_ign_parent); ! 280: } ! 281: ! 282: dumpabort() ! 283: { ! 284: msg("The ENTIRE dump is aborted.\n"); ! 285: Exit(X_ABORT); ! 286: } ! 287: ! 288: Exit(status) ! 289: { ! 290: #ifdef TDEBUG ! 291: msg("pid = %d exits with status %d\n", getpid(), status); ! 292: #endif TDEBUG ! 293: exit(status); ! 294: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.