BSD 4_2 release
[unix-history] / usr / src / etc / dump.4.1 / dumptape.c
CommitLineData
0f4556f1 1static char *sccsid = "@(#)dumptape.c 1.3 (Berkeley) 4/28/83";
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) ){
2a729b17
KM
60 if (pipeout) {
61 msg("Tape write error on %s\n", tape);
62 msg("Cannot recover\n");
63 dumpabort();
64 /*NOTREACHED*/
65 }
ae4b153c
BJ
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");
ed7c701e 71 msg("this dump volume will be rewritten.\n");
ae4b153c
BJ
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;
2a729b17 90 if (!pipeout && asize > tsize) {
ae4b153c
BJ
91 close_rewind();
92 otape();
93 }
94 timeest();
95}
96
97rewind()
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
113close_rewind()
114{
2a729b17
KM
115 if (pipeout)
116 return;
ae4b153c
BJ
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
144otape()
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 */
2a729b17
KM
156 if (!pipeout)
157 close(to);
ae4b153c
BJ
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{
2a729b17
KM
230 if (pipeout)
231 to = 1;
232 else
233 to = creat(tape, 0666);
ae4b153c
BJ
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 */
255sig_ign_parent()
256{
257 msg("Waiting parent receives interrupt\n");
258 signal(SIGINT, sig_ign_parent);
259}
260
261dumpabort()
262{
ed7c701e 263 msg("The ENTIRE dump is aborted.\n");
ae4b153c
BJ
264 Exit(X_ABORT);
265}
266
267Exit(status)
268{
269#ifdef TDEBUG
270 msg("pid = %d exits with status %d\n", getpid(), status);
271#endif TDEBUG
ed7c701e 272 exit(status);
ae4b153c 273}