From cfd8a00918f6e812ed2ccb1eea74b1bd77dbd231 Mon Sep 17 00:00:00 2001 From: Ian Dowse Date: Thu, 14 Feb 2002 01:30:45 +0000 Subject: [PATCH] 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 --- sbin/restore/restore.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c index 33496f39adaf..901439cbf9a6 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.