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