added growfs(8) including ffsinfo(8) to the freebsd base system

Reviewed by:	 grog
This commit is contained in:
Thomas-Henning von Kamptz 2000-12-09 15:27:35 +00:00
parent f786d43aac
commit 3d5000784d
10 changed files with 4260 additions and 1 deletions

View File

@ -16,11 +16,13 @@ SUBDIR= adjkerntz \
dump \
dumpfs \
dumpon \
ffsinfo \
fsck \
fsck_ifs \
fsck_ffs \
fsdb \
fsirand \
growfs \
ifconfig \
init \
ip6fw \

19
sbin/ffsinfo/Makefile Normal file
View File

@ -0,0 +1,19 @@
# @(#)Makefile 8.8 (Berkeley) 6/21/2000
#
# $TSHeader: src/sbin/ffsinfo/Makefile,v 1.3 2000/12/05 19:45:10 tomsoft Exp $
# $FreeBSD$
#
MAINTAINER= tomsoft@FreeBSD.ORG, chm@FreeBSD.ORG
#CFLAGS+=${BDECFLAGS}
PROG= ffsinfo
SRCS= ffsinfo.c debug.c
MAN8= ffsinfo.8
GROWFS= ${.CURDIR}/../growfs
CFLAGS+=-DFS_DEBUG -I${GROWFS}
.PATH: ${GROWFS}
.include <bsd.prog.mk>

132
sbin/ffsinfo/ffsinfo.8 Normal file
View File

@ -0,0 +1,132 @@
.\" Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
.\" Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
.\"
.\" 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 acknowledgment:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors, as well as Christoph
.\" Herrmann and Thomas-Henning von Kamptz.
.\" 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.
.\"
.\" $TSHeader: src/sbin/ffsinfo/ffsinfo.8,v 1.2 2000/12/09 15:12:31 tomsoft Exp $
.\" $FreeBSD$
.\"
.Dd September 8, 2000
.Dt FSINFO 8
.Os BSD 4.4
.Sh NAME
.Nm ffsinfo
.Nd dump all meta information of an existing ufs file system
.Sh SYNOPSIS
.Nm ffsinfo
.Op Fl L
.Op Fl g Ar cylinder group
.Op Fl i Ar inode
.Op Fl l Ar level
.Op Fl o Ar outfile
.Ar < special | file >
.Sh DESCRIPTION
.Nm Ffsinfo
extends the
.Xr dumpfs 8
program.
.Pp
The output is generated into the file
.Nm outfile .
Also expect the output file to be rather large. Up to 2 percent of the size
of the specified filesystem is not uncommon.
.Nm Ffsinfo
has some options to allow the defaults to be overridden.
.\".Pp
.Bl -tag -width indent
.It Fl L
Specifying this options skips the tests of the disklabel. This is automatically
done, if the specified filename to dump is a plain file.
.It Fl g Ar cylinder group
This restrictes the dump to infomation about this cylinder group only. Here
0 means the first cylinder group and -1 the last one.
.It Fl i Ar inode
This restrictes the dump to infomation about this particular inode only. Here
the minimum acceptable inode is 2. If this option is omitted but a cylinder
group is defined then only inodes within that cylinder group are dumped.
.It Fl l Ar level
The level of detail which will be dumped. This value defaults
to 255 and is the bitwise and of the following table:
.Bd -literal -offset left
0x001 - initial superblock
0x002 - superblock copys in each cylindergroup
0x004 - cylinder group summary in initial cylinder group
0x008 - cylinder group information
0x010 - inode allocation bitmap
0x020 - fragment allocation bitmap
0x040 - cluster maps and summary
0x080 - rotational layout tables
0x100 - inode information
0x200 - indirect block dump
.Ed
.It Fl o Ar outfile
This allows to change the output filename where the dump is written to. The
current default is
.Nm /var/tmp/ffsinfo .
.El
.Sh EXAMPLES
.Pp
.Dl ffsinfo -l 1023 /dev/vinum/testvol
.Pp
will dump /dev/vinum/testvol with all available information.
.Sh BUGS
Currently
.Nm
can only dump unmounted file systems. Do not try dumping a mounted file system,
your system may panic and you will not be able to use the file system any
longer.
.Pp
Also snapshots are handled like plain files. They should get a their own
level to provide for independent control of the amount of what gets dumped. It
probably also makes sense to some extend to dump the snapshot as a filesystem.
.Sh SEE ALSO
.Xr vinum 8 ,
.Xr disklabel 8 ,
.Xr fsck 8 ,
.Xr newfs 8 ,
.Xr tunefs 8 ,
.Xr growfs 8 ,
.Xr dumpfs 8
.\".Rs
.\".Re
.Sh AUTHORS
.An Christoph Herrmann Aq chm@FreeBSD.ORG
.An Thomas-Henning von Kamptz Aq tomsoft@FreeBSD.ORG
.An The GROWFS team Aq growfs@Tomsoft.COM
.Sh HISTORY
The
.Nm
command appeared first in
.Bx Free
5.0

615
sbin/ffsinfo/ffsinfo.c Normal file
View File

@ -0,0 +1,615 @@
/*
* Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
* Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
*
* 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 acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors, as well as Christoph
* Herrmann and Thomas-Henning von Kamptz.
* 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.
*
* $TSHeader: src/sbin/ffsinfo/ffsinfo.c,v 1.3 2000/12/09 15:12:31 tomsoft Exp $
* $FreeBSD$
*
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\
Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/* ********************************************************** INCLUDES ***** */
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdio.h>
#include <paths.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <machine/param.h>
#include "debug.h"
/* *********************************************************** GLOBALS ***** */
#ifdef FS_DEBUG
int _dbg_lvl_ = (DL_INFO); /* DL_TRC */
#endif /* FS_DEBUG */
static union {
struct fs fs;
char pad[SBSIZE];
} fsun1, fsun2;
#define sblock fsun1.fs
#define osblock fsun2.fs
static union {
struct cg cg;
char pad[MAXBSIZE];
} cgun1;
#define acg cgun1.cg
static char ablk[MAXBSIZE];
static char i1blk[MAXBSIZE];
static char i2blk[MAXBSIZE];
static char i3blk[MAXBSIZE];
static struct csum *fscs;
/* ******************************************************** PROTOTYPES ***** */
static void rdfs(daddr_t, int, char *, int);
static void usage(char *);
static struct disklabel *get_disklabel(int);
static struct dinode *ginode(ino_t, int);
static void dump_whole_inode(ino_t, int, int);
/* ************************************************************** rdfs ***** */
/*
* Here we read some block(s) from disk.
*/
void
rdfs(daddr_t bno, int size, char *bf, int fsi)
{
DBG_FUNC("rdfs")
int n;
DBG_ENTER;
if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) {
fprintf(stderr, "seek error: %ld\n", (long)bno);
err(33, "rdfs");
}
n = read(fsi, bf, (size_t)size);
if (n != size) {
fprintf(stderr, "read error: %ld\n", (long)bno);
err(34, "rdfs");
}
DBG_LEAVE;
return;
}
/* ************************************************************** main ***** */
/*
* ffsinfo(8) is a tool to dump all metadata of a filesystem. It helps to find
* errors is the filesystem much easier. You can run ffsinfo before and after
* an fsck(8), and compare the two ascii dumps easy with diff, and you see
* directly where the problem is. You can control how much detail you want to
* see with some command line arguments. You can also easy check the status
* of a filesystem, like is there is enough space for growing a filesystem,
* or how many active snapshots do we have. It provides much more detailed
* information then dumpfs. Snapshots, as they are very new, are not really
* supported. They are just mentioned currently, but it is planned to run
* also over active snapshots, to even get that output.
*/
int
main(int argc, char **argv)
{
DBG_FUNC("main")
char *a0, *device, *special, *cp;
char ch;
size_t len;
struct stat st;
struct disklabel *lp;
struct partition *pp;
int fsi;
struct csum *dbg_csp;
int dbg_csc;
char dbg_line[80];
int cylno,i;
int cfg_cg, cfg_in, cfg_lv;
int cg_start, cg_stop;
ino_t in;
char *out_file;
int Lflag=0;
DBG_ENTER;
cfg_lv=0xff;
cfg_in=-2;
cfg_cg=-2;
out_file=strdup("/var/tmp/ffsinfo");
a0=*argv; /* save argv[0] for usage() */
while ((ch=getopt(argc, argv, "Lg:i:l:o:")) != -1) {
switch(ch) {
case 'L':
Lflag=1;
break;
case 'g':
cfg_cg=atol(optarg);
if(cfg_cg < -1) {
usage(a0);
}
break;
case 'i':
cfg_in=atol(optarg);
if(cfg_in < 0) {
usage(a0);
}
break;
case 'l':
cfg_lv=atol(optarg);
if(cfg_lv < 0x1||cfg_lv > 0x3ff) {
usage(a0);
}
break;
case 'o':
free(out_file);
out_file=strdup(optarg);
break;
case '?':
/* FALLTHROUGH */
default:
usage(a0);
}
}
argc -= optind;
argv += optind;
if(argc != 1) {
usage(a0);
}
device=*argv;
/*
* Now we try to guess the (raw)device name.
*/
if (0 == strrchr(device, '/') && (stat(device, &st) == -1)) {
/*
* No path prefix was given, so try in that order:
* /dev/r%s
* /dev/%s
* /dev/vinum/r%s
* /dev/vinum/%s.
*
* FreeBSD now doesn't distinguish between raw and block
* devices any longer, but it should still work this way.
*/
len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/");
special=(char *)malloc(len);
snprintf(special, len, "%sr%s", _PATH_DEV, device);
if (stat(special, &st) == -1) {
snprintf(special, len, "%s%s", _PATH_DEV, device);
if (stat(special, &st) == -1) {
snprintf(special, len, "%svinum/r%s",
_PATH_DEV, device);
if (stat(special, &st) == -1) {
/*
* For now this is the 'last resort'.
*/
snprintf(special, len, "%svinum/%s",
_PATH_DEV, device);
}
}
}
device = special;
}
/*
* Open our device for reading.
*/
fsi = open(device, O_RDONLY);
if (fsi < 0) {
fprintf(stderr, "%s: %s\n", device, strerror(errno));
exit(-1);
}
stat(device, &st);
if(S_ISREG(st.st_mode)) { /* label check not supported for files */
Lflag=1;
}
if(!Lflag) {
/*
* Try to read a label and gess the slice if not specified.
* This code should guess the right thing and avaid to bother
* the user user with the task of specifying the option -v on
* vinum volumes.
*/
cp=device+strlen(device)-1;
lp = get_disklabel(fsi);
if(lp->d_type == DTYPE_VINUM) {
pp = &lp->d_partitions[0];
} else if (isdigit(*cp)) {
pp = &lp->d_partitions[2];
} else if (*cp>='a' && *cp<='h') {
pp = &lp->d_partitions[*cp - 'a'];
} else {
fprintf(stderr, "unknown device\n");
exit(-1);
}
/*
* Check if that partition looks suited for dumping.
*/
if (pp->p_size < 1) {
fprintf(stderr, "partition is unavailable\n");
exit(-1);
}
if (pp->p_fstype != FS_BSDFFS) {
fprintf(stderr, "partition not 4.2BSD\n");
exit(-1);
}
}
/*
* Read the current superblock.
*/
rdfs((daddr_t)(SBOFF/DEV_BSIZE), SBSIZE, (char *)&(sblock), fsi);
if (sblock.fs_magic != FS_MAGIC) {
fprintf(stderr, "superblock not recognized\n");
exit(-1);
}
DBG_OPEN(out_file); /* already here we need a superblock */
if(cfg_lv & 0x001) {
DBG_DUMP_FS(&sblock, "primary sblock");
}
/*
* Determine here what cylinder groups to dump.
*/
if(cfg_cg==-2) {
cg_start=0;
cg_stop=sblock.fs_ncg;
} else if (cfg_cg==-1) {
cg_start=sblock.fs_ncg-1;
cg_stop=sblock.fs_ncg;
} else if (cfg_cg<sblock.fs_ncg) {
cg_start=cfg_cg;
cg_stop=cfg_cg+1;
} else {
cg_start=sblock.fs_ncg;
cg_stop=sblock.fs_ncg;
}
if (cfg_lv & 0x004) {
fscs = (struct csum *)calloc(1, (size_t)sblock.fs_cssize);
/*
* Get the cylinder summary into the memory ...
*/
for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
rdfs(fsbtodb(&sblock, sblock.fs_csaddr +
numfrags(&sblock, i)), sblock.fs_cssize - i <
sblock.fs_bsize ? sblock.fs_cssize - i :
sblock.fs_bsize, ((char *)fscs) + i, fsi);
}
dbg_csp=fscs;
/*
* ... and dump it.
*/
for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) {
snprintf(dbg_line, 80, "%d. csum in fscs",
dbg_csc);
DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++);
}
}
/*
* For each requested cylinder group ...
*/
for(cylno=cg_start; cylno<cg_stop; cylno++) {
snprintf(dbg_line, 80, "cgr %d", cylno);
if(cfg_lv & 0x002) {
/*
* ... dump the superblock copies ...
*/
rdfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
SBSIZE, (char *)&osblock, fsi);
DBG_DUMP_FS(&osblock, dbg_line);
}
/*
* ... read the cylinder group and dump whatever was requested.
*/
rdfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_cgsize,
(char *)&acg, fsi);
if(cfg_lv & 0x008) {
DBG_DUMP_CG(&sblock, dbg_line, &acg);
}
if(cfg_lv & 0x010) {
DBG_DUMP_INMAP(&sblock, dbg_line, &acg);
}
if(cfg_lv & 0x020) {
DBG_DUMP_FRMAP(&sblock, dbg_line, &acg);
}
if(cfg_lv & 0x040) {
DBG_DUMP_CLMAP(&sblock, dbg_line, &acg);
DBG_DUMP_CLSUM(&sblock, dbg_line, &acg);
}
if(cfg_lv & 0x080) {
DBG_DUMP_SPTBL(&sblock, dbg_line, &acg);
}
}
/*
* Dump the requested inode(s).
*/
if(cfg_in != -2) {
dump_whole_inode((ino_t)cfg_in, fsi, cfg_lv);
} else {
for(in=cg_start*sblock.fs_ipg; in<(ino_t)cg_stop*sblock.fs_ipg;
in++) {
dump_whole_inode(in, fsi, cfg_lv);
}
}
DBG_CLOSE;
close(fsi);
DBG_LEAVE;
return 0;
}
/* ************************************************** dump_whole_inode ***** */
/*
* Here we dump a list of all blocks allocated by this inode. We follow
* all indirect blocks.
*/
void
dump_whole_inode(ino_t inode, int fsi, int level)
{
DBG_FUNC("dump_whole_inode")
struct dinode *ino;
int rb;
unsigned int ind2ctr, ind3ctr;
ufs_daddr_t *ind2ptr, *ind3ptr;
char comment[80];
DBG_ENTER;
/*
* Read the inode from disk/cache.
*/
ino=ginode(inode, fsi);
if(ino->di_nlink==0) {
DBG_LEAVE;
return; /* inode not in use */
}
/*
* Dump the main inode structure.
*/
snprintf(comment, 80, "Inode 0x%08x", inode);
if (level & 0x100) {
DBG_DUMP_INO(&sblock, comment, ino);
}
if (!(level & 0x200)) {
DBG_LEAVE;
return;
}
/*
* Ok, now prepare for dumping all direct and indirect pointers.
*/
rb=howmany(ino->di_size, sblock.fs_bsize)-NDADDR;
if(rb>0) {
/*
* Dump single indirect block.
*/
rdfs(fsbtodb(&sblock, ino->di_ib[0]), sblock.fs_bsize, i1blk,
fsi);
snprintf(comment, 80, "Inode 0x%08x: indirect 0", inode);
DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb);
rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t));
}
if(rb>0) {
/*
* Dump double indirect blocks.
*/
rdfs(fsbtodb(&sblock, ino->di_ib[1]), sblock.fs_bsize, i2blk,
fsi);
snprintf(comment, 80, "Inode 0x%08x: indirect 1", inode);
DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb,
howmany(sblock.fs_bsize, sizeof(ufs_daddr_t))));
for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr++) {
ind2ptr=&((ufs_daddr_t *)&i2blk)[ind2ctr];
rdfs(fsbtodb(&sblock, *ind2ptr), sblock.fs_bsize,
i1blk, fsi);
snprintf(comment, 80, "Inode 0x%08x: indirect 1->%d",
inode, ind2ctr);
DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb);
rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t));
}
}
if(rb>0) {
/*
* Dump triple indirect blocks.
*/
rdfs(fsbtodb(&sblock, ino->di_ib[2]), sblock.fs_bsize, i3blk,
fsi);
snprintf(comment, 80, "Inode 0x%08x: indirect 2", inode);
#define SQUARE(a) ((a)*(a))
DBG_DUMP_IBLK(&sblock, comment, i3blk, howmany(rb,
SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))));
#undef SQUARE
for(ind3ctr=0; ((ind3ctr < howmany(sblock.fs_bsize,
sizeof(ufs_daddr_t)))&&(rb>0)); ind3ctr ++) {
ind3ptr=&((ufs_daddr_t *)&i3blk)[ind3ctr];
rdfs(fsbtodb(&sblock, *ind3ptr), sblock.fs_bsize,
i2blk, fsi);
snprintf(comment, 80, "Inode 0x%08x: indirect 2->%d",
inode, ind3ctr);
DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb,
howmany(sblock.fs_bsize, sizeof(ufs_daddr_t))));
for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr ++) {
ind2ptr=&((ufs_daddr_t *)&i2blk)[ind2ctr];
rdfs(fsbtodb(&sblock, *ind2ptr),
sblock.fs_bsize, i1blk, fsi);
snprintf(comment, 80,
"Inode 0x%08x: indirect 2->%d->%d", inode,
ind3ctr, ind3ctr);
DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb);
rb-=howmany(sblock.fs_bsize,
sizeof(ufs_daddr_t));
}
}
}
DBG_LEAVE;
return;
}
/* ***************************************************** get_disklabel ***** */
/*
* Read the disklabel from disk.
*/
struct disklabel *
get_disklabel(int fd)
{
DBG_FUNC("get_disklabel")
static struct disklabel *lab;
DBG_ENTER;
lab=(struct disklabel *)malloc(sizeof(struct disklabel));
if (!lab) {
fprintf(stderr, "malloc failed\n");
exit(-1);
}
if (ioctl(fd, DIOCGDINFO, (char *)lab) < 0) {
fprintf(stderr, "DIOCGDINFO failed\n");
exit(-1);
}
DBG_LEAVE;
return (lab);
}
/* ************************************************************* usage ***** */
/*
* Dump a line of usage.
*/
void
usage(char *name)
{
DBG_FUNC("usage")
char *basename;
DBG_ENTER;
basename=strrchr(name, '/');
if(!basename) {
basename=name;
} else {
basename++;
}
fprintf(stderr,
"usage:\t%s\t[-L] [-g cylgrp] [-i inode] [-l level] [-o outfile]\n"
"\t\t< special | file >\n",
basename);
DBG_LEAVE;
exit(-1);
}
/* ************************************************************ ginode ***** */
/*
* This function provides access to an individual inode. We find out in which
* block the requested inode is located, read it from disk if needed, and
* return the pointer into that block. We maintain a cache of one block to
* not read the same block again and again if we iterate lineary over all
* inodes.
*/
struct dinode *
ginode(ino_t inumber, int fsi)
{
DBG_FUNC("ginode")
ufs_daddr_t iblk;
static ino_t startinum=0; /* first inode in cached block */
struct dinode *pi;
DBG_ENTER;
pi=(struct dinode *)ablk;
if (startinum == 0 || inumber < startinum ||
inumber >= startinum + INOPB(&sblock)) {
/*
* The block needed is not cached, so we have to read it from
* disk now.
*/
iblk = ino_to_fsba(&sblock, inumber);
rdfs(fsbtodb(&sblock, iblk), sblock.fs_bsize, (char *)&ablk,
fsi);
startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
}
DBG_LEAVE;
return (&(pi[inumber % INOPB(&sblock)]));
}

View File

@ -73,12 +73,16 @@ pass1()
cgd = cgdmin(&sblock, c);
if (c == 0) {
i = cgbase(&sblock, c);
cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
} else
i = cgsblock(&sblock, c);
for (; i < cgd; i++)
setbmap(i);
}
i = sblock.fs_csaddr;
cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
for (; i < cgd; i++)
setbmap(i);
/*
* Find all allocated blocks.
*/

21
sbin/growfs/Makefile Normal file
View File

@ -0,0 +1,21 @@
# @(#)Makefile 8.8 (Berkeley) 6/21/2000
#
# $TSHeader: src/sbin/growfs/Makefile,v 1.4 2000/12/05 19:45:24 tomsoft Exp $
# $FreeBSD$
#
MAINTAINER= tomsoft@FreeBSD.ORG, chm@FreeBSD.ORG
#GFSDBG=YES
#CFLAGS+=${BDECFLAGS}
PROG= growfs
SRCS= growfs.c
MAN8= growfs.8
.if defined(GFSDBG)
SRCS+= debug.c
CFLAGS+=-DFS_DEBUG
.endif
.include <bsd.prog.mk>

699
sbin/growfs/debug.c Normal file
View File

@ -0,0 +1,699 @@
/*
* Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
* Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
*
* 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 acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors, as well as Christoph
* Herrmann and Thomas-Henning von Kamptz.
* 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.
*
* $TSHeader: src/sbin/growfs/debug.c,v 1.2 2000/11/16 18:43:49 tom Exp $
* $FreeBSD$
*
*/
#ifndef lint
static const char rcsid[] =
"$TSHeader: src/sbin/growfs/debug.c,v 1.2 2000/11/16 18:43:49 tom Exp $";
#endif /* not lint */
/* ********************************************************** INCLUDES ***** */
#include <sys/param.h>
#include <stdio.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include "debug.h"
#ifdef FS_DEBUG
/* *********************************************************** GLOBALS ***** */
static FILE *dbg_log=NULL;
static unsigned int indent=0;
/*
* prototypes not done here, as they come with debug.h
*/
/* ********************************************************** dbg_open ***** */
/*
* Open the filehandle where all debug output has to go.
*/
void
dbg_open(const char *fn)
{
dbg_log=fopen(fn, "a");
return;
}
/* ********************************************************* dbg_close ***** */
/*
* Close the filehandle where all debug output went to.
*/
void
dbg_close(void)
{
if(dbg_log) {
fclose(dbg_log);
dbg_log=NULL;
}
return;
}
/* ****************************************************** dbg_dump_hex ***** */
/*
* Dump out a full filesystem block in hex.
*/
void
dbg_dump_hex(struct fs *sb, const char *comment, unsigned char *mem)
{
int i, j, k;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START HEXDUMP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)mem, comment);
indent++;
for (i=0; i<sb->fs_bsize; i+=24) {
for (j=0; j<3; j++) {
for (k=0; k<8; k++) {
fprintf(dbg_log, "%02x ", *mem++);
}
fprintf(dbg_log, " ");
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END HEXDUMP =====\n");
return;
}
/* ******************************************************* dbg_dump_fs ***** */
/*
* Dump the superblock.
*/
void
dbg_dump_fs(struct fs *sb, const char *comment)
{
#ifdef FSMAXSNAP
int j;
#endif /* FSMAXSNAP */
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START SUPERBLOCK =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)sb, comment);
indent++;
fprintf(dbg_log, "sblkno ufs_daddr_t 0x%08x\n",
sb->fs_sblkno);
fprintf(dbg_log, "cblkno ufs_daddr_t 0x%08x\n",
sb->fs_cblkno);
fprintf(dbg_log, "iblkno ufs_daddr_t 0x%08x\n",
sb->fs_iblkno);
fprintf(dbg_log, "dblkno ufs_daddr_t 0x%08x\n",
sb->fs_dblkno);
fprintf(dbg_log, "cgoffset int32_t 0x%08x\n",
sb->fs_cgoffset);
fprintf(dbg_log, "cgmask int32_t 0x%08x\n",
sb->fs_cgmask);
fprintf(dbg_log, "time time_t %10lu\n",
sb->fs_time);
fprintf(dbg_log, "size int32_t 0x%08x\n",
sb->fs_size);
fprintf(dbg_log, "dsize int32_t 0x%08x\n",
sb->fs_dsize);
fprintf(dbg_log, "ncg int32_t 0x%08x\n",
sb->fs_ncg);
fprintf(dbg_log, "bsize int32_t 0x%08x\n",
sb->fs_bsize);
fprintf(dbg_log, "fsize int32_t 0x%08x\n",
sb->fs_fsize);
fprintf(dbg_log, "frag int32_t 0x%08x\n",
sb->fs_frag);
fprintf(dbg_log, "minfree int32_t 0x%08x\n",
sb->fs_minfree);
fprintf(dbg_log, "rotdelay int32_t 0x%08x\n",
sb->fs_rotdelay);
fprintf(dbg_log, "rps int32_t 0x%08x\n",
sb->fs_rps);
fprintf(dbg_log, "bmask int32_t 0x%08x\n",
sb->fs_bmask);
fprintf(dbg_log, "fmask int32_t 0x%08x\n",
sb->fs_fmask);
fprintf(dbg_log, "bshift int32_t 0x%08x\n",
sb->fs_bshift);
fprintf(dbg_log, "fshift int32_t 0x%08x\n",
sb->fs_fshift);
fprintf(dbg_log, "maxcontig int32_t 0x%08x\n",
sb->fs_maxcontig);
fprintf(dbg_log, "maxbpg int32_t 0x%08x\n",
sb->fs_maxbpg);
fprintf(dbg_log, "fragshift int32_t 0x%08x\n",
sb->fs_fragshift);
fprintf(dbg_log, "fsbtodb int32_t 0x%08x\n",
sb->fs_fsbtodb);
fprintf(dbg_log, "sbsize int32_t 0x%08x\n",
sb->fs_sbsize);
fprintf(dbg_log, "csmask int32_t 0x%08x\n",
sb->fs_csmask);
fprintf(dbg_log, "csshift int32_t 0x%08x\n",
sb->fs_csshift);
fprintf(dbg_log, "nindir int32_t 0x%08x\n",
sb->fs_nindir);
fprintf(dbg_log, "inopb int32_t 0x%08x\n",
sb->fs_inopb);
fprintf(dbg_log, "nspf int32_t 0x%08x\n",
sb->fs_nspf);
fprintf(dbg_log, "optim int32_t 0x%08x\n",
sb->fs_optim);
fprintf(dbg_log, "npsect int32_t 0x%08x\n",
sb->fs_npsect);
fprintf(dbg_log, "interleave int32_t 0x%08x\n",
sb->fs_interleave);
fprintf(dbg_log, "trackskew int32_t 0x%08x\n",
sb->fs_trackskew);
fprintf(dbg_log, "id int32_t[2] %08x %08x\n",
sb->fs_id[0], sb->fs_id[1]);
fprintf(dbg_log, "csaddr ufs_daddr_t 0x%08x\n",
sb->fs_csaddr);
fprintf(dbg_log, "cssize int32_t 0x%08x\n",
sb->fs_cssize);
fprintf(dbg_log, "cgsize int32_t 0x%08x\n",
sb->fs_cgsize);
fprintf(dbg_log, "ntrak int32_t 0x%08x\n",
sb->fs_ntrak);
fprintf(dbg_log, "nsect int32_t 0x%08x\n",
sb->fs_nsect);
fprintf(dbg_log, "spc int32_t 0x%08x\n",
sb->fs_spc);
fprintf(dbg_log, "ncyl int32_t 0x%08x\n",
sb->fs_ncyl);
fprintf(dbg_log, "cpg int32_t 0x%08x\n",
sb->fs_cpg);
fprintf(dbg_log, "ipg int32_t 0x%08x\n",
sb->fs_ipg);
fprintf(dbg_log, "fpg int32_t 0x%08x\n",
sb->fs_fpg);
dbg_dump_csum("internal cstotal", &sb->fs_cstotal);
fprintf(dbg_log, "fmod int8_t 0x%02x\n",
sb->fs_fmod);
fprintf(dbg_log, "clean int8_t 0x%02x\n",
sb->fs_clean);
fprintf(dbg_log, "ronly int8_t 0x%02x\n",
sb->fs_ronly);
fprintf(dbg_log, "flags int8_t 0x%02x\n",
sb->fs_flags);
fprintf(dbg_log, "fsmnt u_char[MAXMNTLEN] \"%s\"\n",
sb->fs_fsmnt);
fprintf(dbg_log, "cgrotor int32_t 0x%08x\n",
sb->fs_cgrotor);
/*
* struct csum[MAXCSBUFS] - is only maintained in memory
*/
/* fprintf(dbg_log, " int32_t\n", sb->*fs_maxcluster);*/
fprintf(dbg_log, "cpc int32_t 0x%08x\n",
sb->fs_cpc);
/*
* int16_t fs_opostbl[16][8] - is dumped when used in dbg_dump_sptbl
*/
#ifdef FSMAXSNAP
for(j=0; j<FSMAXSNAP; j++) {
fprintf(dbg_log, "snapinum int32_t[%2d] 0x%08x\n",
j, sb->fs_snapinum[j]);
if(!sb->fs_snapinum[j]) { /* list is dense */
break;
}
}
#endif /* FSMAXSNAP */
fprintf(dbg_log, "contigsumsize int32_t 0x%08x\n",
sb->fs_contigsumsize);
fprintf(dbg_log, "maxsymlinklen int32_t 0x%08x\n",
sb->fs_maxsymlinklen);
fprintf(dbg_log, "inodefmt int32_t 0x%08x\n",
sb->fs_inodefmt);
fprintf(dbg_log, "maxfilesize u_int64_t 0x%08x%08x\n",
((unsigned int *)&(sb->fs_maxfilesize))[1],
((unsigned int *)&(sb->fs_maxfilesize))[0]);
fprintf(dbg_log, "qbmask int64_t 0x%08x%08x\n",
((unsigned int *)&(sb->fs_qbmask))[1],
((unsigned int *)&(sb->fs_qbmask))[0]);
fprintf(dbg_log, "qfmask int64_t 0x%08x%08x\n",
((unsigned int *)&(sb->fs_qfmask))[1],
((unsigned int *)&(sb->fs_qfmask))[0]);
fprintf(dbg_log, "state int32_t 0x%08x\n",
sb->fs_state);
fprintf(dbg_log, "postblformat int32_t 0x%08x\n",
sb->fs_postblformat);
fprintf(dbg_log, "nrpos int32_t 0x%08x\n",
sb->fs_nrpos);
fprintf(dbg_log, "postbloff int32_t 0x%08x\n",
sb->fs_postbloff);
fprintf(dbg_log, "rotbloff int32_t 0x%08x\n",
sb->fs_rotbloff);
fprintf(dbg_log, "magic int32_t 0x%08x\n",
sb->fs_magic);
indent--;
fprintf(dbg_log, "===== END SUPERBLOCK =====\n");
return;
}
/* ******************************************************* dbg_dump_cg ***** */
/*
* Dump a cylinder group.
*/
void
dbg_dump_cg(const char *comment, struct cg *cgr)
{
int j;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START CYLINDER GROUP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
fprintf(dbg_log, "magic int32_t 0x%08x\n", cgr->cg_magic);
fprintf(dbg_log, "time time_t %10lu\n", cgr->cg_time);
fprintf(dbg_log, "cgx int32_t 0x%08x\n", cgr->cg_cgx);
fprintf(dbg_log, "ncyl int16_t 0x%04x\n", cgr->cg_ncyl);
fprintf(dbg_log, "niblk int16_t 0x%04x\n", cgr->cg_niblk);
fprintf(dbg_log, "ndblk int32_t 0x%08x\n", cgr->cg_ndblk);
dbg_dump_csum("internal cs", &cgr->cg_cs);
fprintf(dbg_log, "rotor int32_t 0x%08x\n", cgr->cg_rotor);
fprintf(dbg_log, "frotor int32_t 0x%08x\n", cgr->cg_frotor);
fprintf(dbg_log, "irotor int32_t 0x%08x\n", cgr->cg_irotor);
for(j=0; j<MAXFRAG; j++) {
fprintf(dbg_log, "frsum int32_t[%d] 0x%08x\n", j,
cgr->cg_frsum[j]);
}
fprintf(dbg_log, "btotoff int32_t 0x%08x\n", cgr->cg_btotoff);
fprintf(dbg_log, "boff int32_t 0x%08x\n", cgr->cg_boff);
fprintf(dbg_log, "iusedoff int32_t 0x%08x\n", cgr->cg_iusedoff);
fprintf(dbg_log, "freeoff int32_t 0x%08x\n", cgr->cg_freeoff);
fprintf(dbg_log, "nextfreeoff int32_t 0x%08x\n",
cgr->cg_nextfreeoff);
fprintf(dbg_log, "clustersumoff int32_t 0x%08x\n",
cgr->cg_clustersumoff);
fprintf(dbg_log, "clusterof int32_t 0x%08x\n",
cgr->cg_clusteroff);
fprintf(dbg_log, "nclusterblks int32_t 0x%08x\n",
cgr->cg_nclusterblks);
indent--;
fprintf(dbg_log, "===== END CYLINDER GROUP =====\n");
return;
}
/* ***************************************************** dbg_dump_csum ***** */
/*
* Dump a cylinder summary.
*/
void
dbg_dump_csum(const char *comment, struct csum *cs)
{
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START CYLINDER SUMMARY =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cs, comment);
indent++;
fprintf(dbg_log, "ndir int32_t 0x%08x\n", cs->cs_ndir);
fprintf(dbg_log, "nbfree int32_t 0x%08x\n", cs->cs_nbfree);
fprintf(dbg_log, "nifree int32_t 0x%08x\n", cs->cs_nifree);
fprintf(dbg_log, "nffree int32_t 0x%08x\n", cs->cs_nffree);
indent--;
fprintf(dbg_log, "===== END CYLINDER SUMMARY =====\n");
return;
}
/* **************************************************** dbg_dump_inmap ***** */
/*
* Dump the inode allocation map in one cylinder group.
*/
void
dbg_dump_inmap(struct fs *sb, const char *comment, struct cg *cgr)
{
int j,k,l,e;
unsigned char *cp;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START INODE ALLOCATION MAP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
cp=(unsigned char *)cg_inosused(cgr);
e=sb->fs_ipg/8;
for(j=0; j<e; j+=32) {
fprintf(dbg_log, "%08x: ", j);
for(k=0; k<32; k+=8) {
if(j+k+8<e) {
fprintf(dbg_log,
"%02x%02x%02x%02x%02x%02x%02x%02x ",
cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
} else {
for(l=0; (l<8)&&(j+k+l<e); l++) {
fprintf(dbg_log, "%02x", cp[l]);
}
}
cp+=8;
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END INODE ALLOCATION MAP =====\n");
return;
}
/* **************************************************** dbg_dump_frmap ***** */
/*
* Dump the fragment allocation map in one cylinder group.
*/
void
dbg_dump_frmap(struct fs *sb, const char *comment, struct cg *cgr)
{
int j,k,l,e;
unsigned char *cp;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START FRAGMENT ALLOCATION MAP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
cp=(unsigned char *)cg_blksfree(cgr);
e=howmany((sb->fs_cpg * sb->fs_spc / NSPF(sb)), NBBY);
for(j=0; j<e; j+=32) {
fprintf(dbg_log, "%08x: ", j);
for(k=0; k<32; k+=8) {
if(j+k+8<e) {
fprintf(dbg_log,
"%02x%02x%02x%02x%02x%02x%02x%02x ",
cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
} else {
for(l=0; (l<8)&&(j+k+l<e); l++) {
fprintf(dbg_log, "%02x", cp[l]);
}
}
cp+=8;
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END FRAGMENT ALLOCATION MAP =====\n");
return;
}
/* **************************************************** dbg_dump_clmap ***** */
/*
* Dump the cluster allocation map in one cylinder group.
*/
void
dbg_dump_clmap(struct fs *sb, const char *comment, struct cg *cgr)
{
int j,k,l,e;
unsigned char *cp;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START CLUSTER ALLOCATION MAP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
cp=(unsigned char *)cg_clustersfree(cgr);
e=howmany(sb->fs_cpg * sb->fs_spc / NSPB(sb), NBBY);
for(j=0; j<e; j+=32) {
fprintf(dbg_log, "%08x: ", j);
for(k=0; k<32; k+=8) {
if(j+k+8<e) {
fprintf(dbg_log,
"%02x%02x%02x%02x%02x%02x%02x%02x ",
cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
} else {
for(l=0; (l<8)&&(j+k+l<e); l++) {
fprintf(dbg_log, "%02x", cp[l]);
}
}
cp+=8;
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END CLUSTER ALLOCATION MAP =====\n");
return;
}
/* **************************************************** dbg_dump_clsum ***** */
/*
* Dump the cluster availability summary of one cylinder group.
*/
void
dbg_dump_clsum(struct fs *sb, const char *comment, struct cg *cgr)
{
int j;
long *lp;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START CLUSTER SUMMARY =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
lp=(long *)cg_clustersum(cgr);
for(j=0; j<=sb->fs_contigsumsize; j++) {
fprintf(dbg_log, "%02d: %8ld\n", j, *lp++);
}
indent--;
fprintf(dbg_log, "===== END CLUSTER SUMMARY =====\n");
return;
}
/* **************************************************** dbg_dump_sptbl ***** */
/*
* Dump the block summary, and the rotational layout table.
*/
void
dbg_dump_sptbl(struct fs *sb, const char *comment, struct cg *cgr)
{
int j,k;
long *lp;
if(!dbg_log) {
return;
}
fprintf(dbg_log,
"===== START BLOCK SUMMARY AND POSITION TABLE =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
indent++;
lp=(long *)cg_blktot(cgr);
for(j=0; j<sb->fs_cpg; j++) {
fprintf(dbg_log, "%2d: %5ld = ", j, *lp++);
for(k=0; k<sb->fs_nrpos; k++) {
fprintf(dbg_log, "%4d", cg_blks(sb, cgr, j)[k]);
if(k<sb->fs_nrpos-1) {
fprintf(dbg_log, " + ");
}
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END BLOCK SUMMARY AND POSITION TABLE =====\n");
return;
}
/* ****************************************************** dbg_dump_ino ***** */
/*
* Dump an inode structure.
*/
void
dbg_dump_ino(struct fs *sb, const char *comment, struct dinode *ino)
{
int ictr;
int remaining_blocks;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START INODE DUMP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)ino, comment);
indent++;
fprintf(dbg_log, "mode u_int16_t 0%o\n", ino->di_mode);
fprintf(dbg_log, "nlink int16_t 0x%04x\n", ino->di_nlink);
fprintf(dbg_log, "size u_int64_t 0x%08x%08x\n",
((unsigned int *)&(ino->di_size))[1],
((unsigned int *)&(ino->di_size))[0]);
fprintf(dbg_log, "atime int32_t 0x%08x\n", ino->di_atime);
fprintf(dbg_log, "atimensec int32_t 0x%08x\n",
ino->di_atimensec);
fprintf(dbg_log, "mtime int32_t 0x%08x\n",
ino->di_mtime);
fprintf(dbg_log, "mtimensec int32_t 0x%08x\n",
ino->di_mtimensec);
fprintf(dbg_log, "ctime int32_t 0x%08x\n", ino->di_ctime);
fprintf(dbg_log, "ctimensec int32_t 0x%08x\n",
ino->di_ctimensec);
remaining_blocks=howmany(ino->di_size, sb->fs_bsize); /* XXX ts - +1? */
for(ictr=0; ictr < MIN(NDADDR, remaining_blocks); ictr++) {
fprintf(dbg_log, "db ufs_daddr_t[%x] 0x%08x\n", ictr,
ino->di_db[ictr]);
}
remaining_blocks-=NDADDR;
if(remaining_blocks>0) {
fprintf(dbg_log, "ib ufs_daddr_t[0] 0x%08x\n",
ino->di_ib[0]);
}
remaining_blocks-=howmany(sb->fs_bsize, sizeof(ufs_daddr_t));
if(remaining_blocks>0) {
fprintf(dbg_log, "ib ufs_daddr_t[1] 0x%08x\n",
ino->di_ib[1]);
}
#define SQUARE(a) ((a)*(a))
remaining_blocks-=SQUARE(howmany(sb->fs_bsize, sizeof(ufs_daddr_t)));
#undef SQUARE
if(remaining_blocks>0) {
fprintf(dbg_log, "ib ufs_daddr_t[2] 0x%08x\n",
ino->di_ib[2]);
}
fprintf(dbg_log, "flags u_int32_t 0x%08x\n", ino->di_flags);
fprintf(dbg_log, "blocks int32_t 0x%08x\n", ino->di_blocks);
fprintf(dbg_log, "gen int32_t 0x%08x\n", ino->di_gen);
fprintf(dbg_log, "uid u_int32_t 0x%08x\n", ino->di_uid);
fprintf(dbg_log, "gid u_int32_t 0x%08x\n", ino->di_gid);
indent--;
fprintf(dbg_log, "===== END INODE DUMP =====\n");
return;
}
/* ***************************************************** dbg_dump_iblk ***** */
/*
* Dump an indirect block. The iteration to dump a full file has to be
* written around.
*/
void
dbg_dump_iblk(struct fs *sb, const char *comment, char *block, size_t length)
{
unsigned int *mem;
int i, j;
if(!dbg_log) {
return;
}
fprintf(dbg_log, "===== START INDIRECT BLOCK DUMP =====\n");
fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)block,
comment);
indent++;
mem=(unsigned int *)block;
for (i=0; (size_t)i<MIN(howmany(sb->fs_bsize, sizeof(ufs_daddr_t)),
length); i+=8) {
fprintf(dbg_log, "%04x: ", i);
for (j=0; j<8; j++) {
if((size_t)(i+j)<length) {
fprintf(dbg_log, "%08X ", *mem++);
}
}
fprintf(dbg_log, "\n");
}
indent--;
fprintf(dbg_log, "===== END INDIRECT BLOCK DUMP =====\n");
return;
}
#endif /* FS_DEBUG */

137
sbin/growfs/debug.h Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
* Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
*
* 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 acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors, as well as Christoph
* Herrmann and Thomas-Henning von Kamptz.
* 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.
*
* $TSHeader: src/sbin/growfs/debug.h,v 1.2 2000/11/16 18:43:50 tom Exp $
* $FreeBSD$
*
*/
#ifdef FS_DEBUG
/* ********************************************************** INCLUDES ***** */
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
void dbg_open(const char *);
void dbg_close(void);
void dbg_dump_hex(struct fs *, const char *, unsigned char *);
void dbg_dump_fs(struct fs *, const char *);
void dbg_dump_cg(const char *, struct cg *);
void dbg_dump_csum(const char *, struct csum *);
void dbg_dump_ino(struct fs *, const char *, struct dinode *);
void dbg_dump_iblk(struct fs *, const char *, char *, size_t);
void dbg_dump_inmap(struct fs *, const char *, struct cg *);
void dbg_dump_frmap(struct fs *, const char *, struct cg *);
void dbg_dump_clmap(struct fs *, const char *, struct cg *);
void dbg_dump_clsum(struct fs *, const char *, struct cg *);
void dbg_dump_sptbl(struct fs *, const char *, struct cg *);
#define DBG_OPEN(P) dbg_open((P))
#define DBG_CLOSE dbg_close()
#define DBG_DUMP_HEX(F,C,M) dbg_dump_hex((F),(C),(M))
#define DBG_DUMP_FS(F,C) dbg_dump_fs((F),(C))
#define DBG_DUMP_CG(F,C,M) dbg_dump_cg((C),(M))
#define DBG_DUMP_CSUM(F,C,M) dbg_dump_csum((C),(M))
#define DBG_DUMP_INO(F,C,M) dbg_dump_ino((F),(C),(M))
#define DBG_DUMP_IBLK(F,C,M,L) dbg_dump_iblk((F),(C),(M),(L))
#define DBG_DUMP_INMAP(F,C,M) dbg_dump_inmap((F),(C),(M))
#define DBG_DUMP_FRMAP(F,C,M) dbg_dump_frmap((F),(C),(M))
#define DBG_DUMP_CLMAP(F,C,M) dbg_dump_clmap((F),(C),(M))
#define DBG_DUMP_CLSUM(F,C,M) dbg_dump_clsum((F),(C),(M))
#define DBG_DUMP_SPTBL(F,C,M) dbg_dump_sptbl((F),(C),(M))
#define DL_TRC 0x01
#define DL_INFO 0x02
extern int _dbg_lvl_;
#define DBG_FUNC(N) char __FKT__[] = (N);
#define DBG_ENTER if(_dbg_lvl_ & DL_TRC) { \
fprintf(stderr, "~>%s: %s\n", __FILE__, __FKT__ ); \
}
#define DBG_LEAVE if(_dbg_lvl_ & DL_TRC) { \
fprintf(stderr, "~<%s[%d]: %s\n", __FILE__, __LINE__, __FKT__ ); \
}
#define DBG_TRC if(_dbg_lvl_ & DL_TRC) { \
fprintf(stderr, "~=%s[%d]: %s\n", __FILE__, __LINE__, __FKT__ ); \
}
#define DBG_PRINT0(A) if(_dbg_lvl_ & DL_INFO) { \
fprintf(stderr, "~ %s", (A)); \
}
#define DBG_PRINT1(A,B) if(_dbg_lvl_ & DL_INFO) { \
fprintf(stderr, "~ "); \
fprintf(stderr, (A), (B)); \
}
#define DBG_PRINT2(A,B,C) if(_dbg_lvl_ & DL_INFO) { \
fprintf(stderr, "~ "); \
fprintf(stderr, (A), (B), (C)); \
}
#define DBG_PRINT3(A,B,C,D) if(_dbg_lvl_ & DL_INFO) { \
fprintf(stderr, "~ "); \
fprintf(stderr, (A), (B), (C), (D)); \
}
#define DBG_PRINT4(A,B,C,D,E) if(_dbg_lvl_ & DL_INFO) { \
fprintf(stderr, "~ "); \
fprintf(stderr, (A), (B), (C), (D), (E)); \
}
#else /* not FS_DEBUG */
#define DBG_OPEN(P)
#define DBG_CLOSE
#define DBG_DUMP_HEX(F,C,M)
#define DBG_DUMP_FS(F,C)
#define DBG_DUMP_CG(F,C,M)
#define DBG_DUMP_CSUM(F,C,M)
#define DBG_DUMP_INO(F,C,M)
#define DBG_DUMP_IBLK(F,C,M,L)
#define DBG_DUMP_INMAP(F,C,M)
#define DBG_DUMP_FRMAP(F,C,M)
#define DBG_DUMP_CLMAP(F,C,M)
#define DBG_DUMP_CLSUM(F,C,M)
#define DBG_DUMP_SPTBL(F,C,M)
#define DBG_FUNC(N)
#define DBG_ENTER
#define DBG_TRC
#define DBG_LEAVE
#define DBG_PRINT0(A)
#define DBG_PRINT1(A,B)
#define DBG_PRINT2(A,B,C)
#define DBG_PRINT3(A,B,C,D)
#define DBG_PRINT4(A,B,C,D,E)
#endif /* FS_DEBUG */

154
sbin/growfs/growfs.8 Normal file
View File

@ -0,0 +1,154 @@
.\" Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
.\" Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
.\"
.\" 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 acknowledgment:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors, as well as Christoph
.\" Herrmann and Thomas-Henning von Kamptz.
.\" 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.
.\"
.\" $TSHeader: src/sbin/growfs/growfs.8,v 1.2 2000/12/09 15:12:33 tomsoft Exp $
.\" $FreeBSD$
.\"
.Dd September 8, 2000
.Dt GROWFS 8
.Os BSD 4.4
.Sh NAME
.Nm growfs
.Nd grow size of an existing ufs file system
.Sh SYNOPSIS
.Nm growfs
.Op Fl Ny
.Op Fl s Ar size
.Ar special
.Sh DESCRIPTION
.Nm Growfs
extends the
.Xr newfs 8
program.
Before running
.Nm
the disk must be labeled to a bigger size using
.Xr disklabel 8 .
If you are using volumes you must grow them using
.Xr vinum 8 .
.Nm Growfs
extends the size of the file system on the specified special file.
Currently
.Nm
can only grow unmounted file systems. Do not try growing an mounted file system,
your system may panic and you will not be able to use the file system any longer.
Most of the options you have used with
.Xr newfs 8
once can not be changed. In fact you can only increase the size of the file
system. Use
.Xr tunefs 8
for other changes.
Typically the defaults are reasonable, however
.Nm
has some options to allow the defaults to be overridden.
.\".Pp
.Bl -tag -width indent
.It Fl N
Cause the new file system parameters to be printed out
without realy growing the file system.
.It Fl y
.Dq Expert mode
Normally
.Nm
will ask you, if you took a backup of your data before und will do some tests
if
.Ar special
is currently mounted or if there are any active snapshots on the filesystem
specified. This will be supressed. So use this option with care!
.It Fl s Ar size
The size of the file system after growing in sectors. This value defaults
to the size of the raw partition specified in
.Ar special
(in other words,
.Nm
will grow the file system to the size of the entire partition).
.El
.Sh EXAMPLES
.Pp
.Dl growfs -s 4194304 /dev/vinum/testvol
.Pp
will grow /dev/vinum/testvol up to 2GB if there is enough space in
/dev/vinum/testvol .
.Sh BUGS
In some cases on
.Bx Free
3.x it is possible, that
.Nm
did not recognize exactly, if the file system is mounted or not and
exits with an error message, then use
.Nm
-y if you are sure, that the file system is not mounted.
It is also recommended to always use
.Nm fsck
after growing just to be on the safe side.
.Pp
Pay attention, as in certain cases we have to change the location of an file
system internal structure which had never been moved before. Almost everything
works perfect with this relocated structure except the
.Nm fsck(8)
utility. There is a patch available for
.Nm fsck(8) .
For growing above certain limits it is essential to have some free blocks
available in the first cylinder group. To avoid the relocation of that
structure it is currently recommended to use
.Nm ffsinfo -c 0
on the first cylinder group and check that
.Nm nbfree
in the CYLINDER SUMMARY (internal cs) of the CYLINDER GROUP
.Nm cgr0
has enough blocks. As a rule of thumb for default filesystem parameters a block
is needed for every 2 GB of total filesystem size.
.Pp
.Sh SEE ALSO
.Xr vinum 8 ,
.Xr disklabel 8 ,
.Xr fsck 8 ,
.Xr newfs 8 ,
.Xr tunefs 8 ,
.Xr dumpfs 8 ,
.Xr ffsinfo 8
.\".Rs
.\".Re
.Sh AUTHORS
.An Christoph Herrmann Aq chm@FreeBSD.ORG
.An Thomas-Henning von Kamptz Aq tomsoft@FreeBSD.ORG
.An The GROWFS team Aq growfs@Tomsoft.COM
.Sh HISTORY
The
.Nm
command first appeared first in
.Bx Free
5.0.

2476
sbin/growfs/growfs.c Normal file

File diff suppressed because it is too large Load Diff