Subject: autoload flag for dump
To: None <tech-userlevel@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-userlevel
Date: 12/12/2001 19:20:33
--x+6KMIRAuhnl3hBn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
the attached diff adds a '-l' flag to dump that implements an autoload flag,
modeled after solaris ufsdump. With this flag, when a new volume is
required dump doesn't prompt the user but instead eject the tape and tries to
open the tape device until it succeeds. If after 2mn it can't open the
tape device it fall back to prompting the user.
With this change it's possible to do multivolume dumps without user
intervention, provided you have a tape changer device smart enouth to load
the next tape when the current one is ejected. Most cheap changer do behave
this way, and don't have a scsi CHIO interface. I also have changers that
do have a chio interface but can be configured this way.
With this change dump outputs looks like:
  DUMP: 34.30% done, finished in 3:49
  DUMP: Closing /dev/nrst0
  DUMP: Ejecting /dev/nrst0
  DUMP: Volume 1 completed at: Wed Dec 12 19:09:03 2001
  DUMP: Volume 1 took 2:06:53
  DUMP: Volume 1 transfer rate: 275 KB/s
  DUMP: Change Volumes: Mount volume #2
  DUMP: Volume 2 started at: Wed Dec 12 19:10:13 2001
  DUMP: Volume 2 begins with blocks from inode 78017
  DUMP: 35.77% done, finished in 3:49

Does anyone have problems with this change ?

As a side effect, '-e' also works properly for remote tapes with this
patch :) 

--
Manuel Bouyer, LIP6, Universite Paris VI.           Manuel.Bouyer@lip6.fr
--

--x+6KMIRAuhnl3hBn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: dump.8
===================================================================
RCS file: /cvsroot/basesrc/sbin/dump/dump.8,v
retrieving revision 1.42
diff -u -r1.42 dump.8
--- dump.8	2001/12/07 19:53:44	1.42
+++ dump.8	2001/12/12 18:10:56
@@ -43,7 +43,7 @@
 .Nd file system backup
 .Sh SYNOPSIS
 .Nm ""
-.Op Fl 0123456789ceFnStu
+.Op Fl 0123456789ceFlnStu
 .Op Fl B Ar records
 .Op Fl b Ar blocksize
 .Op Fl d Ar density
@@ -187,6 +187,14 @@
 .It Fl k Ar read blocksize
 The size in kilobyte of the read buffers, rounded up to a multiple of the
 file system block size. Default is 32k.
+.It Fl l
+If a tape change is required, eject the tape and wait for the drive do
+be ready again.  This is to be used with tape changers wich automatically load
+the next tape when the tape is ejected.  If after 2 minutes the drive is not
+ready
+.Nm
+fall back to the default behavior, and prompt the operator for the next
+tape.
 .It Fl L Ar label
 The user-supplied text string
 .Ar label
Index: dump.h
===================================================================
RCS file: /cvsroot/basesrc/sbin/dump/dump.h,v
retrieving revision 1.29
diff -u -r1.29 dump.h
--- dump.h	2001/10/15 13:25:34	1.29
+++ dump.h	2001/12/12 18:10:56
@@ -98,6 +98,7 @@
 char	level;		/* dump level of this dump */
 int	uflag;		/* update flag */
 int	eflag;		/* eject flag */
+int	lflag;		/* autoload flag */
 int	diskfd;		/* disk file descriptor */
 int	tapefd;		/* tape file descriptor */
 int	pipeout;	/* true => output to standard output */
@@ -211,8 +212,9 @@
 #if defined(RDUMP) || defined(RRESTORE)
 void	rmtclose(void);
 int	rmthost(char *);
-int	rmtopen(char *, int);
+int	rmtopen(char *, int, int);
 int	rmtwrite(char *, int);
+int	rmtioctl(int, int);
 #endif /* RDUMP || RRESTORE */
 
 void	interrupt(int);	/* in case operator bangs on console */
Index: dumprmt.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/dump/dumprmt.c,v
retrieving revision 1.26
diff -u -r1.26 dumprmt.c
--- dumprmt.c	2001/11/01 08:03:03	1.26
+++ dumprmt.c	2001/12/12 18:10:56
@@ -84,14 +84,13 @@
 static	char *rmtpeer;
 
 static	int	okname(char *);
-static	int	rmtcall(char *, char *);
+static	int	rmtcall(char *, char *, int);
 static	void	rmtconnaborted(int);
 static	int	rmtgetb(void);
 static	void	rmtgetconn(void);
 static	void	rmtgets(char *, int);
-	int	rmtioctl(int, int);
 	int	rmtread(char *, int);
-static	int	rmtreply(char *);
+static	int	rmtreply(char *, int);
 	int	rmtseek(int, int);
 
 extern	int ntrec;		/* blocking factor on tape */
@@ -184,13 +183,13 @@
 }
 
 int
-rmtopen(char *tapedevice, int mode)
+rmtopen(char *tapedevice, int mode, int verbose)
 {
 	char buf[256];
 
 	(void)snprintf(buf, sizeof buf, "O%s\n%d\n", tapedevice, mode);
 	rmtstate = TS_OPEN;
-	return (rmtcall(tapedevice, buf));
+	return (rmtcall(tapedevice, buf, verbose));
 }
 
 void
@@ -199,7 +198,7 @@
 
 	if (rmtstate != TS_OPEN)
 		return;
-	rmtcall("close", "C\n");
+	rmtcall("close", "C\n", 1);
 	rmtstate = TS_CLOSED;
 }
 
@@ -210,7 +209,7 @@
 	int n, i, cc;
 
 	(void)snprintf(line, sizeof line, "R%d\n", count);
-	n = rmtcall("read", line);
+	n = rmtcall("read", line, 1);
 	if (n < 0) {
 		errno = n;
 		return (-1);
@@ -232,7 +231,7 @@
 	(void)snprintf(line, sizeof line, "W%d\n", count);
 	write(rmtape, line, strlen(line));
 	write(rmtape, buf, count);
-	return (rmtreply("write"));
+	return (rmtreply("write", 1));
 }
 
 #if 0		/* XXX unused? */
@@ -256,7 +255,7 @@
 rmtwrite2(void)
 {
 
-	return (rmtreply("write"));
+	return (rmtreply("write", 1));
 }
 #endif
 
@@ -266,7 +265,7 @@
 	char line[80];
 
 	(void)snprintf(line, sizeof line, "L%d\n%d\n", offset, pos);
-	return (rmtcall("seek", line));
+	return (rmtcall("seek", line, 1));
 }
 
 
@@ -280,7 +279,7 @@
 
 	if (rmtstate != TS_OPEN)
 		return (NULL);
-	rmtcall("status", "S\n");
+	rmtcall("status", "S\n", 1);
 	for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
 		*cp++ = rmtgetb();
 	return (&mts);
@@ -295,20 +294,20 @@
 	if (count < 0)
 		return (-1);
 	(void)snprintf(buf, sizeof buf, "I%d\n%d\n", cmd, count);
-	return (rmtcall("ioctl", buf));
+	return (rmtcall("ioctl", buf, 1));
 }
 
 static int
-rmtcall(char *cmd, char *buf)
+rmtcall(char *cmd, char *buf, int verbose)
 {
 
 	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
 		rmtconnaborted(0);
-	return (rmtreply(cmd));
+	return (rmtreply(cmd, verbose));
 }
 
 static int
-rmtreply(char *cmd)
+rmtreply(char *cmd, int verbose)
 {
 	char *cp;
 	char code[30], emsg[BUFSIZ];
@@ -316,7 +315,8 @@
 	rmtgets(code, sizeof (code));
 	if (*code == 'E' || *code == 'F') {
 		rmtgets(emsg, sizeof (emsg));
-		msg("%s: %s", cmd, emsg);
+		if (verbose)
+			msg("%s: %s", cmd, emsg);
 		if (*code == 'F') {
 			rmtstate = TS_CLOSED;
 			return (-1);
Index: main.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/dump/main.c,v
retrieving revision 1.40
diff -u -r1.40 main.c
--- main.c	2001/11/16 04:41:23	1.40
+++ main.c	2001/12/12 18:10:57
@@ -146,7 +146,7 @@
 
 	obsolete(&argc, &argv);
 	while ((ch = getopt(argc, argv,
-	    "0123456789B:b:cd:eFf:h:k:L:nr:s:StT:uWw")) != -1)
+	    "0123456789B:b:cd:eFf:h:k:lL:nr:s:StT:uWw")) != -1)
 		switch (ch) {
 		/* dump level */
 		case '0': case '1': case '2': case '3': case '4':
@@ -193,6 +193,11 @@
 			readblksize = numarg("read block size", 0, 64) * 1024;
 			break;
 
+		case 'l':		/* autoload after eject full tapes */
+			eflag = 1;
+			lflag = 1;
+			break;
+
 		case 'L':
 			/*
 			 * Note that although there are LBLSIZE characters,
@@ -605,7 +610,7 @@
 {
 
 	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
-"usage: dump [-0123456789ceFntu] [-B records] [-b blocksize] [-d density]",
+"usage: dump [-0123456789ceFlntu] [-B records] [-b blocksize] [-d density]",
 "            [-f file] [-h level] [-k read block size] [-L label]",
 "            [-r read cache size] [-s feet] [-T date] file system",
 "       dump [-W | -w]");
Index: tape.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/dump/tape.c,v
retrieving revision 1.30
diff -u -r1.30 tape.c
--- tape.c	2001/11/01 08:03:03	1.30
+++ tape.c	2001/12/12 18:10:57
@@ -404,8 +404,12 @@
 #ifdef RDUMP
 	if (host) {
 		rmtclose();
-		while (rmtopen(tape, 0) < 0)
+		while (rmtopen(tape, 0, 0) < 0)
 			sleep(10);
+		if (eflag && eject) {
+			msg("Ejecting %s\n", tape);
+			(void) rmtioctl(MTOFFL, 0);
+		}
 		rmtclose();
 		return;
 	}
@@ -427,6 +431,8 @@
 void
 close_rewind(void)
 {
+	int i, f;
+
 	trewind(1);
 	(void)do_stats();
 	if (nexttape)
@@ -435,6 +441,23 @@
 		msg("Change Volumes: Mount volume #%d\n", tapeno+1);
 		broadcast("CHANGE DUMP VOLUMES!\7\7\n");
 	}
+	if (lflag) {
+		for (i = 0; i < 12; i++) { /* wait 2 mn */
+			if (host) {
+				if (rmtopen(tape, 0, 0) >= 0) {
+					rmtclose();
+					return;
+				}
+			} else {
+				if ((f = open(tape, 0)) >= 0) {
+					close(f);
+					return;
+				}
+			}
+			sleep (10);
+		}
+	}
+		
 	while (!query("Is the new volume mounted and ready to go?"))
 		if (query("Do you want to abort?")) {
 			dumpabort(0);
@@ -658,7 +681,7 @@
 			msg("Dumping volume %d on %s\n", tapeno, tape);
 		}
 #ifdef RDUMP
-		while ((tapefd = (host ? rmtopen(tape, 2) :
+		while ((tapefd = (host ? rmtopen(tape, 2, 1) :
 			pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
 #else
 		while ((tapefd = (pipeout ? 1 : 

--x+6KMIRAuhnl3hBn--