conform to the standard with respect to types of expressions.
[unix-history] / usr / src / sbin / dump / tape.c
CommitLineData
b6407c9d 1static char *sccsid = "@(#)tape.c 1.5 (Berkeley) %G%";
ae4b153c
BJ
2#include "dump.h"
3
f5bba473
KM
4char tblock[NTREC][TP_BSIZE];
5int trecno = 0;
ae4b153c
BJ
6
7taprec(dp)
b6407c9d 8 char *dp;
ae4b153c
BJ
9{
10 register i;
11
b6407c9d 12 for (i=0; i < TP_BSIZE; i++)
ae4b153c 13 tblock[trecno][i] = *dp++;
ae4b153c
BJ
14 trecno++;
15 spcl.c_tapea++;
16 if(trecno >= NTREC)
17 flusht();
18}
19
f5bba473
KM
20dmpblk(blkno, size)
21 daddr_t blkno;
22 int size;
ae4b153c 23{
b6407c9d 24 int avail, tpblks, dblkno;
f5bba473 25
b6407c9d 26 if (size % TP_BSIZE != 0)
f5bba473
KM
27 msg("bad size to dmpblk: %d\n", size);
28 avail = NTREC - trecno;
b6407c9d
KM
29 dblkno = fsbtodb(sblock, blkno);
30 for (tpblks = size / TP_BSIZE; tpblks > avail; ) {
31 bread(dblkno, tblock[trecno], TP_BSIZE * avail);
f5bba473
KM
32 trecno += avail;
33 spcl.c_tapea += avail;
34 flusht();
b6407c9d
KM
35 dblkno += avail * (TP_BSIZE / DEV_BSIZE);
36 tpblks -= avail;
f5bba473
KM
37 avail = NTREC - trecno;
38 }
b6407c9d
KM
39 bread(dblkno, tblock[trecno], TP_BSIZE * tpblks);
40 trecno += tpblks;
41 spcl.c_tapea += tpblks;
ae4b153c
BJ
42 if(trecno >= NTREC)
43 flusht();
44}
45
46int nogripe = 0;
47
48flusht()
49{
50 register i, si;
51 daddr_t d;
52
ae4b153c
BJ
53 trecno = 0;
54 if (write(to, tblock[0], sizeof(tblock)) != sizeof(tblock) ){
55 msg("Tape write error on tape %d\n", tapeno);
56 broadcast("TAPE ERROR!\n");
57 if (query("Do you want to restart?")){
58 msg("This tape will rewind. After it is rewound,\n");
59 msg("replace the faulty tape with a new one;\n");
ed7c701e 60 msg("this dump volume will be rewritten.\n");
ae4b153c
BJ
61 /*
62 * Temporarily change the tapeno identification
63 */
64 tapeno--;
65 nogripe = 1;
66 close_rewind();
67 nogripe = 0;
68 tapeno++;
69 Exit(X_REWRITE);
70 } else {
71 dumpabort();
72 /*NOTREACHED*/
73 }
74 }
75
76 asize += sizeof(tblock)/density;
77 asize += 7;
78 blockswritten += NTREC;
79 if (asize > tsize) {
80 close_rewind();
81 otape();
82 }
83 timeest();
84}
85
86rewind()
87{
88 int secs;
be3f486f 89 int f;
ae4b153c
BJ
90#ifdef DEBUG
91 msg("Waiting 10 seconds to rewind.\n");
92 sleep(10);
93#else
94 /*
95 * It takes about 3 minutes, 25secs to rewind 2300' of tape
96 */
be3f486f
BJ
97 msg("Tape rewinding\n", secs);
98 close(to);
99 while ((f = open(tape, 0)) < 0)
100 sleep (10);
101 close(f);
ae4b153c
BJ
102#endif
103}
104
105close_rewind()
106{
107 close(to);
108 if (!nogripe){
109 rewind();
110 msg("Change Tapes: Mount tape #%d\n", tapeno+1);
111 broadcast("CHANGE TAPES!\7\7\n");
112 }
113 do{
114 if (query ("Is the new tape mounted and ready to go?"))
115 break;
116 if (query ("Do you want to abort?")){
117 dumpabort();
118 /*NOTREACHED*/
119 }
120 } while (1);
121}
122
123/*
124 * We implement taking and restoring checkpoints on
125 * the tape level.
126 * When each tape is opened, a new process is created by forking; this
127 * saves all of the necessary context in the parent. The child
128 * continues the dump; the parent waits around, saving the context.
129 * If the child returns X_REWRITE, then it had problems writing that tape;
130 * this causes the parent to fork again, duplicating the context, and
131 * everything continues as if nothing had happened.
132 */
133
134otape()
135{
136 int parentpid;
137 int childpid;
138 int status;
139 int waitpid;
140 int sig_ign_parent();
141 int interrupt();
142
143 /*
144 * Force the tape to be closed
145 */
146 close(to);
147 parentpid = getpid();
148
149 restore_check_point:
150 signal(SIGINT, interrupt);
151 /*
152 * All signals are inherited...
153 */
154 childpid = fork();
155 if (childpid < 0){
156 msg("Context save fork fails in parent %d\n", parentpid);
157 Exit(X_ABORT);
158 }
159 if (childpid != 0){
160 /*
161 * PARENT:
162 * save the context by waiting
163 * until the child doing all of the work returns.
164 * don't catch the interrupt
165 */
166 signal(SIGINT, SIG_IGN);
167#ifdef TDEBUG
168 msg("Tape: %d; parent process: %d child process %d\n",
169 tapeno+1, parentpid, childpid);
170#endif TDEBUG
171 for (;;){
172 waitpid = wait(&status);
173 if (waitpid != childpid){
174 msg("Parent %d waiting for child %d has another child %d return\n",
175 parentpid, childpid, waitpid);
176 } else
177 break;
178 }
179 if (status & 0xFF){
180 msg("Child %d returns LOB status %o\n",
181 childpid, status&0xFF);
182 }
183 status = (status >> 8) & 0xFF;
184#ifdef TDEBUG
185 switch(status){
186 case X_FINOK:
187 msg("Child %d finishes X_FINOK\n", childpid);
188 break;
189 case X_ABORT:
190 msg("Child %d finishes X_ABORT\n", childpid);
191 break;
192 case X_REWRITE:
193 msg("Child %d finishes X_REWRITE\n", childpid);
194 break;
195 default:
196 msg("Child %d finishes unknown %d\n", childpid,status);
197 break;
198 }
199#endif TDEBUG
200 switch(status){
201 case X_FINOK:
202 Exit(X_FINOK);
203 case X_ABORT:
204 Exit(X_ABORT);
205 case X_REWRITE:
206 goto restore_check_point;
207 default:
208 msg("Bad return code from dump: %d\n", status);
209 Exit(X_ABORT);
210 }
211 /*NOTREACHED*/
212 } else { /* we are the child; just continue */
213#ifdef TDEBUG
214 sleep(4); /* allow time for parent's message to get out */
215 msg("Child on Tape %d has parent %d, my pid = %d\n",
216 tapeno+1, parentpid, getpid());
217#endif
218 do{
219 to = creat(tape, 0666);
220 if (to < 0) {
221 if (!query("Cannot open tape. Do you want to retry the open?"))
222 dumpabort();
223 } else break;
224 } while (1);
225
226 asize = 0;
227 tapeno++; /* current tape sequence */
228 newtape++; /* new tape signal */
229 spcl.c_volume++;
230 spcl.c_type = TS_TAPE;
231 spclrec();
232 if (tapeno > 1)
233 msg("Tape %d begins with blocks from ino %d\n",
234 tapeno, ino);
235 }
236}
237
238/*
239 * The parent still catches interrupts, but does nothing with them
240 */
241sig_ign_parent()
242{
243 msg("Waiting parent receives interrupt\n");
244 signal(SIGINT, sig_ign_parent);
245}
246
247dumpabort()
248{
ed7c701e 249 msg("The ENTIRE dump is aborted.\n");
ae4b153c
BJ
250 Exit(X_ABORT);
251}
252
253Exit(status)
254{
255#ifdef TDEBUG
256 msg("pid = %d exits with status %d\n", getpid(), status);
257#endif TDEBUG
ed7c701e 258 exit(status);
ae4b153c 259}