summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-02-14 01:30:45 +0000
committeriedowse <iedowse@FreeBSD.org>2002-02-14 01:30:45 +0000
commitc745bc3937461deb0149ef098ea50897e1e5c0a1 (patch)
tree44b9d69656d82c750df987e7bb9f18b133806c23 /sbin
parent0a7fefb6effa4f154f578894ae6556fb5a2fd9a9 (diff)
downloadFreeBSD-src-c745bc3937461deb0149ef098ea50897e1e5c0a1.zip
FreeBSD-src-c745bc3937461deb0149ef098ea50897e1e5c0a1.tar.gz
In createfiles(), properly handle a number of cases where no further
volumes are available, instead of getting stuck in a loop calling getvol(). Normally restore in 'x' or 'i' modes will ask for a new (earlier) volume when the current inode number on the tape is greater than the last inode to be restored, since there can be no further inodes of interest on that volume. However we don't want to change volumes in this case either if the user explicitly said that there are no more tapes, or if we are looking at the first volume. When no more volumes are available but there are still inodes that we have not found, we now just fall through to the code that prints out a list of any missing files, so the restore completes normally. Also simplify the logic a bit by always returning to the start of the main for(;;) loop whenever the volume has changed. This should completely fix the "Changing volumes on pipe input" bug that is often observed when restoring dumps of active filesystems. PR: bin/4176, bin/34604, misc/34675
Diffstat (limited to 'sbin')
-rw-r--r--sbin/restore/restore.c40
1 files changed, 24 insertions, 16 deletions
diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c
index 33496f3..901439c 100644
--- a/sbin/restore/restore.c
+++ b/sbin/restore/restore.c
@@ -695,6 +695,7 @@ createfiles()
first = lowerbnd(ROOTINO);
last = upperbnd(maxino - 1);
for (;;) {
+ curvol = volno;
first = lowerbnd(first);
last = upperbnd(last);
/*
@@ -703,34 +704,41 @@ createfiles()
if (first > last)
return;
/*
- * Reject any volumes with inodes greater
- * than the last one needed
+ * Reject any volumes with inodes greater than the last
+ * one needed, so that we can quickly skip backwards to
+ * a volume containing useful inodes. We can't do this
+ * if there are no further volumes available (curfile.ino
+ * >= maxino) or if we are already at the first tape.
*/
- while (curfile.ino > last) {
+ if (curfile.ino > last && curfile.ino < maxino && volno > 1) {
curfile.action = SKIP;
getvol((long)0);
skipmaps();
skipdirs();
+ continue;
}
/*
* Decide on the next inode needed.
* Skip across the inodes until it is found
- * or an out of order volume change is encountered
+ * or a volume change is encountered
*/
- next = lowerbnd(curfile.ino);
- do {
- curvol = volno;
+ if (curfile.ino < maxino) {
+ next = lowerbnd(curfile.ino);
while (next > curfile.ino && volno == curvol)
skipfile();
- skipmaps();
- skipdirs();
- } while (volno == curvol + 1);
- /*
- * If volume change out of order occurred the
- * current state must be recalculated
- */
- if (volno != curvol)
- continue;
+ if (volno != curvol) {
+ skipmaps();
+ skipdirs();
+ continue;
+ }
+ } else {
+ /*
+ * No further volumes or inodes available. Set
+ * `next' to the first inode, so that a warning
+ * is emitted below for each missing file.
+ */
+ next = first;
+ }
/*
* If the current inode is greater than the one we were
* looking for then we missed the one we were looking for.
OpenPOWER on IntegriCloud