Adapt dump(8) to use filestore-independent (but still ufs-specific)
replacements for NINDIR, fsbtodb, etc. Create dump_lfs by adding a few LFS-filestore-specific routines. As described in PR#8317.
This commit is contained in:
parent
93eb76dd3d
commit
54fd3dd508
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.59 1999/07/02 08:28:04 itojun Exp $
|
||||
# $NetBSD: Makefile,v 1.60 1999/09/29 04:57:48 perseant Exp $
|
||||
# @(#)Makefile 8.5 (Berkeley) 3/31/94
|
||||
|
||||
# Not ported: XNSrouted enpload scsiformat startslip
|
||||
|
@ -17,7 +17,7 @@ SUBDIR+= mount_fdesc
|
|||
SUBDIR+= mount_filecore
|
||||
SUBDIR+= mount_ffs newfs fsck_ffs fsdb dump restore clri tunefs
|
||||
SUBDIR+= mount_kernfs
|
||||
SUBDIR+= mount_lfs newfs_lfs fsck_lfs
|
||||
SUBDIR+= mount_lfs newfs_lfs fsck_lfs dump_lfs
|
||||
# mount_mfs -> newfs
|
||||
SUBDIR+= mount_msdos newfs_msdos fsck_msdos
|
||||
SUBDIR+= mount_nfs
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.22 1999/03/23 14:22:59 bouyer Exp $
|
||||
# $NetBSD: Makefile,v 1.23 1999/09/29 04:57:49 perseant Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
|
||||
# dump.h header file
|
||||
|
@ -9,16 +9,18 @@
|
|||
# tape.c handles the mag tape and opening/closing
|
||||
# traverse.c traverses the file system
|
||||
# unctime.c undo ctime
|
||||
# ffs_inode.c FFS-specific filestore routines
|
||||
# ffs_bswap.c FFS byte-swapping
|
||||
#
|
||||
# DEBUG use local directory to find ddate and dumpdates
|
||||
# TDEBUG trace out the process forking
|
||||
|
||||
PROG= dump
|
||||
LINKS= ${BINDIR}/dump ${BINDIR}/rdump
|
||||
CPPFLAGS+=-DRDUMP
|
||||
CPPFLAGS+=-DRDUMP -I${.CURDIR}
|
||||
# CPPFLAGS+= -DDEBUG -DTDEBUG -DFDEBUG -DWRITEDEBUG -DSTATS -DDIAGNOSTICS
|
||||
SRCS= itime.c main.c optr.c dumprmt.c rcache.c tape.c traverse.c unctime.c \
|
||||
ffs_bswap.c
|
||||
ffs_inode.c ffs_bswap.c
|
||||
BINGRP= tty
|
||||
BINMODE=2555
|
||||
MAN= dump.8
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: dump.h,v 1.16 1999/03/23 14:22:59 bouyer Exp $ */
|
||||
/* $NetBSD: dump.h,v 1.17 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1993
|
||||
|
@ -40,6 +40,36 @@
|
|||
#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
|
||||
#define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
|
||||
|
||||
/*
|
||||
* Filestore-independent UFS data, so code can be more easily shared
|
||||
* between ffs, lfs, and maybe ext2fs and others as well.
|
||||
*/
|
||||
struct ufsi {
|
||||
int64_t ufs_dsize; /* filesystem size, in sectors */
|
||||
int32_t ufs_bsize; /* block size */
|
||||
int32_t ufs_bshift; /* log2(ufs_bsize) */
|
||||
int32_t ufs_fsize; /* fragment size */
|
||||
int32_t ufs_frag; /* block size / frag size */
|
||||
int32_t ufs_fsatoda; /* disk address conversion constant */
|
||||
int32_t ufs_nindir; /* disk addresses per indirect block */
|
||||
int32_t ufs_inopb; /* inodes per block */
|
||||
int32_t ufs_maxsymlinklen; /* max symlink length */
|
||||
int32_t ufs_bmask; /* block mask */
|
||||
int32_t ufs_fmask; /* frag mask */
|
||||
int64_t ufs_qbmask; /* ~ufs_bmask */
|
||||
int64_t ufs_qfmask; /* ~ufs_fmask */
|
||||
};
|
||||
#define fsatoda(u,a) ((a) << (u)->ufs_fsatoda)
|
||||
#define ufs_fragroundup(u,size) /* calculates roundup(size, ufs_fsize) */ \
|
||||
(((size) + (u)->ufs_qfmask) & (u)->ufs_fmask)
|
||||
#define ufs_blkoff(u,loc) /* calculates (loc % u->ufs_bsize) */ \
|
||||
((loc) & (u)->ufs_qbmask)
|
||||
#define ufs_dblksize(u,d,b) \
|
||||
((((b) >= NDADDR || (d)->di_size >= ((b)+1) << (u)->ufs_bshift \
|
||||
? (u)->ufs_bsize \
|
||||
: (ufs_fragroundup((u), ufs_blkoff(u, (d)->di_size))))))
|
||||
struct ufsi *ufsib;
|
||||
|
||||
/*
|
||||
* Dump maps used to describe what is to be dumped.
|
||||
*/
|
||||
|
@ -84,8 +114,7 @@ int blockswritten; /* number of blocks written on current tape */
|
|||
int tapeno; /* current tape number */
|
||||
time_t tstart_writing; /* when started writing the first tape block */
|
||||
int xferrate; /* averaged transfer rate of all volumes */
|
||||
struct fs *sblock; /* the file system super block */
|
||||
char sblock_buf[MAXBSIZE];
|
||||
char sblock_buf[MAXBSIZE]; /* buffer to hold the superblock */
|
||||
long dev_bsize; /* block size of underlying disk device */
|
||||
int dev_bshift; /* log2(dev_bsize) */
|
||||
int tp_bshift; /* log2(TP_BSIZE) */
|
||||
|
@ -123,6 +152,11 @@ static __inline u_int64_t iswap64(x)
|
|||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
|
||||
/* filestore-specific hooks */
|
||||
int fs_read_sblock __P((char *));
|
||||
struct ufsi *fs_parametrize __P((void));
|
||||
ino_t fs_maxino __P((void));
|
||||
|
||||
/* operator interface functions */
|
||||
void broadcast __P((char *message));
|
||||
void lastdump __P((int arg)); /* int should be char */
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* $NetBSD: ffs_inode.c,v 1.1 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: ffs_inode.c,v 1.1 1999/09/29 04:57:49 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef sunos
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <ufs/fs.h>
|
||||
#include <ufs/fsdir.h>
|
||||
#include <ufs/inode.h>
|
||||
#else
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
#include <ufs/ffs/ffs_extern.h>
|
||||
#endif
|
||||
|
||||
#include <protocols/dumprestore.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "dump.h"
|
||||
|
||||
#ifndef SBOFF
|
||||
#define SBOFF (SBLOCK * DEV_BSIZE)
|
||||
#endif
|
||||
|
||||
struct fs *sblock;
|
||||
|
||||
/*
|
||||
* Read the superblock from disk, and check its magic number.
|
||||
* Determine whether byte-swapping needs to be done on this filesystem.
|
||||
*/
|
||||
int
|
||||
fs_read_sblock(char *sblock_buf)
|
||||
{
|
||||
int needswap = 0;
|
||||
|
||||
sblock = (struct fs *)sblock_buf;
|
||||
rawread(SBOFF, (char *) sblock, SBSIZE);
|
||||
if (sblock->fs_magic != FS_MAGIC) {
|
||||
if (sblock->fs_magic == bswap32(FS_MAGIC)) {
|
||||
ffs_sb_swap(sblock, sblock, 0);
|
||||
needswap = 1;
|
||||
} else
|
||||
quit("bad sblock magic number\n");
|
||||
}
|
||||
return needswap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the ufsi struct, as well as the maxino and dev_bsize global
|
||||
* variables.
|
||||
*/
|
||||
struct ufsi *
|
||||
fs_parametrize(void)
|
||||
{
|
||||
static struct ufsi ufsi;
|
||||
|
||||
#ifdef FS_44INODEFMT
|
||||
if (sblock->fs_inodefmt >= FS_44INODEFMT) {
|
||||
spcl.c_flags = iswap32(iswap32(spcl.c_flags) | DR_NEWINODEFMT);
|
||||
} else {
|
||||
/*
|
||||
* Determine parameters for older filesystems. From
|
||||
* /sys/ufs/ffs/ffs_vfsops.c::ffs_oldfscompat()
|
||||
*
|
||||
* XXX: not sure if other variables (fs_npsect, fs_interleave,
|
||||
* fs_nrpos, fs_maxfilesize) need to be fudged too.
|
||||
*/
|
||||
sblock->fs_qbmask = ~sblock->fs_bmask;
|
||||
sblock->fs_qfmask = ~sblock->fs_fmask;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill out ufsi struct */
|
||||
ufsi.ufs_dsize = fsbtodb(sblock,sblock->fs_size);
|
||||
ufsi.ufs_bsize = sblock->fs_bsize;
|
||||
ufsi.ufs_bshift = sblock->fs_bshift;
|
||||
ufsi.ufs_fsize = sblock->fs_fsize;
|
||||
ufsi.ufs_frag = sblock->fs_frag;
|
||||
ufsi.ufs_fsatoda = sblock->fs_fsbtodb;
|
||||
ufsi.ufs_nindir = sblock->fs_nindir;
|
||||
ufsi.ufs_inopb = sblock->fs_inopb;
|
||||
ufsi.ufs_maxsymlinklen = sblock->fs_maxsymlinklen;
|
||||
ufsi.ufs_bmask = sblock->fs_bmask;
|
||||
ufsi.ufs_fmask = sblock->fs_fmask;
|
||||
ufsi.ufs_qbmask = sblock->fs_qbmask;
|
||||
ufsi.ufs_qfmask = sblock->fs_qfmask;
|
||||
ufsi.ufs_maxino = sblock->fs_ipg * sblock->fs_ncg;
|
||||
|
||||
dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
|
||||
|
||||
return &ufsi;
|
||||
}
|
||||
|
||||
struct dinode *
|
||||
getino(inum)
|
||||
ino_t inum;
|
||||
{
|
||||
static daddr_t minino, maxino;
|
||||
static struct dinode inoblock[MAXINOPB];
|
||||
int i;
|
||||
|
||||
curino = inum;
|
||||
if (inum >= minino && inum < maxino)
|
||||
return (&inoblock[inum - minino]);
|
||||
bread(fsatoda(ufsib, ino_to_fsba(sblock, inum)), (char *)inoblock,
|
||||
(int)ufsib->ufs_bsize);
|
||||
if (needswap)
|
||||
for (i = 0; i < MAXINOPB; i++)
|
||||
ffs_dinode_swap(&inoblock[i], &inoblock[i]);
|
||||
minino = inum - (inum % INOPB(sblock));
|
||||
maxino = minino + INOPB(sblock);
|
||||
return (&inoblock[inum - minino]);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: main.c,v 1.22 1999/03/23 14:22:59 bouyer Exp $ */
|
||||
/* $NetBSD: main.c,v 1.23 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993, 1994
|
||||
|
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.22 1999/03/23 14:22:59 bouyer Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.23 1999/09/29 04:57:49 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -80,10 +80,6 @@ __RCSID("$NetBSD: main.c,v 1.22 1999/03/23 14:22:59 bouyer Exp $");
|
|||
#include "dump.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifndef SBOFF
|
||||
#define SBOFF (SBLOCK * DEV_BSIZE)
|
||||
#endif
|
||||
|
||||
int notify = 0; /* notify operator flag */
|
||||
int blockswritten = 0; /* number of blocks written on current tape */
|
||||
int tapeno = 0; /* current tape number */
|
||||
|
@ -119,6 +115,7 @@ main(argc, argv)
|
|||
char *toplevel;
|
||||
int just_estimate = 0;
|
||||
char labelstr[LBLSIZE];
|
||||
struct ufsi ufsi;
|
||||
|
||||
spcl.c_date = 0;
|
||||
(void)time((time_t *)&spcl.c_date);
|
||||
|
@ -388,15 +385,8 @@ main(argc, argv)
|
|||
exit(X_ABORT);
|
||||
}
|
||||
sync();
|
||||
sblock = (struct fs *)sblock_buf;
|
||||
rawread(SBOFF, (char *) sblock, SBSIZE);
|
||||
if (sblock->fs_magic != FS_MAGIC) {
|
||||
if (sblock->fs_magic == bswap32(FS_MAGIC)) {
|
||||
ffs_sb_swap(sblock, sblock, 0);
|
||||
needswap = 1;
|
||||
} else
|
||||
quit("bad sblock magic number\n");
|
||||
}
|
||||
|
||||
needswap = fs_read_sblock(sblock_buf);
|
||||
|
||||
spcl.c_level = iswap32(level - '0');
|
||||
spcl.c_type = iswap32(TS_TAPE);
|
||||
|
@ -421,29 +411,15 @@ main(argc, argv)
|
|||
msgtail("to %s\n", tape);
|
||||
msg("Label: %s\n", labelstr);
|
||||
|
||||
dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
|
||||
ufsib = fs_parametrize();
|
||||
|
||||
dev_bshift = ffs(dev_bsize) - 1;
|
||||
if (dev_bsize != (1 << dev_bshift))
|
||||
quit("dev_bsize (%d) is not a power of 2", dev_bsize);
|
||||
tp_bshift = ffs(TP_BSIZE) - 1;
|
||||
if (TP_BSIZE != (1 << tp_bshift))
|
||||
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
|
||||
#ifdef FS_44INODEFMT
|
||||
if (sblock->fs_inodefmt >= FS_44INODEFMT) {
|
||||
spcl.c_flags = iswap32(iswap32(spcl.c_flags) | DR_NEWINODEFMT);
|
||||
} else {
|
||||
/*
|
||||
* Determine parameters for older filesystems. From
|
||||
* /sys/ufs/ffs/ffs_vfsops.c::ffs_oldfscompat()
|
||||
*
|
||||
* XXX: not sure if other variables (fs_npsect, fs_interleave,
|
||||
* fs_nrpos, fs_maxfilesize) need to be fudged too.
|
||||
*/
|
||||
sblock->fs_qbmask = ~sblock->fs_bmask;
|
||||
sblock->fs_qfmask = ~sblock->fs_fmask;
|
||||
}
|
||||
#endif
|
||||
maxino = sblock->fs_ipg * sblock->fs_ncg;
|
||||
maxino = fs_maxino();
|
||||
mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE);
|
||||
usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
|
||||
dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rcache.c,v 1.1 1999/03/23 14:22:59 bouyer Exp $ */
|
||||
/* $NetBSD: rcache.c,v 1.2 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
|
@ -43,7 +43,6 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -100,7 +99,7 @@ initcache(cachesize, readblksize)
|
|||
size_t len;
|
||||
size_t sharedSize;
|
||||
|
||||
nblksread = (readblksize + sblock->fs_bsize - 1) / sblock->fs_bsize;
|
||||
nblksread = (readblksize + ufsib->ufs_bsize - 1) / ufsib->ufs_bsize;
|
||||
if(cachesize == -1) { /* Compute from memory available */
|
||||
int usermem;
|
||||
int mib[2] = { CTL_HW, HW_USERMEM };
|
||||
|
@ -359,9 +358,11 @@ retry:
|
|||
blockBlkNo = (blkno / nblksread) * nblksread;
|
||||
idx = findlru();
|
||||
rsize = min(nblksread,
|
||||
fsbtodb(sblock, sblock->fs_size) - blockBlkNo) *
|
||||
ufsib->ufs_dsize - blockBlkNo) *
|
||||
dev_bsize;
|
||||
|
||||
if(rsize < 0)
|
||||
fprintf(stderr,"blk %d, rsize=%d (dsize=%d)\n",
|
||||
blockBlkNo, rsize, ufsib->ufs_dsize);
|
||||
#ifdef DIAGNOSTICS
|
||||
if (cdesc[idx].owner)
|
||||
fprintf(stderr, "Owner is set (%d, me=%d), can"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tape.c,v 1.18 1999/03/23 14:22:59 bouyer Exp $ */
|
||||
/* $NetBSD: tape.c,v 1.19 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)tape.c 8.4 (Berkeley) 5/1/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: tape.c,v 1.18 1999/03/23 14:22:59 bouyer Exp $");
|
||||
__RCSID("$NetBSD: tape.c,v 1.19 1999/09/29 04:57:49 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -53,7 +53,6 @@ __RCSID("$NetBSD: tape.c,v 1.18 1999/03/23 14:22:59 bouyer Exp $");
|
|||
#include <ufs/inode.h>
|
||||
#else
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
#endif
|
||||
|
||||
#include <protocols/dumprestore.h>
|
||||
|
@ -202,7 +201,7 @@ dumpblock(blkno, size)
|
|||
{
|
||||
int avail, tpblks, dblkno;
|
||||
|
||||
dblkno = fsbtodb(sblock, blkno);
|
||||
dblkno = fsatoda(ufsib, blkno);
|
||||
tpblks = size >> tp_bshift;
|
||||
while ((avail = MIN(tpblks, ntrec - trecno)) > 0) {
|
||||
slp->req[trecno].dblk = dblkno;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: traverse.c,v 1.25 1999/05/05 16:53:46 sommerfe Exp $ */
|
||||
/* $NetBSD: traverse.c,v 1.26 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1988, 1991, 1993
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)traverse.c 8.7 (Berkeley) 6/15/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: traverse.c,v 1.25 1999/05/05 16:53:46 sommerfe Exp $");
|
||||
__RCSID("$NetBSD: traverse.c,v 1.26 1999/09/29 04:57:49 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -117,10 +117,10 @@ blockest(dp)
|
|||
sizeest = howmany(dp->di_size, TP_BSIZE);
|
||||
if (blkest > sizeest)
|
||||
blkest = sizeest;
|
||||
if (dp->di_size > sblock->fs_bsize * NDADDR) {
|
||||
if (dp->di_size > ufsib->ufs_bsize * NDADDR) {
|
||||
/* calculate the number of indirect blocks on the dump tape */
|
||||
blkest +=
|
||||
howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE,
|
||||
howmany(sizeest - NDADDR * ufsib->ufs_bsize / TP_BSIZE,
|
||||
TP_NINDIR);
|
||||
}
|
||||
return (blkest + 1);
|
||||
|
@ -330,12 +330,12 @@ mapdirs(maxino, tapesize)
|
|||
for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
|
||||
if (di.di_db[i] != 0)
|
||||
ret |= searchdir(ino, iswap32(di.di_db[i]),
|
||||
(long)dblksize(sblock, &di, i),
|
||||
(long)ufs_dblksize(ufsib, &di, i),
|
||||
filesize, tapesize, nodump);
|
||||
if (ret & HASDUMPEDFILE)
|
||||
filesize = 0;
|
||||
else
|
||||
filesize -= sblock->fs_bsize;
|
||||
filesize -= ufsib->ufs_bsize;
|
||||
}
|
||||
for (i = 0; filesize > 0 && i < NIADDR; i++) {
|
||||
if (di.di_ib[i] == 0)
|
||||
|
@ -381,24 +381,24 @@ dirindir(ino, blkno, ind_level, filesize, tapesize, nodump)
|
|||
int i;
|
||||
daddr_t idblk[MAXNINDIR];
|
||||
|
||||
bread(fsbtodb(sblock, iswap32(blkno)), (char *)idblk,
|
||||
(int)sblock->fs_bsize);
|
||||
bread(fsatoda(ufsib, iswap32(blkno)), (char *)idblk,
|
||||
(int)ufsib->ufs_bsize);
|
||||
if (ind_level <= 0) {
|
||||
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
|
||||
for (i = 0; *filesize > 0 && i < ufsib->ufs_nindir; i++) {
|
||||
blkno = idblk[i];
|
||||
if (blkno != 0)
|
||||
ret |= searchdir(ino, iswap32(blkno),
|
||||
sblock->fs_bsize, *filesize,
|
||||
ufsib->ufs_bsize, *filesize,
|
||||
tapesize, nodump);
|
||||
if (ret & HASDUMPEDFILE)
|
||||
*filesize = 0;
|
||||
else
|
||||
*filesize -= sblock->fs_bsize;
|
||||
*filesize -= ufsib->ufs_bsize;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
ind_level--;
|
||||
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
|
||||
for (i = 0; *filesize > 0 && i < ufsib->ufs_nindir; i++) {
|
||||
blkno = idblk[i];
|
||||
if (blkno != 0)
|
||||
ret |= dirindir(ino, blkno, ind_level, filesize,
|
||||
|
@ -427,7 +427,7 @@ searchdir(dino, blkno, size, filesize, tapesize, nodump)
|
|||
char dblk[MAXBSIZE];
|
||||
ino_t ino;
|
||||
|
||||
bread(fsbtodb(sblock, blkno), dblk, (int)size);
|
||||
bread(fsatoda(ufsib, blkno), dblk, (int)size);
|
||||
if (filesize < size)
|
||||
size = filesize;
|
||||
for (loc = 0; loc < size; ) {
|
||||
|
@ -513,8 +513,8 @@ dumpino(dp, ino)
|
|||
*/
|
||||
if (dp->di_size > 0 &&
|
||||
#ifdef FS_44INODEFMT
|
||||
(dp->di_size < sblock->fs_maxsymlinklen ||
|
||||
(sblock->fs_maxsymlinklen == 0 && dp->di_blocks == 0))) {
|
||||
(dp->di_size < ufsib->ufs_maxsymlinklen ||
|
||||
(ufsib->ufs_maxsymlinklen == 0 && dp->di_blocks == 0))) {
|
||||
#else
|
||||
dp->di_blocks == 0) {
|
||||
#endif
|
||||
|
@ -545,12 +545,12 @@ dumpino(dp, ino)
|
|||
msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT);
|
||||
return;
|
||||
}
|
||||
if (dp->di_size > NDADDR * sblock->fs_bsize)
|
||||
cnt = NDADDR * sblock->fs_frag;
|
||||
if (dp->di_size > NDADDR * ufsib->ufs_bsize)
|
||||
cnt = NDADDR * ufsib->ufs_frag;
|
||||
else
|
||||
cnt = howmany(dp->di_size, sblock->fs_fsize);
|
||||
cnt = howmany(dp->di_size, ufsib->ufs_fsize);
|
||||
blksout(&dp->di_db[0], cnt, ino);
|
||||
if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0)
|
||||
if ((size = dp->di_size - NDADDR * ufsib->ufs_bsize) <= 0)
|
||||
return;
|
||||
for (ind_level = 0; ind_level < NIADDR; ind_level++) {
|
||||
dmpindir(ino, dp->di_ib[ind_level], ind_level, &size);
|
||||
|
@ -573,21 +573,21 @@ dmpindir(ino, blk, ind_level, size)
|
|||
daddr_t idblk[MAXNINDIR];
|
||||
|
||||
if (blk != 0)
|
||||
bread(fsbtodb(sblock, iswap32(blk)), (char *)idblk,
|
||||
(int) sblock->fs_bsize);
|
||||
bread(fsatoda(ufsib, iswap32(blk)), (char *)idblk,
|
||||
(int) ufsib->ufs_bsize);
|
||||
else
|
||||
memset(idblk, 0, (int)sblock->fs_bsize);
|
||||
memset(idblk, 0, (int)ufsib->ufs_bsize);
|
||||
if (ind_level <= 0) {
|
||||
if (*size < NINDIR(sblock) * sblock->fs_bsize)
|
||||
cnt = howmany(*size, sblock->fs_fsize);
|
||||
if (*size < ufsib->ufs_nindir * ufsib->ufs_bsize)
|
||||
cnt = howmany(*size, ufsib->ufs_fsize);
|
||||
else
|
||||
cnt = NINDIR(sblock) * sblock->fs_frag;
|
||||
*size -= NINDIR(sblock) * sblock->fs_bsize;
|
||||
cnt = ufsib->ufs_nindir * ufsib->ufs_frag;
|
||||
*size -= ufsib->ufs_nindir * ufsib->ufs_bsize;
|
||||
blksout(&idblk[0], cnt, ino);
|
||||
return;
|
||||
}
|
||||
ind_level--;
|
||||
for (i = 0; i < NINDIR(sblock); i++) {
|
||||
for (i = 0; i < ufsib->ufs_nindir; i++) {
|
||||
dmpindir(ino, idblk[i], ind_level, size);
|
||||
if (*size <= 0)
|
||||
return;
|
||||
|
@ -606,8 +606,8 @@ blksout(blkp, frags, ino)
|
|||
daddr_t *bp;
|
||||
int i, j, count, blks, tbperdb;
|
||||
|
||||
blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
|
||||
tbperdb = sblock->fs_bsize >> tp_bshift;
|
||||
blks = howmany(frags * ufsib->ufs_fsize, TP_BSIZE);
|
||||
tbperdb = ufsib->ufs_bsize >> tp_bshift;
|
||||
for (i = 0; i < blks; i += TP_NINDIR) {
|
||||
if (i + TP_NINDIR > blks)
|
||||
count = blks;
|
||||
|
@ -624,7 +624,7 @@ blksout(blkp, frags, ino)
|
|||
for (j = i; j < count; j += tbperdb, bp++)
|
||||
if (*bp != 0) {
|
||||
if (j + tbperdb <= count)
|
||||
dumpblock(iswap32(*bp), (int)sblock->fs_bsize);
|
||||
dumpblock(iswap32(*bp), (int)ufsib->ufs_bsize);
|
||||
else
|
||||
dumpblock(iswap32(*bp), (count - j) * TP_BSIZE);
|
||||
}
|
||||
|
@ -675,24 +675,3 @@ writeheader(ino)
|
|||
spcl.c_checksum = iswap32(CHECKSUM - sum);
|
||||
writerec((char *)&spcl, 1);
|
||||
}
|
||||
|
||||
struct dinode *
|
||||
getino(inum)
|
||||
ino_t inum;
|
||||
{
|
||||
static daddr_t minino, maxino;
|
||||
static struct dinode inoblock[MAXINOPB];
|
||||
int i;
|
||||
|
||||
curino = inum;
|
||||
if (inum >= minino && inum < maxino)
|
||||
return (&inoblock[inum - minino]);
|
||||
bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock,
|
||||
(int)sblock->fs_bsize);
|
||||
if (needswap)
|
||||
for (i = 0; i < MAXINOPB; i++)
|
||||
ffs_dinode_swap(&inoblock[i], &inoblock[i]);
|
||||
minino = inum - (inum % INOPB(sblock));
|
||||
maxino = minino + INOPB(sblock);
|
||||
return (&inoblock[inum - minino]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# $NetBSD: Makefile,v 1.1 1999/09/29 04:57:49 perseant Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
|
||||
# lfs_inode.c LFS filestore-specific routines
|
||||
#
|
||||
# DEBUG use local directory to find ddate and dumpdates
|
||||
# TDEBUG trace out the process forking
|
||||
|
||||
PROG= dump_lfs
|
||||
LINKS= ${BINDIR}/dump_lfs ${BINDIR}/rdump_lfs
|
||||
CPPFLAGS+=-DRDUMP -I${.CURDIR} -I${.CURDIR}/../dump
|
||||
# CPPFLAGS+= -DDEBUG -DTDEBUG -DFDEBUG -DWRITEDEBUG -DSTATS -DDIAGNOSTICS
|
||||
SRCS= itime.c main.c optr.c dumprmt.c rcache.c tape.c traverse.c unctime.c \
|
||||
ffs_bswap.c lfs_inode.c
|
||||
BINGRP= tty
|
||||
BINMODE=2555
|
||||
MAN= dump_lfs.8
|
||||
MLINKS+=dump_lfs.8 rdump_lfs.8
|
||||
CFLAGS+=-g
|
||||
|
||||
.PATH: ${.CURDIR}/../dump ${.CURDIR}/../../sys/ufs/lfs ${.CURDIR}/../../sys/ufs/ffs
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,477 @@
|
|||
.\" $NetBSD: dump_lfs.8,v 1.1 1999/09/29 04:57:49 perseant Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)dump.8 8.3 (Berkeley) 5/1/95
|
||||
.\"
|
||||
.Dd September 3, 1999
|
||||
.Dt DUMP_LFS 8
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm dump_lfs ,
|
||||
.Nm rdump_lfs
|
||||
.Nd filesystem backup
|
||||
.Sh SYNOPSIS
|
||||
.Nm ""
|
||||
.Op Fl 0123456789cnSu
|
||||
.Op Fl B Ar records
|
||||
.Op Fl b Ar blocksize
|
||||
.Op Fl d Ar density
|
||||
.Op Fl f Ar file
|
||||
.Op Fl h Ar level
|
||||
.Op Fl k Ar read blocksize
|
||||
.Op Fl L Ar label
|
||||
.Op Fl r Ar cachesize
|
||||
.Op Fl s Ar feet
|
||||
.Op Fl T Ar date
|
||||
.Ar files-to-dump
|
||||
.Nm ""
|
||||
.Op Fl W Li \&| Fl w
|
||||
.Pp
|
||||
.in -\\n(iSu
|
||||
(The
|
||||
.Bx 4.3
|
||||
option syntax is implemented for backward compatibility, but
|
||||
is not documented here).
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
examines files on a filesystem and determines which files need to
|
||||
be backed up.
|
||||
These files are copied to the given disk, tape or other storage
|
||||
medium for safe keeping (see the
|
||||
.Fl f
|
||||
option below for doing remote backups).
|
||||
A dump that is larger than the output medium is broken into
|
||||
multiple volumes.
|
||||
On most media the size is determined by writing until an
|
||||
end-of-media indication is returned.
|
||||
On media that cannot reliably return an end-of-media indication
|
||||
(such as some cartridge tape drives)
|
||||
each volume is of a fixed size;
|
||||
the actual size is determined by the tape size and density and/or
|
||||
block count options below.
|
||||
By default, the same output file name is used for each volume
|
||||
after prompting the operator to change media.
|
||||
.Pp
|
||||
.Ar files-to-dump
|
||||
is either a mountpoint of a filesystem,
|
||||
or a list of files and directories on a single filesystem to be backed
|
||||
up as a subset of the filesystem.
|
||||
In the former case, either the path to a mounted filesystem,
|
||||
or the device of an unmounted filesystem can be used.
|
||||
In the latter case, certain restrictions are placed on the backup:
|
||||
.Fl u
|
||||
is ignored, the only dump level that is supported is
|
||||
.Fl 0 ,
|
||||
and all of the files must reside on the same filesystem.
|
||||
.Pp
|
||||
The following options are supported by
|
||||
.Nm "" :
|
||||
.Bl -tag -width Ds
|
||||
.It Fl 0\-9
|
||||
Dump levels.
|
||||
A level 0, full backup,
|
||||
guarantees the entire file system is copied
|
||||
(but see also the
|
||||
.Fl h
|
||||
option below).
|
||||
A level number above 0,
|
||||
incremental backup,
|
||||
tells dump to
|
||||
copy all files new or modified since the
|
||||
last dump of a lower level.
|
||||
The default level is 9.
|
||||
.It Fl B Ar records
|
||||
The number of kilobytes per volume, rounded
|
||||
down to a multiple of the blocksize.
|
||||
This option overrides the calculation of tape size
|
||||
based on length and density.
|
||||
.It Fl b Ar blocksize
|
||||
The number of kilobytes per dump record.
|
||||
.It Fl c
|
||||
Modify the calculation of the default density and tape size to be more
|
||||
appropriate for cartridge tapes.
|
||||
.It Fl d Ar density
|
||||
Set tape density to
|
||||
.Ar density .
|
||||
The default is 1600 Bits Per Inch (BPI).
|
||||
.It Fl f Ar file
|
||||
Write the backup to
|
||||
.Ar file ;
|
||||
.Ar file
|
||||
may be a special device file
|
||||
like
|
||||
.Pa /dev/rst0
|
||||
(a tape drive),
|
||||
.Pa /dev/rsd1c
|
||||
(a disk drive),
|
||||
an ordinary file,
|
||||
or
|
||||
.Ql Fl
|
||||
(the standard output).
|
||||
Multiple file names may be given as a single argument separated by commas.
|
||||
Each file will be used for one dump volume in the order listed;
|
||||
if the dump requires more volumes than the number of names given,
|
||||
the last file name will used for all remaining volumes after prompting
|
||||
for media changes.
|
||||
If the name of the file is of the form
|
||||
.Qq host:file ,
|
||||
or
|
||||
.Qq user@host:file ,
|
||||
.Nm
|
||||
writes to the named file on the remote host using
|
||||
.Xr rmt 8 .
|
||||
Note that methods more secure than
|
||||
.Xr rsh 1
|
||||
.Pq such as Xr ssh 1
|
||||
can be used to invoke
|
||||
.Xr rmt 8
|
||||
on the remote host, via the environment variable
|
||||
.Ev RCMD_CMD .
|
||||
See
|
||||
.Xr rcmd 3
|
||||
for more details.
|
||||
|
||||
.It Fl h Ar level
|
||||
Honor the user
|
||||
.Qq nodump
|
||||
flag
|
||||
.Dp Dv UF_NODUMP
|
||||
only for dumps at or above the given
|
||||
.Ar level .
|
||||
The default honor level is 1,
|
||||
so that incremental backups omit such files
|
||||
but full backups retain them.
|
||||
.It Fl k Ar read blocksize
|
||||
The size in kilobyte of the read buffers, rounded up to a multiple of the
|
||||
filesystem block size. Default is 32k.
|
||||
.It Fl L Ar label
|
||||
The user-supplied text string
|
||||
.Ar label
|
||||
is placed into the dump header, where tools like
|
||||
.Xr restore 8
|
||||
and
|
||||
.Xr file 1
|
||||
can access it.
|
||||
Note that this label is limited
|
||||
to be at most LBLSIZE (currently 16) characters, which must include
|
||||
the terminating
|
||||
.Ql \e0 .
|
||||
.It Fl n
|
||||
Whenever
|
||||
.Nm
|
||||
requires operator attention,
|
||||
notify all operators in the group
|
||||
.Qq operator
|
||||
by means similar to a
|
||||
.Xr wall 1 .
|
||||
.It Fl r Ar cachesize
|
||||
Use that many buffers for read cache operations.
|
||||
A value of zero disables the read cache altogether, higher values
|
||||
improve read performance by reading larger data blocks from the
|
||||
disk and maintaining them in an LRU cache. See the
|
||||
.Fl k
|
||||
option for the size of the buffers. Maximum is 512, the size of the cache is
|
||||
limited to 15% of the avail RAM by default.
|
||||
.It Fl s Ar feet
|
||||
Attempt to calculate the amount of tape needed
|
||||
at a particular density.
|
||||
If this amount is exceeded,
|
||||
.Nm
|
||||
prompts for a new tape.
|
||||
It is recommended to be a bit conservative on this option.
|
||||
The default tape length is 2300 feet.
|
||||
.It Fl S
|
||||
Display an estimate of the backup size and the number of tapes
|
||||
required, and exit without actually performing the dump.
|
||||
.It Fl T Ar date
|
||||
Use the specified date as the starting time for the dump
|
||||
instead of the time determined from looking in
|
||||
.Pa /etc/dumpdates .
|
||||
The format of date is the same as that of
|
||||
.Xr ctime 3 .
|
||||
This option is useful for automated dump scripts that wish to
|
||||
dump over a specific period of time.
|
||||
The
|
||||
.Fl T
|
||||
option is mutually exclusive from the
|
||||
.Fl u
|
||||
option.
|
||||
.It Fl u
|
||||
Update the file
|
||||
.Pa /etc/dumpdates
|
||||
after a successful dump.
|
||||
The format of
|
||||
.Pa /etc/dumpdates
|
||||
is readable by people, consisting of one
|
||||
free format record per line:
|
||||
filesystem name,
|
||||
increment level
|
||||
and
|
||||
.Xr ctime 3
|
||||
format dump date.
|
||||
There may be only one entry per filesystem at each level.
|
||||
The file
|
||||
.Pa /etc/dumpdates
|
||||
may be edited to change any of the fields,
|
||||
if necessary.
|
||||
If a list of files or subdirectories is being dumped
|
||||
(as opposed to and entire filesystem), then
|
||||
.Fl u
|
||||
is ignored.
|
||||
.It Fl W
|
||||
.Nm
|
||||
tells the operator what file systems need to be dumped.
|
||||
This information is gleaned from the files
|
||||
.Pa /etc/dumpdates
|
||||
and
|
||||
.Pa /etc/fstab .
|
||||
The
|
||||
.Fl W
|
||||
option causes
|
||||
.Nm
|
||||
to print out, for each file system in
|
||||
.Pa /etc/dumpdates
|
||||
the most recent dump date and level,
|
||||
and highlights those file systems that should be dumped.
|
||||
If the
|
||||
.Fl W
|
||||
option is set, all other options are ignored, and
|
||||
.Nm
|
||||
exits immediately.
|
||||
.It Fl w
|
||||
Is like W, but prints only those filesystems which need to be dumped.
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Nm
|
||||
honors the
|
||||
.Qq nodump
|
||||
flag,
|
||||
.Dp Dv UF_NODUMP
|
||||
files with the
|
||||
.Qq nodump
|
||||
flag will not be backed up. If a directory has the
|
||||
.Qq nodump
|
||||
flag, this directory and any file or directory under it will not be backed up.
|
||||
.Pp
|
||||
.Nm
|
||||
requires operator intervention on these conditions:
|
||||
end of tape,
|
||||
end of dump,
|
||||
tape write error,
|
||||
tape open error or
|
||||
disk read error (if there are more than a threshold of 32).
|
||||
In addition to alerting all operators implied by the
|
||||
.Fl n
|
||||
option,
|
||||
.Nm
|
||||
interacts with the operator on
|
||||
.Nm "" Ns 's
|
||||
control terminal at times when
|
||||
.Nm
|
||||
can no longer proceed,
|
||||
or if something is grossly wrong.
|
||||
All questions
|
||||
.Nm
|
||||
poses
|
||||
.Em must
|
||||
be answered by typing
|
||||
.Qq yes
|
||||
or
|
||||
.Qq no ,
|
||||
appropriately.
|
||||
.Pp
|
||||
Since making a dump involves a lot of time and effort for full dumps,
|
||||
.Nm
|
||||
checkpoints itself at the start of each tape volume.
|
||||
If writing that volume fails for some reason,
|
||||
.Nm
|
||||
will,
|
||||
with operator permission,
|
||||
restart itself from the checkpoint
|
||||
after the old tape has been rewound and removed,
|
||||
and a new tape has been mounted.
|
||||
.Pp
|
||||
.Nm
|
||||
tells the operator what is going on at periodic intervals,
|
||||
including usually low estimates of the number of blocks to write,
|
||||
the number of tapes it will take, the time to completion, and
|
||||
the time to the tape change.
|
||||
The output is verbose,
|
||||
so that others know that the terminal
|
||||
controlling
|
||||
.Nm
|
||||
is busy,
|
||||
and will be for some time.
|
||||
.Pp
|
||||
In the event of a catastrophic disk event, the time required
|
||||
to restore all the necessary backup tapes or files to disk
|
||||
can be kept to a minimum by staggering the incremental dumps.
|
||||
An efficient method of staggering incremental dumps
|
||||
to minimize the number of tapes follows:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
Always start with a level 0 backup, for example:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/dump -0u -f /dev/nrst1 /usr/src
|
||||
.Ed
|
||||
.Pp
|
||||
This should be done at set intervals, say once a month or once every two months,
|
||||
and on a set of fresh tapes that is saved forever.
|
||||
.It
|
||||
After a level 0, dumps of active file
|
||||
systems are taken on a daily basis,
|
||||
using a modified Tower of Hanoi algorithm,
|
||||
with this sequence of dump levels:
|
||||
.Bd -literal -offset indent
|
||||
3 2 5 4 7 6 9 8 9 9 ...
|
||||
.Ed
|
||||
.Pp
|
||||
For the daily dumps, it should be possible to use a fixed number of tapes
|
||||
for each day, used on a weekly basis.
|
||||
Each week, a level 1 dump is taken, and
|
||||
the daily Hanoi sequence repeats beginning with 3.
|
||||
For weekly dumps, another fixed set of tapes per dumped file system is
|
||||
used, also on a cyclical basis.
|
||||
.El
|
||||
.Pp
|
||||
After several months or so, the daily and weekly tapes should get
|
||||
rotated out of the dump cycle and fresh tapes brought in.
|
||||
.Pp
|
||||
If
|
||||
.Nm
|
||||
receives a
|
||||
.Dv SIGINFO
|
||||
signal
|
||||
(see the
|
||||
.Qq status
|
||||
argument of
|
||||
.Xr stty 1 )
|
||||
whilst a backup is in progress, statistics on the amount completed,
|
||||
current transfer rate, and estimated finished time, will be written
|
||||
to the standard error output.
|
||||
.Sh ENVIRONMENT
|
||||
If the following environment variables exist, they are utilized by
|
||||
.Nm "" .
|
||||
.Bl -tag -width Fl
|
||||
.It Ev TAPE
|
||||
If no -f option was specified,
|
||||
.Nm
|
||||
will use the device specified via
|
||||
.Ev TAPE
|
||||
as the dump device.
|
||||
.Ev TAPE
|
||||
may be of the form
|
||||
.Qq tapename ,
|
||||
.Qq host:tapename ,
|
||||
or
|
||||
.Qq user@host:tapename .
|
||||
.It Ev RCMD_CMD
|
||||
.Nm
|
||||
will use
|
||||
.Ev RCMD_CMD
|
||||
rather than
|
||||
.Xr rsh 1
|
||||
to invoke
|
||||
.Xr rmt 8
|
||||
on the remote machine.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/dumpdates -compact
|
||||
.It Pa /dev/nrst0
|
||||
default tape unit to use. Taken from
|
||||
.Dv _PATH_DEFTAPE
|
||||
in
|
||||
.Pa /usr/include/paths.h .
|
||||
.It Pa /dev/rst*
|
||||
raw SCSI tape interface
|
||||
.It Pa /etc/dumpdates
|
||||
dump date records
|
||||
.It Pa /etc/fstab
|
||||
dump table: file systems and frequency
|
||||
.It Pa /etc/group
|
||||
to find group
|
||||
.Em operator
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chflags 1 ,
|
||||
.Xr stty 1 ,
|
||||
.Xr fts 3 ,
|
||||
.Xr fstab 5 ,
|
||||
.Xr restore 8 ,
|
||||
.Xr rmt 8 ,
|
||||
.Xr st 4
|
||||
.Sh DIAGNOSTICS
|
||||
Many, and verbose.
|
||||
.Pp
|
||||
.Nm
|
||||
exits with zero status on success.
|
||||
Startup errors are indicated with an exit code of 1;
|
||||
abnormal termination is indicated with an exit code of 3.
|
||||
.Sh BUGS
|
||||
Fewer than 32 read errors on the filesystem are ignored.
|
||||
.Pp
|
||||
Each reel requires a new process, so parent processes for
|
||||
reels already written just hang around until the entire tape
|
||||
is written.
|
||||
.Pp
|
||||
.Nm
|
||||
with the
|
||||
.Fl W
|
||||
or
|
||||
.Fl w
|
||||
options does not report filesystems that have never been recorded
|
||||
in
|
||||
.Pa /etc/dumpdates ,
|
||||
even if listed in
|
||||
.Pa /etc/fstab .
|
||||
.Pp
|
||||
When dumping a list of files or subdirectories, access privileges are
|
||||
required to scan the directory (as this is done via the
|
||||
.Xr fts 3
|
||||
routines rather than directly accessing the filesystem).
|
||||
.Pp
|
||||
It would be nice if
|
||||
.Nm
|
||||
knew about the dump sequence,
|
||||
kept track of the tapes scribbled on,
|
||||
told the operator which tape to mount when,
|
||||
and provided more assistance
|
||||
for the operator running
|
||||
.Xr restore 8 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.Nx 1.5.
|
|
@ -0,0 +1,287 @@
|
|||
/* $NetBSD: lfs_inode.c,v 1.1 1999/09/29 04:57:49 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: lfs_inode.c,v 1.1 1999/09/29 04:57:49 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <sys/mount.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
|
||||
#include <protocols/dumprestore.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "dump.h"
|
||||
|
||||
#define MAXIFPB (MAXBSIZE / sizeof(IFILE))
|
||||
|
||||
#define HASDUMPEDFILE 0x1
|
||||
#define HASSUBDIRS 0x2
|
||||
|
||||
struct lfs *sblock;
|
||||
|
||||
/*
|
||||
* Read the superblock from disk, and check its magic number.
|
||||
* Determine whether byte-swapping needs to be done on this filesystem.
|
||||
*/
|
||||
int
|
||||
fs_read_sblock(char *sblock_buf)
|
||||
{
|
||||
int needswap = 0;
|
||||
|
||||
sblock = (struct lfs *)sblock_buf;
|
||||
rawread(LFS_LABELPAD, (char *) sblock, LFS_SBPAD);
|
||||
if (sblock->lfs_magic != LFS_MAGIC) {
|
||||
#if 0
|
||||
if (sblock->lfs_magic == bswap32(LFS_MAGIC)) {
|
||||
lfs_sb_swap(sblock, sblock, 0);
|
||||
needswap = 1;
|
||||
} else
|
||||
#endif
|
||||
quit("bad sblock magic number\n");
|
||||
}
|
||||
return needswap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the ufsi struct, as well as the maxino and dev_bsize global
|
||||
* variables.
|
||||
*/
|
||||
struct ufsi *
|
||||
fs_parametrize(void)
|
||||
{
|
||||
static struct ufsi ufsi;
|
||||
|
||||
ufsi.ufs_dsize = fsbtodb(sblock,sblock->lfs_size);
|
||||
ufsi.ufs_bsize = sblock->lfs_bsize;
|
||||
ufsi.ufs_bshift = sblock->lfs_bshift;
|
||||
ufsi.ufs_fsize = sblock->lfs_fsize;
|
||||
ufsi.ufs_frag = sblock->lfs_frag;
|
||||
ufsi.ufs_fsatoda = 0;
|
||||
ufsi.ufs_nindir = sblock->lfs_nindir;
|
||||
ufsi.ufs_inopb = sblock->lfs_inopb;
|
||||
ufsi.ufs_maxsymlinklen = sblock->lfs_maxsymlinklen;
|
||||
ufsi.ufs_bmask = ~(sblock->lfs_bmask);
|
||||
ufsi.ufs_qbmask = sblock->lfs_bmask;
|
||||
ufsi.ufs_fmask = ~(sblock->lfs_ffmask);
|
||||
ufsi.ufs_qfmask = sblock->lfs_ffmask;
|
||||
|
||||
dev_bsize = sblock->lfs_bsize >> sblock->lfs_fsbtodb;
|
||||
|
||||
return &ufsi;
|
||||
}
|
||||
|
||||
ino_t
|
||||
fs_maxino(void)
|
||||
{
|
||||
return ((getino(sblock->lfs_ifile)->di_size
|
||||
- (sblock->lfs_cleansz + sblock->lfs_segtabsz)
|
||||
* sblock->lfs_bsize)
|
||||
/ sblock->lfs_bsize) * sblock->lfs_ifpb - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX KS - I know there's a better way to do this.
|
||||
*/
|
||||
#define BASE_SINDIR (NDADDR)
|
||||
#define BASE_DINDIR (NDADDR+NINDIR(fs))
|
||||
#define BASE_TINDIR (NDADDR+NINDIR(fs)+NINDIR(fs)*NINDIR(fs))
|
||||
|
||||
#define D_UNITS (NINDIR(fs))
|
||||
#define T_UNITS (NINDIR(fs)*NINDIR(fs))
|
||||
|
||||
static daddr_t
|
||||
lfs_bmap(struct lfs *fs, struct dinode *idinode, ufs_daddr_t lbn)
|
||||
{
|
||||
ufs_daddr_t residue, up;
|
||||
int off=0;
|
||||
char bp[MAXBSIZE];
|
||||
|
||||
if(lbn > 0 && lbn > (idinode->di_size-1)/dev_bsize) {
|
||||
return UNASSIGNED;
|
||||
}
|
||||
/*
|
||||
* Indirect blocks: if it is a first-level indirect, pull its
|
||||
* address from the inode; otherwise, call ourselves to find the
|
||||
* address of the parent indirect block, and load that to find
|
||||
* the desired address.
|
||||
*/
|
||||
if(lbn < 0) {
|
||||
lbn *= -1;
|
||||
if(lbn == NDADDR) {
|
||||
/* printf("lbn %d: single indir base\n", -lbn); */
|
||||
return idinode->di_ib[0]; /* single indirect */
|
||||
} else if(lbn == BASE_DINDIR+1) {
|
||||
/* printf("lbn %d: double indir base\n", -lbn); */
|
||||
return idinode->di_ib[1]; /* double indirect */
|
||||
} else if(lbn == BASE_TINDIR+2) {
|
||||
/* printf("lbn %d: triple indir base\n", -lbn); */
|
||||
return idinode->di_ib[2]; /* triple indirect */
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the immediate parent. This is essentially finding the
|
||||
* residue of modulus, and then rounding accordingly.
|
||||
*/
|
||||
residue = (lbn-NDADDR) % NINDIR(fs);
|
||||
if(residue == 1) {
|
||||
/* Double indirect. Parent is the triple. */
|
||||
up = idinode->di_ib[2];
|
||||
off = (lbn-2-BASE_TINDIR)/(NINDIR(fs)*NINDIR(fs));
|
||||
if(up == UNASSIGNED || up == LFS_UNUSED_DADDR)
|
||||
return UNASSIGNED;
|
||||
/* printf("lbn %d: parent is the triple\n", -lbn); */
|
||||
bread(up, bp, sblock->lfs_bsize);
|
||||
return ((daddr_t *)bp)[off];
|
||||
} else /* residue == 0 */ {
|
||||
/* Single indirect. Two cases. */
|
||||
if(lbn < BASE_TINDIR) {
|
||||
/* Parent is the double, simple */
|
||||
up = -(BASE_DINDIR) - 1;
|
||||
off = (lbn-BASE_DINDIR) / D_UNITS;
|
||||
/* printf("lbn %d: parent is %d/%d\n", -lbn, up,off); */
|
||||
} else {
|
||||
/* Ancestor is the triple, more complex */
|
||||
up = ((lbn-BASE_TINDIR) / T_UNITS)
|
||||
* T_UNITS + BASE_TINDIR + 1;
|
||||
off = (lbn/D_UNITS) - (up/D_UNITS);
|
||||
up = -up;
|
||||
/* printf("lbn %d: parent is %d/%d\n", -lbn, up,off); */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Direct block. Its parent must be a single indirect. */
|
||||
if(lbn < NDADDR)
|
||||
return idinode->di_db[lbn];
|
||||
else {
|
||||
/* Parent is an indirect block. */
|
||||
up = -(((lbn-NDADDR) / D_UNITS) * D_UNITS + NDADDR);
|
||||
off = (lbn-NDADDR) % D_UNITS;
|
||||
/* printf("lbn %d: parent is %d/%d\n", lbn,up,off); */
|
||||
}
|
||||
}
|
||||
up = lfs_bmap(fs,idinode,up);
|
||||
if(up == UNASSIGNED || up == LFS_UNUSED_DADDR)
|
||||
return UNASSIGNED;
|
||||
bread(up, bp, sblock->lfs_bsize);
|
||||
return ((daddr_t *)bp)[off];
|
||||
}
|
||||
|
||||
static struct ifile *
|
||||
lfs_ientry(ino_t ino)
|
||||
{
|
||||
static struct ifile ifileblock[MAXIFPB];
|
||||
static daddr_t ifblkno;
|
||||
ufs_daddr_t lbn;
|
||||
daddr_t blkno;
|
||||
|
||||
lbn = ino/sblock->lfs_ifpb + sblock->lfs_cleansz + sblock->lfs_segtabsz;
|
||||
blkno = lfs_bmap(sblock,getino(sblock->lfs_ifile),lbn);
|
||||
if(blkno != ifblkno)
|
||||
bread(blkno, (char *)ifileblock, sblock->lfs_bsize);
|
||||
return ifileblock + (ino%sblock->lfs_ifpb);
|
||||
}
|
||||
|
||||
/* Search a block for a specific dinode. */
|
||||
struct dinode *
|
||||
lfs_ifind(struct lfs *fs, ino_t ino, struct dinode *dip)
|
||||
{
|
||||
register int cnt;
|
||||
|
||||
for(cnt=0;cnt<INOPB(fs);cnt++)
|
||||
if(dip[cnt].di_inumber == ino)
|
||||
return &(dip[cnt]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dinode *
|
||||
getino(inum)
|
||||
ino_t inum;
|
||||
{
|
||||
static daddr_t inoblkno;
|
||||
daddr_t blkno;
|
||||
static struct dinode inoblock[MAXINOPB];
|
||||
static struct dinode ifile_dinode; /* XXX fill this in */
|
||||
static struct dinode empty_dinode; /* Always stays zeroed */
|
||||
struct dinode *dp;
|
||||
int i;
|
||||
|
||||
if(inum == sblock->lfs_ifile) {
|
||||
/* Load the ifile inode if not already */
|
||||
if(ifile_dinode.di_u.inumber == 0) {
|
||||
blkno = sblock->lfs_idaddr;
|
||||
bread(blkno, (char *)inoblock, (int)sblock->lfs_bsize);
|
||||
dp = lfs_ifind(sblock, inum, inoblock);
|
||||
ifile_dinode = *dp; /* Structure copy */
|
||||
}
|
||||
return &ifile_dinode;
|
||||
}
|
||||
|
||||
curino = inum;
|
||||
blkno = lfs_ientry(inum)->if_daddr;
|
||||
if(blkno == LFS_UNUSED_DADDR)
|
||||
return &empty_dinode;
|
||||
|
||||
if(blkno != inoblkno) {
|
||||
bread(blkno, (char *)inoblock, (int)sblock->lfs_bsize);
|
||||
if (needswap)
|
||||
for (i = 0; i < MAXINOPB; i++)
|
||||
ffs_dinode_swap(&inoblock[i], &inoblock[i]);
|
||||
}
|
||||
return lfs_ifind(sblock, inum, inoblock);
|
||||
}
|
Loading…
Reference in New Issue