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