BSD 4 release
[unix-history] / usr / src / cmd / dump / dumptape.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)dumptape.c 1.1 (Berkeley) 10/13/80";
ae4b153c
BJ
2#include "dump.h"
3
4char tblock[NTREC][BSIZE];
5daddr_t tdaddr[NTREC];
6int trecno;
7
8taprec(dp)
9char *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
22tapsrec(d)
23daddr_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
35int nogripe = 0;
36
37flusht()
38{
39 register i, si;
40 daddr_t d;
41
42 while(trecno < NTREC)
43 tdaddr[trecno++] = 1;
44
45loop:
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
91rewind()
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
107close_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
136otape()
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 */
243sig_ign_parent()
244{
245 msg("Waiting parent receives interrupt\n");
246 signal(SIGINT, sig_ign_parent);
247}
248
249dumpabort()
250{
251 msg("The ENTIRE dump is aborted. NO second chances (tough luck sucker).\n");
252 Exit(X_ABORT);
253}
254
255Exit(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
264exit(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
283henryexit(status)
284 /* ARGSUSED */
285{
286 _cleanup();
287 asm(" chmk $1");
288 asm("halt");
289}