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