|
|
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.