xref: /csrg-svn/old/dump.4.1/dumptape.c (revision 12082)
1*12082Smckusick static	char *sccsid = "@(#)dumptape.c	1.3 (Berkeley) 04/28/83";
21425Sroot #include "dump.h"
31425Sroot 
41425Sroot char	tblock[NTREC][BSIZE];
51425Sroot daddr_t	tdaddr[NTREC];
61425Sroot int	trecno;
71425Sroot 
81425Sroot taprec(dp)
91425Sroot char *dp;
101425Sroot {
111425Sroot 	register i;
121425Sroot 
131425Sroot 	for(i=0; i<BSIZE; i++)
141425Sroot 		tblock[trecno][i] = *dp++;
151425Sroot 	tdaddr[trecno] = 0;
161425Sroot 	trecno++;
171425Sroot 	spcl.c_tapea++;
181425Sroot 	if(trecno >= NTREC)
191425Sroot 		flusht();
201425Sroot }
211425Sroot 
221425Sroot tapsrec(d)
231425Sroot daddr_t d;
241425Sroot {
251425Sroot 
261425Sroot 	if(d == 0)
271425Sroot 		return;
281425Sroot 	tdaddr[trecno] = d;
291425Sroot 	trecno++;
301425Sroot 	spcl.c_tapea++;
311425Sroot 	if(trecno >= NTREC)
321425Sroot 		flusht();
331425Sroot }
341425Sroot 
351425Sroot int	nogripe = 0;
361425Sroot 
371425Sroot flusht()
381425Sroot {
391425Sroot 	register i, si;
401425Sroot 	daddr_t d;
411425Sroot 
421425Sroot 	while(trecno < NTREC)
431425Sroot 		tdaddr[trecno++] = 1;
441425Sroot 
451425Sroot loop:
461425Sroot 	d = 0;
471425Sroot 	for(i=0; i<NTREC; i++)
481425Sroot 		if(tdaddr[i] != 0)
491425Sroot 		if(d == 0 || tdaddr[i] < d) {
501425Sroot 			si = i;
511425Sroot 			d = tdaddr[i];
521425Sroot 		}
531425Sroot 	if(d != 0) {
541425Sroot 		bread(d, tblock[si], BSIZE);
551425Sroot 		tdaddr[si] = 0;
561425Sroot 		goto loop;
571425Sroot 	}
581425Sroot 	trecno = 0;
591425Sroot 	if (write(to, tblock[0], sizeof(tblock)) != sizeof(tblock) ){
60*12082Smckusick 		if (pipeout) {
61*12082Smckusick 			msg("Tape write error on %s\n", tape);
62*12082Smckusick 			msg("Cannot recover\n");
63*12082Smckusick 			dumpabort();
64*12082Smckusick 			/*NOTREACHED*/
65*12082Smckusick 		}
661425Sroot 		msg("Tape write error on tape %d\n", tapeno);
671425Sroot 		broadcast("TAPE ERROR!\n");
681425Sroot 		if (query("Do you want to restart?")){
691425Sroot 			msg("This tape will rewind.  After it is rewound,\n");
701425Sroot 			msg("replace the faulty tape with a new one;\n");
711925Swnj 			msg("this dump volume will be rewritten.\n");
721425Sroot 			/*
731425Sroot 			 *	Temporarily change the tapeno identification
741425Sroot 			 */
751425Sroot 			tapeno--;
761425Sroot 			nogripe = 1;
771425Sroot 			close_rewind();
781425Sroot 			nogripe = 0;
791425Sroot 			tapeno++;
801425Sroot 			Exit(X_REWRITE);
811425Sroot 		} else {
821425Sroot 			dumpabort();
831425Sroot 			/*NOTREACHED*/
841425Sroot 		}
851425Sroot 	}
861425Sroot 
871425Sroot 	asize += sizeof(tblock)/density;
881425Sroot 	asize += 7;
891425Sroot 	blockswritten += NTREC;
90*12082Smckusick 	if (!pipeout && asize > tsize) {
911425Sroot 		close_rewind();
921425Sroot 		otape();
931425Sroot 	}
941425Sroot 	timeest();
951425Sroot }
961425Sroot 
971425Sroot rewind()
981425Sroot {
991425Sroot 	int	secs;
1001425Sroot #ifdef DEBUG
1011425Sroot 	msg("Waiting 10 seconds to rewind.\n");
1021425Sroot 	sleep(10);
1031425Sroot #else
1041425Sroot 	/*
1051425Sroot 	 *	It takes about 3 minutes, 25secs to rewind 2300' of tape
1061425Sroot 	 */
1071425Sroot 	secs = (( (60*3) + 25)*asize)/(2300L*12L*10L);
1081425Sroot 	msg("Waiting %d seconds to rewind.\n", secs);
1091425Sroot 	sleep(secs);
1101425Sroot #endif
1111425Sroot }
1121425Sroot 
1131425Sroot close_rewind()
1141425Sroot {
115*12082Smckusick 	if (pipeout)
116*12082Smckusick 		return;
1171425Sroot 	close(to);
1181425Sroot 	if (!nogripe){
1191425Sroot 		rewind();
1201425Sroot 		msg("Change Tapes: Mount tape #%d\n", tapeno+1);
1211425Sroot 		broadcast("CHANGE TAPES!\7\7\n");
1221425Sroot 	}
1231425Sroot 	do{
1241425Sroot 		if (query ("Is the new tape mounted and ready to go?"))
1251425Sroot 			break;
1261425Sroot 		if (query ("Do you want to abort?")){
1271425Sroot 			dumpabort();
1281425Sroot 			/*NOTREACHED*/
1291425Sroot 		}
1301425Sroot 	} while (1);
1311425Sroot }
1321425Sroot 
1331425Sroot /*
1341425Sroot  *	We implement taking and restoring checkpoints on
1351425Sroot  *	the tape level.
1361425Sroot  *	When each tape is opened, a new process is created by forking; this
1371425Sroot  *	saves all of the necessary context in the parent.  The child
1381425Sroot  *	continues the dump; the parent waits around, saving the context.
1391425Sroot  *	If the child returns X_REWRITE, then it had problems writing that tape;
1401425Sroot  *	this causes the parent to fork again, duplicating the context, and
1411425Sroot  *	everything continues as if nothing had happened.
1421425Sroot  */
1431425Sroot 
1441425Sroot otape()
1451425Sroot {
1461425Sroot 	int	parentpid;
1471425Sroot 	int	childpid;
1481425Sroot 	int	status;
1491425Sroot 	int	waitpid;
1501425Sroot 	int	sig_ign_parent();
1511425Sroot 	int	interrupt();
1521425Sroot 
1531425Sroot 	/*
1541425Sroot 	 *	Force the tape to be closed
1551425Sroot 	 */
156*12082Smckusick 	if (!pipeout)
157*12082Smckusick 		close(to);
1581425Sroot 	parentpid = getpid();
1591425Sroot 
1601425Sroot     restore_check_point:
1611425Sroot 	signal(SIGINT, interrupt);
1621425Sroot 	/*
1631425Sroot 	 *	All signals are inherited...
1641425Sroot 	 */
1651425Sroot 	childpid = fork();
1661425Sroot 	if (childpid < 0){
1671425Sroot 		msg("Context save fork fails in parent %d\n", parentpid);
1681425Sroot 		Exit(X_ABORT);
1691425Sroot 	}
1701425Sroot 	if (childpid != 0){
1711425Sroot 		/*
1721425Sroot 		 *	PARENT:
1731425Sroot 		 *	save the context by waiting
1741425Sroot 		 *	until the child doing all of the work returns.
1751425Sroot 		 *	don't catch the interrupt
1761425Sroot 		 */
1771425Sroot 		signal(SIGINT, SIG_IGN);
1781425Sroot #ifdef TDEBUG
1791425Sroot 		msg("Tape: %d; parent process: %d child process %d\n",
1801425Sroot 			tapeno+1, parentpid, childpid);
1811425Sroot #endif TDEBUG
1821425Sroot 		for (;;){
1831425Sroot 			waitpid = wait(&status);
1841425Sroot 			if (waitpid != childpid){
1851425Sroot 				msg("Parent %d waiting for child %d has another child %d return\n",
1861425Sroot 					parentpid, childpid, waitpid);
1871425Sroot 			} else
1881425Sroot 				break;
1891425Sroot 		}
1901425Sroot 		if (status & 0xFF){
1911425Sroot 			msg("Child %d returns LOB status %o\n",
1921425Sroot 				childpid, status&0xFF);
1931425Sroot 		}
1941425Sroot 		status = (status >> 8) & 0xFF;
1951425Sroot #ifdef TDEBUG
1961425Sroot 		switch(status){
1971425Sroot 			case X_FINOK:
1981425Sroot 				msg("Child %d finishes X_FINOK\n", childpid);
1991425Sroot 				break;
2001425Sroot 			case X_ABORT:
2011425Sroot 				msg("Child %d finishes X_ABORT\n", childpid);
2021425Sroot 				break;
2031425Sroot 			case X_REWRITE:
2041425Sroot 				msg("Child %d finishes X_REWRITE\n", childpid);
2051425Sroot 				break;
2061425Sroot 			default:
2071425Sroot 				msg("Child %d finishes unknown %d\n", childpid,status);
2081425Sroot 				break;
2091425Sroot 		}
2101425Sroot #endif TDEBUG
2111425Sroot 		switch(status){
2121425Sroot 			case X_FINOK:
2131425Sroot 				Exit(X_FINOK);
2141425Sroot 			case X_ABORT:
2151425Sroot 				Exit(X_ABORT);
2161425Sroot 			case X_REWRITE:
2171425Sroot 				goto restore_check_point;
2181425Sroot 			default:
2191425Sroot 				msg("Bad return code from dump: %d\n", status);
2201425Sroot 				Exit(X_ABORT);
2211425Sroot 		}
2221425Sroot 		/*NOTREACHED*/
2231425Sroot 	} else {	/* we are the child; just continue */
2241425Sroot #ifdef TDEBUG
2251425Sroot 		sleep(4);	/* allow time for parent's message to get out */
2261425Sroot 		msg("Child on Tape %d has parent %d, my pid = %d\n",
2271425Sroot 			tapeno+1, parentpid, getpid());
2281425Sroot #endif
2291425Sroot 		do{
230*12082Smckusick 			if (pipeout)
231*12082Smckusick 				to = 1;
232*12082Smckusick 			else
233*12082Smckusick 				to = creat(tape, 0666);
2341425Sroot 			if (to < 0) {
2351425Sroot 				if (!query("Cannot open tape. Do you want to retry the open?"))
2361425Sroot 					dumpabort();
2371425Sroot 			} else break;
2381425Sroot 		} while (1);
2391425Sroot 
2401425Sroot 		asize = 0;
2411425Sroot 		tapeno++;		/* current tape sequence */
2421425Sroot 		newtape++;		/* new tape signal */
2431425Sroot 		spcl.c_volume++;
2441425Sroot 		spcl.c_type = TS_TAPE;
2451425Sroot 		spclrec();
2461425Sroot 		if (tapeno > 1)
2471425Sroot 			msg("Tape %d begins with blocks from ino %d\n",
2481425Sroot 				tapeno, ino);
2491425Sroot 	}
2501425Sroot }
2511425Sroot 
2521425Sroot /*
2531425Sroot  *	The parent still catches interrupts, but does nothing with them
2541425Sroot  */
2551425Sroot sig_ign_parent()
2561425Sroot {
2571425Sroot 	msg("Waiting parent receives interrupt\n");
2581425Sroot 	signal(SIGINT, sig_ign_parent);
2591425Sroot }
2601425Sroot 
2611425Sroot dumpabort()
2621425Sroot {
2631925Swnj 	msg("The ENTIRE dump is aborted.\n");
2641425Sroot 	Exit(X_ABORT);
2651425Sroot }
2661425Sroot 
2671425Sroot Exit(status)
2681425Sroot {
2691425Sroot #ifdef TDEBUG
2701425Sroot 	msg("pid = %d exits with status %d\n", getpid(), status);
2711425Sroot #endif TDEBUG
2721925Swnj 	exit(status);
2731425Sroot }
274