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--