summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/fsck/dir.c96
-rw-r--r--sbin/fsck/fsck.8112
-rw-r--r--sbin/fsck/fsck.h47
-rw-r--r--sbin/fsck/inode.c92
-rw-r--r--sbin/fsck/main.c59
-rw-r--r--sbin/fsck/pass1.c110
-rw-r--r--sbin/fsck/pass1b.c7
-rw-r--r--sbin/fsck/pass2.c64
-rw-r--r--sbin/fsck/pass3.c71
-rw-r--r--sbin/fsck/pass4.c72
-rw-r--r--sbin/fsck/pass5.c38
-rw-r--r--sbin/fsck/preen.c62
-rw-r--r--sbin/fsck/setup.c49
-rw-r--r--sbin/fsck/utilities.c56
-rw-r--r--sbin/fsck_ffs/dir.c96
-rw-r--r--sbin/fsck_ffs/fsck.h47
-rw-r--r--sbin/fsck_ffs/fsck_ffs.8112
-rw-r--r--sbin/fsck_ffs/inode.c92
-rw-r--r--sbin/fsck_ffs/main.c59
-rw-r--r--sbin/fsck_ffs/pass1.c110
-rw-r--r--sbin/fsck_ffs/pass1b.c7
-rw-r--r--sbin/fsck_ffs/pass2.c64
-rw-r--r--sbin/fsck_ffs/pass3.c71
-rw-r--r--sbin/fsck_ffs/pass4.c72
-rw-r--r--sbin/fsck_ffs/pass5.c38
-rw-r--r--sbin/fsck_ffs/preen.c62
-rw-r--r--sbin/fsck_ffs/setup.c49
-rw-r--r--sbin/fsck_ffs/utilities.c56
-rw-r--r--sbin/fsck_ifs/dir.c96
-rw-r--r--sbin/fsck_ifs/fsck.h47
-rw-r--r--sbin/fsck_ifs/fsck_ifs.8112
-rw-r--r--sbin/fsck_ifs/inode.c92
-rw-r--r--sbin/fsck_ifs/main.c59
-rw-r--r--sbin/fsck_ifs/pass1.c110
-rw-r--r--sbin/fsck_ifs/pass1b.c7
-rw-r--r--sbin/fsck_ifs/pass2.c64
-rw-r--r--sbin/fsck_ifs/pass3.c71
-rw-r--r--sbin/fsck_ifs/pass4.c72
-rw-r--r--sbin/fsck_ifs/pass5.c38
-rw-r--r--sbin/fsck_ifs/preen.c62
-rw-r--r--sbin/fsck_ifs/setup.c49
-rw-r--r--sbin/fsck_ifs/utilities.c56
-rw-r--r--sbin/quotacheck/preen.c62
43 files changed, 1701 insertions, 1166 deletions
diff --git a/sbin/fsck/dir.c b/sbin/fsck/dir.c
index 91b507f..ceb66e6 100644
--- a/sbin/fsck/dir.c
+++ b/sbin/fsck/dir.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: dir.c,v 1.11 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -88,9 +85,9 @@ propagate()
inp = *inpp;
if (inp->i_parent == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE) {
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE) {
+ inoinfo(inp->i_number)->ino_state = DFOUND;
change++;
}
}
@@ -123,6 +120,8 @@ dirscan(idesc)
idesc->id_loc = 0;
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
+ if (dsize > sizeof(dbuf))
+ dsize = sizeof(dbuf);
memmove(dbuf, dp, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
@@ -235,8 +234,7 @@ dircheck(idesc, dp)
int spaceleft;
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
- if (dp->d_ino >= maxino ||
- dp->d_reclen == 0 ||
+ if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
@@ -306,13 +304,40 @@ adjust(idesc, lcnt)
register struct inodesc *idesc;
int lcnt;
{
- register struct dinode *dp;
+ struct dinode *dp;
+ int saveresolved;
dp = ginode(idesc->id_number);
if (dp->di_nlink == lcnt) {
- if (linkup(idesc->id_number, (ino_t)0) == 0)
- clri(idesc, "UNREF", 0);
- } else {
+ /*
+ * If we have not hit any unresolved problems, are running
+ * in preen mode, and are on a filesystem using soft updates,
+ * then just toss any partially allocated files.
+ */
+ if (resolved && preen && usedsoftdep) {
+ clri(idesc, "UNREF", 1);
+ return;
+ } else {
+ /*
+ * The filesystem can be marked clean even if
+ * a file is not linked up, but is cleared.
+ * Hence, resolved should not be cleared when
+ * linkup is answered no, but clri is answered yes.
+ */
+ saveresolved = resolved;
+ if (linkup(idesc->id_number, (ino_t)0, NULL) == 0) {
+ resolved = saveresolved;
+ clri(idesc, "UNREF", 0);
+ return;
+ }
+ /*
+ * Account for the new reference created by linkup().
+ */
+ dp = ginode(idesc->id_number);
+ lcnt--;
+ }
+ }
+ if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
@@ -355,7 +380,7 @@ mkentry(idesc)
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
dirp->d_reclen = newent.d_reclen;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
dirp->d_namlen = newent.d_namlen;
@@ -388,16 +413,17 @@ chgino(idesc)
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
return (ALTERED|STOP);
}
int
-linkup(orphan, parentdir)
+linkup(orphan, parentdir, name)
ino_t orphan;
ino_t parentdir;
+ char *name;
{
register struct dinode *dp;
int lostdir;
@@ -410,7 +436,7 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
- if ((preen || usedsoftdep) && dp->di_size == 0)
+ if (preen && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
@@ -431,6 +457,7 @@ linkup(orphan, parentdir)
lfdir = allocdir(ROOTINO, (ino_t)0, lfmode);
if (lfdir != 0) {
if (makeentry(ROOTINO, lfdir, lfname) != 0) {
+ numdirs++;
if (preen)
printf(" (CREATED)\n");
} else {
@@ -466,21 +493,21 @@ linkup(orphan, parentdir)
idesc.id_type = ADDR;
idesc.id_func = pass4check;
idesc.id_number = oldlfdir;
- adjust(&idesc, lncntp[oldlfdir] + 1);
- lncntp[oldlfdir] = 0;
+ adjust(&idesc, inoinfo(oldlfdir)->ino_linkcnt + 1);
+ inoinfo(oldlfdir)->ino_linkcnt = 0;
dp = ginode(lfdir);
}
- if (statemap[lfdir] != DFOUND) {
+ if (inoinfo(lfdir)->ino_state != DFOUND) {
pfatal("SORRY. NO lost+found DIRECTORY\n\n");
return (0);
}
(void)lftempname(tempname, orphan);
- if (makeentry(lfdir, orphan, tempname) == 0) {
+ if (makeentry(lfdir, orphan, (name ? name : tempname)) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
printf("\n\n");
return (0);
}
- lncntp[orphan]--;
+ inoinfo(orphan)->ino_linkcnt--;
if (lostdir) {
if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
parentdir != (ino_t)-1)
@@ -488,19 +515,11 @@ linkup(orphan, parentdir)
dp = ginode(lfdir);
dp->di_nlink++;
inodirty();
- lncntp[lfdir]++;
+ inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", orphan);
if (parentdir != (ino_t)-1) {
printf("PARENT WAS I=%lu\n", (u_long)parentdir);
- /*
- * The parent directory, because of the ordering
- * guarantees, has had the link count incremented
- * for the child, but no entry was made. This
- * fixes the parent link count so that fsck does
- * not need to be rerun.
- */
- lncntp[parentdir]++;
-
+ inoinfo(parentdir)->ino_linkcnt++;
}
if (preen == 0)
printf("\n");
@@ -658,19 +677,20 @@ allocdir(parent, request, mode)
dp->di_nlink = 2;
inodirty();
if (ino == ROOTINO) {
- lncntp[ino] = dp->di_nlink;
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
cacheino(dp, ino);
return(ino);
}
- if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
+ if (inoinfo(parent)->ino_state != DSTATE &&
+ inoinfo(parent)->ino_state != DFOUND) {
freeino(ino);
return (0);
}
cacheino(dp, ino);
- statemap[ino] = statemap[parent];
- if (statemap[ino] == DSTATE) {
- lncntp[ino] = dp->di_nlink;
- lncntp[parent]++;
+ inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
+ if (inoinfo(ino)->ino_state == DSTATE) {
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
+ inoinfo(parent)->ino_linkcnt++;
}
dp = ginode(parent);
dp->di_nlink++;
diff --git a/sbin/fsck/fsck.8 b/sbin/fsck/fsck.8
index 51d1679..20c867f 100644
--- a/sbin/fsck/fsck.8
+++ b/sbin/fsck/fsck.8
@@ -1,3 +1,4 @@
+.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -10,7 +11,7 @@
.\" 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:
+.\" 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
@@ -30,9 +31,8 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
-.\" $Id: fsck.8,v 1.10 1997/03/12 16:35:26 bde Exp $
.\"
-.Dd May 9, 1995
+.Dd November 15, 1996
.Dt FSCK 8
.Os BSD 4
.Sh NAME
@@ -43,24 +43,25 @@
.Fl p
.Op Fl f
.Op Fl m Ar mode
+.Op Ar filesystem
+.Ar ...
.Nm fsck
+.Op Fl ny
.Op Fl b Ar block#
.Op Fl c Ar level
.Op Fl l Ar maxparallel
-.Op Fl y
-.Op Fl n
.Op Fl m Ar mode
.Op Ar filesystem
.Ar ...
.Sh DESCRIPTION
The first form of
-.Nm
+.Nm fsck
preens a standard set of filesystems or the specified filesystems.
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
Here
-.Nm
+.Nm fsck
reads the table
.Pa /etc/fstab
to determine which filesystems to check.
@@ -73,22 +74,18 @@ running one process per disk drive.
The disk drive containing each filesystem is inferred from the longest prefix
of the device name that ends in a digit; the remaining characters are assumed
to be the partition designator.
-.Pp
-The clean flag of each filesystem's superblock is examined and only those filesystems that
-are not marked clean are checked.
+In preening mode,
+filesystems that are marked clean are skipped.
Filesystems are marked clean when they are unmounted,
when they have been mounted read-only, or when
-.Nm
+.Nm fsck
runs on them successfully.
-If the
-.Fl f
-option is specified, the filesystems
-will be checked regardless of the state of their clean flag.
.Pp
The kernel takes care that only a restricted class of innocuous filesystem
inconsistencies can happen unless hardware or software failures intervene.
These are limited to the following:
-.Bl -item -compact
+.Pp
+.Bl -item -compact -offset indent
.It
Unreferenced inodes
.It
@@ -102,7 +99,7 @@ Counts in the super-block wrong
.El
.Pp
These are the only inconsistencies that
-.Nm
+.Nm fsck
with the
.Fl p
option will correct; if it encounters other inconsistencies, it exits
@@ -110,7 +107,7 @@ with an abnormal return status and an automatic reboot will then fail.
For each corrected inconsistency one or more lines will be printed
identifying the filesystem on which the correction will take place,
and the nature of the correction. After successfully correcting a filesystem,
-.Nm
+.Nm fsck
will print the number of files on that filesystem,
the number of used and free blocks,
and the percentage of fragmentation.
@@ -118,7 +115,7 @@ and the percentage of fragmentation.
If sent a
.Dv QUIT
signal,
-.Nm
+.Nm fsck
will finish the filesystem checks, then exit with an abnormal
return status that causes an automatic reboot to fail.
This is useful when you want to finish the filesystem checks during an
@@ -128,7 +125,7 @@ but do not want the machine to come up multiuser after the checks complete.
Without the
.Fl p
option,
-.Nm
+.Nm fsck
audits and interactively repairs inconsistent conditions for filesystems.
If the filesystem is inconsistent the operator is prompted for concurrence
before each correction is attempted.
@@ -144,7 +141,7 @@ is to wait for the operator to respond
or
.Li no .
If the operator does not have write permission on the filesystem
-.Nm
+.Nm fsck
will default to a
.Fl n
action.
@@ -158,38 +155,12 @@ and
combined.
.Pp
The following flags are interpreted by
-.Nm Ns .
+.Nm fsck .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the filesystem. Block 32 is usually
an alternate super block.
-.It Fl l
-Limit the number of parallel checks to the number specified in the following
-argument.
-By default, the limit is the number of disks, running one process per disk.
-If a smaller limit is given, the disks are checked round-robin, one filesystem
-at a time.
-.It Fl m
-Use the mode specified in octal immediately after the flag as the
-permission bits to use when creating the
-.Pa lost+found
-directory rather than the default 1777.
-In particular, systems that do not wish to have lost files accessible
-by all users on the system should use a more restrictive
-set of permissions such as 700.
-.It Fl y
-Assume a yes response to all questions asked by
-.Nm Ns ;
-this should be used with great caution as this is a free license
-to continue after essentially unlimited trouble has been encountered.
-.It Fl n
-Assume a no response to all questions asked by
-.Nm
-except for
-.Ql CONTINUE? ,
-which is assumed to be affirmative;
-do not open the filesystem for writing.
.It Fl c
Convert the filesystem to the specified level.
Note that the level of a filesystem can only be raised.
@@ -210,7 +181,7 @@ If maxcontig is equal to one, delete any existing segment maps.
.El
.Pp
In interactive mode,
-.Nm
+.Nm fsck
will list the conversion to be made
and ask whether the conversion should be done.
If a negative answer is given,
@@ -223,10 +194,44 @@ are being converted at once.
The format of a filesystem can be determined from the
first line of output from
.Xr dumpfs 8 .
+.It Fl f
+Force
+.Nm fsck
+to check
+.Sq clean
+filesystems when preening.
+.It Fl l
+Limit the number of parallel checks to the number specified in the following
+argument.
+By default, the limit is the number of disks, running one process per disk.
+If a smaller limit is given, the disks are checked round-robin, one filesystem
+at a time.
+.It Fl m
+Use the mode specified in octal immediately after the flag as the
+permission bits to use when creating the
+.Pa lost+found
+directory rather than the default 1777.
+In particular, systems that do not wish to have lost files accessible
+by all users on the system should use a more restrictive
+set of permissions such as 700.
+.It Fl n
+Assume a no response to all questions asked by
+.Nm fsck
+except for
+.Ql CONTINUE? ,
+which is assumed to be affirmative;
+do not open the filesystem for writing.
+.It Fl p
+Preen filesystems (see above).
+.It Fl y
+Assume a yes response to all questions asked by
+.Nm fsck ;
+this should be used with great caution as this is a free license
+to continue after essentially unlimited trouble has been encountered.
.El
.Pp
If no filesystems are given to
-.Nm
+.Nm fsck
then a default list of filesystems is read from
the file
.Pa /etc/fstab .
@@ -259,7 +264,7 @@ File pointing to unallocated inode.
.It
Inode number out of range.
.It
-Holes in directories.
+Directories with unallocated blocks (holes).
.It
Dot or dot-dot not the first two entries of a directory
or having the wrong inode number.
@@ -296,14 +301,13 @@ contains default list of filesystems to check.
.El
.Sh DIAGNOSTICS
The diagnostics produced by
-.Nm
+.Nm fsck
are fully enumerated and explained in Appendix A of
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
-.Xr fs 5 ,
.Xr fstab 5 ,
-.Xr fsdb 8 ,
+.Xr fs 5 ,
.Xr newfs 8 ,
.Xr reboot 8
diff --git a/sbin/fsck/fsck.h b/sbin/fsck/fsck.h
index 4e0271d..81b2292 100644
--- a/sbin/fsck/fsck.h
+++ b/sbin/fsck/fsck.h
@@ -42,16 +42,35 @@
#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */
-#ifndef BUFSIZ
-#define BUFSIZ 1024
-#endif
-
+/*
+ * Each inode on the filesystem is described by the following structure.
+ * The linkcnt is initially set to the value in the inode. Each time it
+ * is found during the descent in passes 2, 3, and 4 the count is
+ * decremented. Any inodes whose count is non-zero after pass 4 needs to
+ * have its link count adjusted by the value remaining in ino_linkcnt.
+ */
+struct inostat {
+ char ino_state; /* state of inode, see below */
+ char ino_type; /* type of inode */
+ short ino_linkcnt; /* number of links not found */
+};
+/*
+ * Inode states.
+ */
#define USTATE 01 /* inode not allocated */
#define FSTATE 02 /* inode is file */
#define DSTATE 03 /* inode is directory */
#define DFOUND 04 /* directory found during descent */
#define DCLEAR 05 /* directory is to be cleared */
#define FCLEAR 06 /* file is to be cleared */
+/*
+ * Inode state information is contained on per cylinder group lists
+ * which are described by the following structure.
+ */
+struct inostatlist {
+ long il_numalloced; /* number of inodes allocated in this cg */
+ struct inostat *il_stat;/* inostat info for this cylinder group */
+} *inostathead;
/*
* buffer cache structure.
@@ -163,11 +182,12 @@ struct inoinfo {
ufs_daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, listmax, inplast;
+long countdirs; /* number of directories we actually found */
char *cdevname; /* name of device being checked */
long dev_bsize; /* computed value of DEV_BSIZE */
long secsize; /* actual disk sector size */
-char fflag; /* force fs check (ignore clean flag) */
+char fflag; /* force check, ignore clean flag */
char nflag; /* assume a no response */
char yflag; /* assume a yes response */
int bflag; /* location of alternate super block */
@@ -177,23 +197,19 @@ int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
-char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
+char rerun; /* rerun fsck. Only used in non-preen mode */
+int returntosingle; /* 1 => return to single user mode on exit */
+char resolved; /* cleared if unresolved changes => not clean */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */
int fsmodified; /* 1 => write done to file system */
int fsreadfd; /* file descriptor for reading file system */
int fswritefd; /* file descriptor for writing file system */
-int returntosingle; /* return to single user mode */
-int rerun; /* rerun fsck. Only used in non-preen mode */
ufs_daddr_t maxfsblock; /* number of blocks in the file system */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in file system */
-ino_t lastino; /* last inode in use */
-char *statemap; /* ptr to inode state table */
-u_char *typemap; /* ptr to inode type table */
-short *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
char *lfname; /* lost & found directory name */
@@ -219,6 +235,7 @@ struct dinode zino;
struct fstab;
+
void adjust __P((struct inodesc *, int lcnt));
ufs_daddr_t allocblk __P((long frags));
ino_t allocdir __P((ino_t parent, ino_t request, int mode));
@@ -239,6 +256,7 @@ int chkrange __P((ufs_daddr_t blk, int cnt));
void ckfini __P((int markclean));
int ckinode __P((struct dinode *dp, struct inodesc *));
void clri __P((struct inodesc *, char *type, int flag));
+int clearentry __P((struct inodesc *));
void direrror __P((ino_t ino, char *errmesg));
int dirscan __P((struct inodesc *));
int dofix __P((struct inodesc *, char *msg));
@@ -262,7 +280,8 @@ void getpathname __P((char *namebuf, ino_t curdir, ino_t ino));
struct dinode *ginode __P((ino_t inumber));
void inocleanup __P((void));
void inodirty __P((void));
-int linkup __P((ino_t orphan, ino_t parentdir));
+struct inostat *inoinfo __P((ino_t inum));
+int linkup __P((ino_t orphan, ino_t parentdir, char *name));
int makeentry __P((ino_t parent, ino_t ino, char *name));
void panic __P((const char *fmt, ...));
void pass1 __P((void));
@@ -278,6 +297,6 @@ void pinode __P((ino_t ino));
void propagate __P((void));
void pwarn __P((const char *fmt, ...));
int reply __P((char *question));
-void resetinodebuf __P((void));
+void setinodebuf __P((ino_t));
int setup __P((char *dev));
void voidquit __P((int));
diff --git a/sbin/fsck/inode.c b/sbin/fsck/inode.c
index b7e80cd..a54f2ce 100644
--- a/sbin/fsck/inode.c
+++ b/sbin/fsck/inode.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: inode.c,v 1.15 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -62,7 +58,8 @@ ckinode(dp, idesc)
register struct inodesc *idesc;
{
ufs_daddr_t *ap;
- long ret, n, ndb, offset;
+ int ret;
+ long n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
mode_t mode;
@@ -74,7 +71,7 @@ ckinode(dp, idesc)
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
- (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0)))
+ dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
@@ -239,8 +236,16 @@ chkrange(blk, cnt)
{
register int c;
- if (blk < 0 || blk >= maxfsblock || cnt < 0 || cnt > maxfsblock - blk)
+ if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
+ cnt - 1 > maxfsblock - blk)
return (1);
+ if (cnt > sblock.fs_frag ||
+ fragnum(&sblock, blk) + cnt > sblock.fs_frag) {
+ if (debug)
+ printf("bad size: blk %ld, offset %ld, size %ld\n",
+ blk, fragnum(&sblock, blk), cnt);
+ return (1);
+ }
c = dtog(&sblock, blk);
if (blk < cgdmin(&sblock, c)) {
if ((blk + cnt) > cgsblock(&sblock, c)) {
@@ -317,20 +322,29 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
- (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
+ /*
+ * If bread returns an error, it will already have zeroed
+ * out the buffer, so we do not need to do so here.
+ */
+ (void)bread(fsreadfd, (char *)inodebuf, dblk, size);
dp = inodebuf;
}
return (dp++);
}
void
-resetinodebuf()
+setinodebuf(inum)
+ ino_t inum;
{
+ if (inum % sblock.fs_ipg != 0)
+ errx(EEXIT, "bad inode number %d to setinodebuf", inum);
startinum = 0;
- nextino = 0;
- lastinum = 0;
+ nextino = inum;
+ lastinum = inum;
readcnt = 0;
+ if (inodebuf != NULL)
+ return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / sizeof(struct dinode);
readpercg = sblock.fs_ipg / fullcnt;
@@ -342,11 +356,8 @@ resetinodebuf()
partialcnt = fullcnt;
partialsize = inobufsize;
}
- if (inodebuf == NULL &&
- (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
+ if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
- while (nextino < ROOTINO)
- (void)getnextinode(nextino);
}
void
@@ -380,14 +391,11 @@ cacheino(dp, inumber)
inp = (struct inoinfo *)
malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
if (inp == NULL)
- return;
+ errx(EEXIT, "cannot increase directory list");
inpp = &inphead[inumber % numdirs];
inp->i_nexthash = *inpp;
*inpp = inp;
- if (inumber == ROOTINO)
- inp->i_parent = ROOTINO;
- else
- inp->i_parent = (ino_t)0;
+ inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = dp->di_size;
@@ -465,7 +473,7 @@ clri(idesc, type, flag)
n_files--;
(void)ckinode(dp, idesc);
clearinode(dp);
- statemap[idesc->id_number] = USTATE;
+ inoinfo(idesc->id_number)->ino_state = USTATE;
inodirty();
}
}
@@ -476,8 +484,10 @@ findname(idesc)
{
register struct direct *dirp = idesc->id_dirp;
- if (dirp->d_ino != idesc->id_parent)
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
return (KEEPON);
+ }
memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
return (STOP|FOUND);
}
@@ -498,6 +508,20 @@ findino(idesc)
return (KEEPON);
}
+int
+clearentry(idesc)
+ struct inodesc *idesc;
+{
+ register struct direct *dirp = idesc->id_dirp;
+
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
+ return (KEEPON);
+ }
+ dirp->d_ino = 0;
+ return (STOP|FOUND|ALTERED);
+}
+
void
pinode(ino)
ino_t ino;
@@ -534,14 +558,14 @@ blkerror(ino, type, blk)
pfatal("%ld %s I=%lu", blk, type, ino);
printf("\n");
- switch (statemap[ino]) {
+ switch (inoinfo(ino)->ino_state) {
case FSTATE:
- statemap[ino] = FCLEAR;
+ inoinfo(ino)->ino_state = FCLEAR;
return;
case DSTATE:
- statemap[ino] = DCLEAR;
+ inoinfo(ino)->ino_state = DCLEAR;
return;
case FCLEAR:
@@ -549,7 +573,7 @@ blkerror(ino, type, blk)
return;
default:
- errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]);
+ errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state);
/* NOTREACHED */
}
}
@@ -569,10 +593,10 @@ allocino(request, type)
if (request == 0)
request = ROOTINO;
- else if (statemap[request] != USTATE)
+ else if (inoinfo(request)->ino_state != USTATE)
return (0);
for (ino = request; ino < maxino; ino++)
- if (statemap[ino] == USTATE)
+ if (inoinfo(ino)->ino_state == USTATE)
break;
if (ino == maxino)
return (0);
@@ -584,12 +608,12 @@ allocino(request, type)
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
- statemap[ino] = DSTATE;
+ inoinfo(ino)->ino_state = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
- statemap[ino] = FSTATE;
+ inoinfo(ino)->ino_state = FSTATE;
break;
default:
return (0);
@@ -598,11 +622,11 @@ allocino(request, type)
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
return (0);
}
- dp->di_flags = 0;
dp->di_mode = type;
+ dp->di_flags = 0;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_size = sblock.fs_fsize;
@@ -610,7 +634,7 @@ allocino(request, type)
n_files++;
inodirty();
if (newinofmt)
- typemap[ino] = IFTODT(type);
+ inoinfo(ino)->ino_type = IFTODT(type);
return (ino);
}
@@ -632,6 +656,6 @@ freeino(ino)
(void)ckinode(dp, &idesc);
clearinode(dp);
inodirty();
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
n_files--;
}
diff --git a/sbin/fsck/main.c b/sbin/fsck/main.c
index 317015b..681ee6dc 100644
--- a/sbin/fsck/main.c
+++ b/sbin/fsck/main.c
@@ -38,11 +38,7 @@ static const char copyright[] =
#endif /* not lint */
#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
-#endif
-static const char rcsid[] =
- "$Id: main.c,v 1.14 1998/06/15 07:07:16 charnier Exp $";
+static const char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif /* not lint */
#include <sys/param.h>
@@ -56,11 +52,10 @@ static const char rcsid[] =
#include <err.h>
#include <fstab.h>
+#include <string.h>
#include "fsck.h"
-int returntosingle;
-
static int argtoi __P((int flag, char *req, char *str, int base));
static int docheck __P((struct fstab *fsp));
static int checkfilesys __P((char *filesys, char *mntpt, long auxdata,
@@ -74,12 +69,8 @@ main(argc, argv)
{
int ch;
int ret, maxrun = 0;
- struct rlimit rlim;
+ struct rlimit rlimit;
- if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
- rlim.rlim_cur = rlim.rlim_max;
- (void) setrlimit(RLIMIT_DATA, &rlim);
- }
sync();
while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != -1) {
switch (ch) {
@@ -137,9 +128,24 @@ main(argc, argv)
(void)signal(SIGINT, catch);
if (preen)
(void)signal(SIGQUIT, catchquit);
+ /*
+ * Push up our allowed memory limit so we can cope
+ * with huge filesystems.
+ */
+ if (getrlimit(RLIMIT_DATA, &rlimit) == 0) {
+ rlimit.rlim_cur = rlimit.rlim_max;
+ (void)setrlimit(RLIMIT_DATA, &rlimit);
+ }
if (argc) {
- while (argc-- > 0)
- (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
+ while (argc-- > 0) {
+ char *path = blockcheck(*argv);
+
+ if (path == NULL)
+ pfatal("Can't check %s\n", *argv);
+ else
+ (void)checkfilesys(path, 0, 0L, 0);
+ ++argv;
+ }
exit(0);
}
ret = checkfstab(preen, maxrun, docheck, checkfilesys);
@@ -203,16 +209,10 @@ checkfilesys(filesys, mntpt, auxdata, child)
case 0:
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
- return (0);
+ /* fall through */
case -1:
- pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree +
- sblock.fs_frag * sblock.fs_cstotal.cs_nbfree);
- printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
- sblock.fs_cstotal.cs_nffree, sblock.fs_cstotal.cs_nbfree,
- sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
return (0);
}
-
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
@@ -304,7 +304,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
muldup = (struct dups *)0;
inocleanup();
if (fsmodified) {
- (void)time(&sblock.fs_time);
+ sblock.fs_time = time(NULL);
sbdirty();
}
if (cvtlevel && sblk.b_dirty) {
@@ -329,12 +329,13 @@ checkfilesys(filesys, mntpt, auxdata, child)
resolved = 0;
}
ckfini(resolved);
- free(blockmap);
- free(statemap);
- free((char *)lncntp);
- if (!fsmodified)
- return (0);
- if (!preen)
+
+ for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
+ if (inostathead[cylno].il_stat != NULL)
+ free((char *)inostathead[cylno].il_stat);
+ free((char *)inostathead);
+ inostathead = NULL;
+ if (fsmodified && !preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
@@ -354,6 +355,8 @@ checkfilesys(filesys, mntpt, auxdata, child)
if (ret == 0)
return (0);
}
+ if (!fsmodified)
+ return (0);
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
diff --git a/sbin/fsck/pass1.c b/sbin/fsck/pass1.c
index 30c0e7d..1ce4471 100644
--- a/sbin/fsck/pass1.c
+++ b/sbin/fsck/pass1.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass1.c,v 1.11 1998/06/15 07:07:16 charnier Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -52,14 +49,17 @@ static const char rcsid[] =
static ufs_daddr_t badblk;
static ufs_daddr_t dupblk;
+static ino_t lastino; /* last inode in use */
static void checkinode __P((ino_t inumber, struct inodesc *));
void
pass1()
{
+ u_int8_t *cp;
ino_t inumber;
- int c, i, cgd;
+ int c, i, cgd, inosused;
+ struct inostat *info;
struct inodesc idesc;
/*
@@ -81,15 +81,84 @@ pass1()
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
- inumber = 0;
n_files = n_blks = 0;
- resetinodebuf();
for (c = 0; c < sblock.fs_ncg; c++) {
- for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
- if (inumber < ROOTINO)
+ inumber = c * sblock.fs_ipg;
+ setinodebuf(inumber);
+ inosused = sblock.fs_ipg;
+ /*
+ * If we are using soft updates, then we can trust the
+ * cylinder group inode allocation maps to tell us which
+ * inodes are allocated. We will scan the used inode map
+ * to find the inodes that are really in use, and then
+ * read only those inodes in from disk.
+ */
+ if (preen && usedsoftdep) {
+ getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
+ if (!cg_chkmagic(&cgrp))
+ pfatal("CG %d: BAD MAGIC NUMBER\n", c);
+ cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY];
+ for ( ; inosused > 0; inosused -= NBBY, cp--) {
+ if (*cp == 0)
+ continue;
+ for (i = 1 << (NBBY - 1); i > 0; i >>= 1) {
+ if (*cp & i)
+ break;
+ inosused--;
+ }
+ break;
+ }
+ if (inosused < 0)
+ inosused = 0;
+ }
+ /*
+ * Allocate inoinfo structures for the allocated inodes.
+ */
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ inostathead[c].il_stat = info;
+ /*
+ * Scan the allocated inodes.
+ */
+ for (i = 0; i < inosused; i++, inumber++) {
+ if (inumber < ROOTINO) {
+ (void)getnextinode(inumber);
continue;
+ }
checkinode(inumber, &idesc);
}
+ lastino += 1;
+ if (inosused < sblock.fs_ipg || inumber == lastino)
+ continue;
+ /*
+ * If we were not able to determine in advance which inodes
+ * were in use, then reduce the size of the inoinfo structure
+ * to the size necessary to describe the inodes that we
+ * really found.
+ */
+ inosused = lastino - (c * sblock.fs_ipg);
+ if (inosused < 0)
+ inosused = 0;
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = info;
}
freeinodebuf();
}
@@ -120,7 +189,7 @@ checkinode(inumber, idesc)
inodirty();
}
}
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
return;
}
lastino = inumber;
@@ -158,8 +227,7 @@ checkinode(inumber, idesc)
if (debug) {
symbuf[dp->di_size] = 0;
printf("convert symlink %lu(%s) of size %ld\n",
- (u_long)inumber, symbuf,
- (long)dp->di_size);
+ (u_long)inumber, symbuf, (long)dp->di_size);
}
dp = ginode(inumber);
memmove(dp->di_shortlink, symbuf, (long)dp->di_size);
@@ -170,8 +238,7 @@ checkinode(inumber, idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
- if (dp->di_size < sblock.fs_maxsymlinklen ||
- dp->di_blocks == 0) {
+ if (dp->di_size < sblock.fs_maxsymlinklen) {
ndb = howmany(dp->di_size, sizeof(ufs_daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
@@ -200,7 +267,7 @@ checkinode(inumber, idesc)
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
- lncntp[inumber] = dp->di_nlink;
+ inoinfo(inumber)->ino_linkcnt = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
@@ -217,13 +284,14 @@ checkinode(inumber, idesc)
}
if (mode == IFDIR) {
if (dp->di_size == 0)
- statemap[inumber] = DCLEAR;
+ inoinfo(inumber)->ino_state = DCLEAR;
else
- statemap[inumber] = DSTATE;
+ inoinfo(inumber)->ino_state = DSTATE;
cacheino(dp, inumber);
+ countdirs++;
} else
- statemap[inumber] = FSTATE;
- typemap[inumber] = IFTODT(mode);
+ inoinfo(inumber)->ino_state = FSTATE;
+ inoinfo(inumber)->ino_type = IFTODT(mode);
if (doinglevel2 &&
(dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) {
dp = ginode(inumber);
@@ -251,9 +319,9 @@ checkinode(inumber, idesc)
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
- statemap[inumber] = FCLEAR;
+ inoinfo(inumber)->ino_state = FCLEAR;
if (reply("CLEAR") == 1) {
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
diff --git a/sbin/fsck/pass1b.c b/sbin/fsck/pass1b.c
index 32a3be7..65ff49c 100644
--- a/sbin/fsck/pass1b.c
+++ b/sbin/fsck/pass1b.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1b.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -72,7 +69,7 @@ pass1b()
if (dp == NULL)
continue;
idesc.id_number = inumber;
- if (statemap[inumber] != USTATE &&
+ if (inoinfo(inumber)->ino_state != USTATE &&
(ckinode(dp, &idesc) & STOP))
return;
}
diff --git a/sbin/fsck/pass2.c b/sbin/fsck/pass2.c
index 4c24b23..7a61d1d 100644
--- a/sbin/fsck/pass2.c
+++ b/sbin/fsck/pass2.c
@@ -32,17 +32,15 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -64,7 +62,7 @@ pass2()
struct dinode dino;
char pathbuf[MAXPATHLEN + 1];
- switch (statemap[ROOTINO]) {
+ switch (inoinfo(ROOTINO)->ino_state) {
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
@@ -113,12 +111,13 @@ pass2()
break;
default:
- errx(EEXIT, "BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
+ errx(EEXIT, "BAD STATE %d FOR ROOT INODE",
+ inoinfo(ROOTINO)->ino_state);
}
- statemap[ROOTINO] = DFOUND;
+ inoinfo(ROOTINO)->ino_state = DFOUND;
if (newinofmt) {
- statemap[WINO] = FSTATE;
- typemap[WINO] = DT_WHT;
+ inoinfo(WINO)->ino_state = FSTATE;
+ inoinfo(WINO)->ino_type = DT_WHT;
}
/*
* Sort the directory list into disk block order.
@@ -181,9 +180,9 @@ pass2()
inp = *inpp;
if (inp->i_parent == 0 || inp->i_isize == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE)
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE)
+ inoinfo(inp->i_number)->ino_state = DFOUND;
if (inp->i_dotdot == inp->i_parent ||
inp->i_dotdot == (ino_t)-1)
continue;
@@ -193,15 +192,15 @@ pass2()
if (reply("FIX") == 0)
continue;
(void)makeentry(inp->i_number, inp->i_parent, "..");
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
- lncntp[inp->i_dotdot]++;
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
inp->i_dotdot = inp->i_parent;
(void)changeino(inp->i_number, "..", inp->i_parent);
}
@@ -228,7 +227,7 @@ pass2check(idesc)
* If converting, set directory entry type.
*/
if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
ret |= ALTERED;
}
/*
@@ -284,7 +283,7 @@ pass2check(idesc)
proto.d_reclen = entrysize;
memmove(dirp, &proto, (size_t)entrysize);
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + entrysize);
memset(dirp, 0, (size_t)n);
dirp->d_reclen = n;
@@ -319,7 +318,7 @@ chk1:
proto.d_reclen = dirp->d_reclen - n;
dirp->d_reclen = n;
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + n);
memset(dirp, 0, (size_t)proto.d_reclen);
dirp->d_reclen = proto.d_reclen;
@@ -356,7 +355,7 @@ chk1:
}
idesc->id_entryno++;
if (dirp->d_ino != 0)
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
return (ret|KEEPON);
chk2:
if (dirp->d_ino == 0)
@@ -394,7 +393,7 @@ chk2:
ret |= ALTERED;
} else {
again:
- switch (statemap[dirp->d_ino]) {
+ switch (inoinfo(dirp->d_ino)->ino_state) {
case USTATE:
if (idesc->id_entryno <= 2)
break;
@@ -406,7 +405,7 @@ again:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
- if (statemap[dirp->d_ino] == FCLEAR)
+ if (inoinfo(dirp->d_ino)->ino_state == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
@@ -418,14 +417,14 @@ again:
if ((n = reply("REMOVE")) == 1)
break;
dp = ginode(dirp->d_ino);
- statemap[dirp->d_ino] =
+ inoinfo(dirp->d_ino)->ino_state =
(dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
- lncntp[dirp->d_ino] = dp->di_nlink;
+ inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink;
goto again;
case DSTATE:
- if (statemap[idesc->id_number] == DFOUND)
- statemap[dirp->d_ino] = DFOUND;
+ if (inoinfo(idesc->id_number)->ino_state == DFOUND)
+ inoinfo(dirp->d_ino)->ino_state = DFOUND;
/* fall through */
case DFOUND:
@@ -439,10 +438,10 @@ again:
namebuf);
if (preen) {
printf(" (REMOVED)\n");
- n = 1;
- break;
+ n = 1;
+ break;
}
- else if ((n = reply("REMOVE")) == 1)
+ if ((n = reply("REMOVE")) == 1)
break;
}
if (idesc->id_entryno > 2)
@@ -450,19 +449,20 @@ again:
/* fall through */
case FSTATE:
- if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
+ if (newinofmt &&
+ dirp->d_type != inoinfo(dirp->d_ino)->ino_type) {
fileerror(idesc->id_number, dirp->d_ino,
"BAD TYPE VALUE");
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
if (reply("FIX") == 1)
ret |= ALTERED;
}
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
break;
default:
errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[dirp->d_ino], dirp->d_ino);
+ inoinfo(dirp->d_ino)->ino_state, dirp->d_ino);
}
}
if (n == 0)
diff --git a/sbin/fsck/pass3.c b/sbin/fsck/pass3.c
index 6524a11..6320755 100644
--- a/sbin/fsck/pass3.c
+++ b/sbin/fsck/pass3.c
@@ -32,45 +32,84 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass3.c 8.2 (Berkeley) 4/27/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+
+#include <string.h>
#include "fsck.h"
void
pass3()
{
- register struct inoinfo **inpp, *inp;
+ struct inoinfo *inp;
+ int loopcnt, inpindex, state;
ino_t orphan;
- int loopcnt;
+ struct inodesc idesc;
+ char namebuf[MAXNAMLEN+1];
- for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
- inp = *inpp;
+ for (inpindex = inplast - 1; inpindex >= 0; inpindex--) {
+ inp = inpsort[inpindex];
+ state = inoinfo(inp->i_number)->ino_state;
if (inp->i_number == ROOTINO ||
- !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
+ (inp->i_parent != 0 && state != DSTATE))
+ continue;
+ if (state == DCLEAR)
continue;
- if (statemap[inp->i_number] == DCLEAR)
+ /*
+ * If we are running with soft updates and we come
+ * across unreferenced directories, we just leave
+ * them in DSTATE which will cause them to be pitched
+ * in pass 4.
+ */
+ if (preen && resolved && usedsoftdep && state == DSTATE) {
+ if (inp->i_dotdot >= ROOTINO)
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
continue;
+ }
for (loopcnt = 0; ; loopcnt++) {
orphan = inp->i_number;
if (inp->i_parent == 0 ||
- statemap[inp->i_parent] != DSTATE ||
- loopcnt > numdirs)
+ inoinfo(inp->i_parent)->ino_state != DSTATE ||
+ loopcnt > countdirs)
break;
inp = getinoinfo(inp->i_parent);
}
- (void)linkup(orphan, inp->i_dotdot);
- inp->i_parent = inp->i_dotdot = lfdir;
- lncntp[lfdir]--;
- statemap[orphan] = DFOUND;
+ if (loopcnt <= countdirs) {
+ if (linkup(orphan, inp->i_dotdot, NULL)) {
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
+ propagate();
+ continue;
+ }
+ pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu", orphan);
+ if (reply("RECONNECT") == 0)
+ continue;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = DATA;
+ idesc.id_number = inp->i_parent;
+ idesc.id_parent = orphan;
+ idesc.id_func = findname;
+ idesc.id_name = namebuf;
+ if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0)
+ pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
+ if (linkup(orphan, inp->i_parent, namebuf)) {
+ idesc.id_func = clearentry;
+ if (ckinode(ginode(inp->i_parent), &idesc) & FOUND)
+ inoinfo(orphan)->ino_linkcnt++;
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
propagate();
}
}
diff --git a/sbin/fsck/pass4.c b/sbin/fsck/pass4.c
index b2f1fe9..48c5090 100644
--- a/sbin/fsck/pass4.c
+++ b/sbin/fsck/pass4.c
@@ -32,16 +32,14 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -55,22 +53,27 @@ pass4()
register struct zlncnt *zlnp;
struct dinode *dp;
struct inodesc idesc;
- int n;
+ int i, n, cg;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass4check;
- for (inumber = ROOTINO; inumber <= lastino; inumber++) {
- idesc.id_number = inumber;
- switch (statemap[inumber]) {
+ for (cg = 0; cg < sblock.fs_ncg; cg++) {
+ inumber = cg * sblock.fs_ipg;
+ for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) {
+ if (inumber < ROOTINO)
+ continue;
+ idesc.id_number = inumber;
+ switch (inoinfo(inumber)->ino_state) {
- case FSTATE:
- case DFOUND:
- n = lncntp[inumber];
- if (n)
- adjust(&idesc, (short)n);
- else {
- for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
+ case FSTATE:
+ case DFOUND:
+ n = inoinfo(inumber)->ino_linkcnt;
+ if (n) {
+ adjust(&idesc, (short)n);
+ break;
+ }
+ for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
if (zlnp->zlncnt == inumber) {
zlnp->zlncnt = zlnhead->zlncnt;
zlnp = zlnhead;
@@ -79,30 +82,31 @@ pass4()
clri(&idesc, "UNREF", 1);
break;
}
- }
- break;
+ }
+ break;
- case DSTATE:
- clri(&idesc, "UNREF", 1);
- break;
+ case DSTATE:
+ clri(&idesc, "UNREF", 1);
+ break;
- case DCLEAR:
- dp = ginode(inumber);
- if (dp->di_size == 0) {
- clri(&idesc, "ZERO LENGTH", 1);
+ case DCLEAR:
+ dp = ginode(inumber);
+ if (dp->di_size == 0) {
+ clri(&idesc, "ZERO LENGTH", 1);
+ break;
+ }
+ /* fall through */
+ case FCLEAR:
+ clri(&idesc, "BAD/DUP", 1);
break;
- }
- /* fall through */
- case FCLEAR:
- clri(&idesc, "BAD/DUP", 1);
- break;
- case USTATE:
- break;
+ case USTATE:
+ break;
- default:
- errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[inumber], inumber);
+ default:
+ errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
+ inoinfo(inumber)->ino_state, inumber);
+ }
}
}
}
diff --git a/sbin/fsck/pass5.c b/sbin/fsck/pass5.c
index f3994f8..d492a18 100644
--- a/sbin/fsck/pass5.c
+++ b/sbin/fsck/pass5.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass5.c,v 1.13 1998/08/04 09:19:03 phk Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -52,7 +49,7 @@ static const char rcsid[] =
void
pass5()
{
- int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
+ int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
@@ -66,7 +63,7 @@ pass5()
register struct cg *newcg = (struct cg *)buf;
struct ocg *ocg = (struct ocg *)buf;
- statemap[WINO] = USTATE;
+ inoinfo(WINO)->ino_state = USTATE;
memset(newcg, 0, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
if (cvtlevel >= 3) {
@@ -207,8 +204,8 @@ pass5()
if (fs->fs_postblformat == FS_42POSTBLFMT)
ocg->cg_magic = CG_MAGIC;
j = fs->fs_ipg * c;
- for (i = 0; i < fs->fs_ipg; j++, i++) {
- switch (statemap[j]) {
+ for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
+ switch (inoinfo(j)->ino_state) {
case USTATE:
break;
@@ -229,7 +226,7 @@ pass5()
if (j < ROOTINO)
break;
errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
- statemap[j], j);
+ inoinfo(j)->ino_state, j);
}
}
if (c == 0)
@@ -325,7 +322,7 @@ pass5()
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE\n",
- c * fs->fs_ipg + i * 8 + k);
+ c * fs->fs_ipg + i * NBBY + k);
}
}
for (i = 0; i < blkmapsize; i++) {
@@ -338,7 +335,7 @@ pass5()
if (cg_blksfree(newcg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE\n",
- c * fs->fs_fpg + i * 8 + k);
+ c * fs->fs_fpg + i * NBBY + k);
}
}
}
@@ -355,24 +352,7 @@ pass5()
&& dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
fs->fs_ronly = 0;
+ fs->fs_fmod = 0;
sbdirty();
}
- if (fs->fs_fmod != 0) {
- pwarn("MODIFIED FLAG SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_fmod = 0;
- sbdirty();
- }
- }
- if (fs->fs_clean == 0) {
- pwarn("CLEAN FLAG NOT SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_clean = 1;
- sbdirty();
- }
- }
}
diff --git a/sbin/fsck/preen.c b/sbin/fsck/preen.c
index 9705aee..ba0140b 100644
--- a/sbin/fsck/preen.c
+++ b/sbin/fsck/preen.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
@@ -46,7 +42,7 @@ static const char rcsid[] =
#include <ufs/ufs/dinode.h>
#include <ctype.h>
-#include <err.h>
+#include <errno.h>
#include <fstab.h>
#include <string.h>
@@ -93,7 +89,8 @@ checkfstab(preen, maxrun, docheck, chkit)
sumstatus = 0;
for (passno = 1; passno <= 2; passno++) {
if (setfsent() == 0) {
- warnx("can't open checklist file: %s", _PATH_FSTAB);
+ fprintf(stderr, "Can't open checklist file: %s\n",
+ _PATH_FSTAB);
return (8);
}
while ((fsp = getfsent()) != 0) {
@@ -222,11 +219,15 @@ finddisk(name)
dk->name[len] == 0)
return (dk);
}
- if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
- errx(8, "out of memory");
+ if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
dk = *dkp;
- if ((dk->name = malloc(len + 1)) == NULL)
- errx(8, "out of memory");
+ if ((dk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strncpy(dk->name, name, len);
dk->name[len] = '\0';
dk->part = NULL;
@@ -249,14 +250,20 @@ addpart(name, fsname, auxdata)
printf("%s in fstab more than once!\n", name);
return;
}
- if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
- errx(8, "out of memory");
+ if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
pt = *ppt;
- if ((pt->name = malloc(strlen(name) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->name, name);
- if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->fsname, fsname);
pt->next = NULL;
pt->auxdata = auxdata;
@@ -271,7 +278,7 @@ startdisk(dk, checkit)
dk->pid = fork();
if (dk->pid < 0) {
- warn("fork");
+ perror("fork");
return (8);
}
if (dk->pid == 0)
@@ -287,19 +294,17 @@ blockcheck(origname)
struct stat stslash, stblock, stchar;
char *newname, *raw;
struct fstab *fsinfo;
- int retried = 0, l;
+ int retried = 0, len;
hotroot = 0;
if (stat("/", &stslash) < 0) {
- warn("/");
- printf("Can't stat root\n");
+ printf("Can't stat /: %s\n", strerror(errno));
return (origname);
}
newname = origname;
retry:
if (stat(newname, &stblock) < 0) {
- warn("%s", newname);
- printf("Can't stat %s\n", newname);
+ printf("Can't stat %s: %s\n", newname, strerror(errno));
return (origname);
}
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
@@ -307,8 +312,7 @@ retry:
hotroot++;
raw = rawname(newname);
if (stat(raw, &stchar) < 0) {
- warn("%s", raw);
- printf("Can't stat %s\n", raw);
+ printf("Can't stat %s: %s\n", raw, strerror(errno));
return (origname);
}
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
@@ -318,15 +322,15 @@ retry:
return (origname);
}
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
- newname = unrawname(origname);
+ newname = unrawname(newname);
retried++;
goto retry;
} else if ((stblock.st_mode & S_IFMT) == S_IFDIR && !retried) {
- l = strlen(origname) - 1;
- if (l > 0 && origname[l] == '/')
+ len = strlen(origname) - 1;
+ if (len > 0 && origname[len] == '/')
/* remove trailing slash */
- origname[l] = '\0';
- if(!(fsinfo=getfsfile(origname))) {
+ origname[len] = '\0';
+ if ((fsinfo = getfsfile(origname)) == NULL) {
printf("Can't resolve %s to character special device",
origname);
return (0);
diff --git a/sbin/fsck/setup.c b/sbin/fsck/setup.c
index 25dab92..5a842f4 100644
--- a/sbin/fsck/setup.c
+++ b/sbin/fsck/setup.c
@@ -32,16 +32,13 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
-#endif
-static const char rcsid[] =
- "$Id: setup.c,v 1.11 1998/06/15 07:07:21 charnier Exp $";
#endif /* not lint */
#define DKTYPENAMES
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
@@ -82,7 +79,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
- skipclean = preen;
+ skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
@@ -114,8 +111,7 @@ setup(dev)
asblk.b_un.b_buf = malloc(SBSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
- lp = getdisklabel((char *)NULL, fsreadfd);
- if (lp)
+ if ((lp = getdisklabel(NULL, fsreadfd)))
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
@@ -147,6 +143,10 @@ setup(dev)
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
bflag = 0;
}
+ if (skipclean && sblock.fs_clean) {
+ pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
+ return (-1);
+ }
maxfsblock = sblock.fs_size;
maxino = sblock.fs_ncg * sblock.fs_ipg;
/*
@@ -265,12 +265,6 @@ setup(dev)
}
}
/*
- * If we survive the above basic checks and are preening,
- * quit here unless forced.
- */
- if (skipclean && sblock.fs_clean && !fflag)
- return (-1);
- /*
* allocate and initialize the necessary maps
*/
bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short));
@@ -280,22 +274,11 @@ setup(dev)
(unsigned)bmapsize);
goto badsb;
}
- statemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (statemap == NULL) {
- printf("cannot alloc %u bytes for statemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- typemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (typemap == NULL) {
- printf("cannot alloc %u bytes for typemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
- if (lncntp == NULL) {
- printf("cannot alloc %u bytes for lncntp\n",
- (unsigned)(maxino + 1) * sizeof(short));
+ inostathead = calloc((unsigned)(sblock.fs_ncg),
+ sizeof(struct inostatlist));
+ if (inostathead == NULL) {
+ printf("cannot alloc %u bytes for inostathead\n",
+ (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg)));
goto badsb;
}
numdirs = sblock.fs_cstotal.cs_ndir;
@@ -474,9 +457,11 @@ calcsb(dev, devfd, fs)
fstypenames[pp->p_fstype] : "unknown");
return (0);
}
- if (pp->p_fsize == 0 || pp->p_frag == 0) {
- pfatal("%s: LABELED AS A %s FILE SYSTEM, BUT BLOCK SIZE IS 0\n",
- dev, fstypenames[pp->p_fstype]);
+ if (pp->p_fsize == 0 || pp->p_frag == 0 ||
+ pp->p_cpg == 0 || pp->p_size == 0) {
+ pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n",
+ dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype],
+ pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size);
return (0);
}
memset(fs, 0, sizeof(struct fs));
diff --git a/sbin/fsck/utilities.c b/sbin/fsck/utilities.c
index 0d82d6e..5ea02b6 100644
--- a/sbin/fsck/utilities.c
+++ b/sbin/fsck/utilities.c
@@ -32,20 +32,16 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
-#include <ctype.h>
#include <err.h>
#include <string.h>
@@ -116,6 +112,26 @@ reply(question)
}
/*
+ * Look up state information for an inode.
+ */
+struct inostat *
+inoinfo(inum)
+ ino_t inum;
+{
+ static struct inostat unallocated = { USTATE, 0, 0 };
+ struct inostatlist *ilp;
+ int iloff;
+
+ if (inum > maxino)
+ errx(EEXIT, "inoinfo: inumber %d out of range", inum);
+ ilp = &inostathead[inum / sblock.fs_ipg];
+ iloff = inum % sblock.fs_ipg;
+ if (iloff >= ilp->il_numalloced)
+ return (&unallocated);
+ return (&ilp->il_stat[iloff]);
+}
+
+/*
* Malloc buffers and set up cache.
*/
void
@@ -270,16 +286,23 @@ ckfini(markclean)
free((char *)bp);
}
if (bufhead.b_size != cnt)
- errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt);
+ errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt);
pbp = pdirbp = (struct bufarea *)0;
- if (markclean && sblock.fs_clean == 0) {
- sblock.fs_clean = 1;
+ if (sblock.fs_clean != markclean) {
+ sblock.fs_clean = markclean;
sbdirty();
ofsmodified = fsmodified;
flush(fswritefd, &sblk);
fsmodified = ofsmodified;
- if (!preen)
- printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
+ if (!preen) {
+ printf("\n***** FILE SYSTEM MARKED %s *****\n",
+ markclean ? "CLEAN" : "DIRTY");
+ if (!markclean)
+ rerun = 1;
+ }
+ } else if (!preen && !markclean) {
+ printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
+ rerun = 1;
}
if (debug)
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
@@ -324,6 +347,8 @@ bread(fd, buf, blk, size)
}
}
printf("\n");
+ if (errs)
+ resolved = 0;
return (errs);
}
@@ -348,6 +373,7 @@ bwrite(fd, buf, blk, size)
fsmodified = 1;
return;
}
+ resolved = 0;
rwerror("WRITE", blk);
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
@@ -438,7 +464,8 @@ getpathname(namebuf, curdir, ino)
return;
}
if (busy ||
- (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
+ (inoinfo(curdir)->ino_state != DSTATE &&
+ inoinfo(curdir)->ino_state != DFOUND)) {
(void)strcpy(namebuf, "?");
return;
}
@@ -497,6 +524,7 @@ void
catchquit(sig)
int sig;
{
+
printf("returning to single-user after filesystem check\n");
returntosingle = 1;
(void)signal(SIGQUIT, SIG_DFL);
@@ -589,14 +617,16 @@ pfatal(fmt, va_alist)
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
- "\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
+ "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n");
return;
}
+ if (cdevname == NULL)
+ cdevname = "fsck";
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
- cdevname, usedsoftdep ? " SOFTDEP " : " ");
+ cdevname, usedsoftdep ? " SOFT UPDATE " : " ");
ckfini(0);
exit(EEXIT);
}
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 91b507f..ceb66e6 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: dir.c,v 1.11 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -88,9 +85,9 @@ propagate()
inp = *inpp;
if (inp->i_parent == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE) {
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE) {
+ inoinfo(inp->i_number)->ino_state = DFOUND;
change++;
}
}
@@ -123,6 +120,8 @@ dirscan(idesc)
idesc->id_loc = 0;
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
+ if (dsize > sizeof(dbuf))
+ dsize = sizeof(dbuf);
memmove(dbuf, dp, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
@@ -235,8 +234,7 @@ dircheck(idesc, dp)
int spaceleft;
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
- if (dp->d_ino >= maxino ||
- dp->d_reclen == 0 ||
+ if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
@@ -306,13 +304,40 @@ adjust(idesc, lcnt)
register struct inodesc *idesc;
int lcnt;
{
- register struct dinode *dp;
+ struct dinode *dp;
+ int saveresolved;
dp = ginode(idesc->id_number);
if (dp->di_nlink == lcnt) {
- if (linkup(idesc->id_number, (ino_t)0) == 0)
- clri(idesc, "UNREF", 0);
- } else {
+ /*
+ * If we have not hit any unresolved problems, are running
+ * in preen mode, and are on a filesystem using soft updates,
+ * then just toss any partially allocated files.
+ */
+ if (resolved && preen && usedsoftdep) {
+ clri(idesc, "UNREF", 1);
+ return;
+ } else {
+ /*
+ * The filesystem can be marked clean even if
+ * a file is not linked up, but is cleared.
+ * Hence, resolved should not be cleared when
+ * linkup is answered no, but clri is answered yes.
+ */
+ saveresolved = resolved;
+ if (linkup(idesc->id_number, (ino_t)0, NULL) == 0) {
+ resolved = saveresolved;
+ clri(idesc, "UNREF", 0);
+ return;
+ }
+ /*
+ * Account for the new reference created by linkup().
+ */
+ dp = ginode(idesc->id_number);
+ lcnt--;
+ }
+ }
+ if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
@@ -355,7 +380,7 @@ mkentry(idesc)
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
dirp->d_reclen = newent.d_reclen;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
dirp->d_namlen = newent.d_namlen;
@@ -388,16 +413,17 @@ chgino(idesc)
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
return (ALTERED|STOP);
}
int
-linkup(orphan, parentdir)
+linkup(orphan, parentdir, name)
ino_t orphan;
ino_t parentdir;
+ char *name;
{
register struct dinode *dp;
int lostdir;
@@ -410,7 +436,7 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
- if ((preen || usedsoftdep) && dp->di_size == 0)
+ if (preen && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
@@ -431,6 +457,7 @@ linkup(orphan, parentdir)
lfdir = allocdir(ROOTINO, (ino_t)0, lfmode);
if (lfdir != 0) {
if (makeentry(ROOTINO, lfdir, lfname) != 0) {
+ numdirs++;
if (preen)
printf(" (CREATED)\n");
} else {
@@ -466,21 +493,21 @@ linkup(orphan, parentdir)
idesc.id_type = ADDR;
idesc.id_func = pass4check;
idesc.id_number = oldlfdir;
- adjust(&idesc, lncntp[oldlfdir] + 1);
- lncntp[oldlfdir] = 0;
+ adjust(&idesc, inoinfo(oldlfdir)->ino_linkcnt + 1);
+ inoinfo(oldlfdir)->ino_linkcnt = 0;
dp = ginode(lfdir);
}
- if (statemap[lfdir] != DFOUND) {
+ if (inoinfo(lfdir)->ino_state != DFOUND) {
pfatal("SORRY. NO lost+found DIRECTORY\n\n");
return (0);
}
(void)lftempname(tempname, orphan);
- if (makeentry(lfdir, orphan, tempname) == 0) {
+ if (makeentry(lfdir, orphan, (name ? name : tempname)) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
printf("\n\n");
return (0);
}
- lncntp[orphan]--;
+ inoinfo(orphan)->ino_linkcnt--;
if (lostdir) {
if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
parentdir != (ino_t)-1)
@@ -488,19 +515,11 @@ linkup(orphan, parentdir)
dp = ginode(lfdir);
dp->di_nlink++;
inodirty();
- lncntp[lfdir]++;
+ inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", orphan);
if (parentdir != (ino_t)-1) {
printf("PARENT WAS I=%lu\n", (u_long)parentdir);
- /*
- * The parent directory, because of the ordering
- * guarantees, has had the link count incremented
- * for the child, but no entry was made. This
- * fixes the parent link count so that fsck does
- * not need to be rerun.
- */
- lncntp[parentdir]++;
-
+ inoinfo(parentdir)->ino_linkcnt++;
}
if (preen == 0)
printf("\n");
@@ -658,19 +677,20 @@ allocdir(parent, request, mode)
dp->di_nlink = 2;
inodirty();
if (ino == ROOTINO) {
- lncntp[ino] = dp->di_nlink;
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
cacheino(dp, ino);
return(ino);
}
- if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
+ if (inoinfo(parent)->ino_state != DSTATE &&
+ inoinfo(parent)->ino_state != DFOUND) {
freeino(ino);
return (0);
}
cacheino(dp, ino);
- statemap[ino] = statemap[parent];
- if (statemap[ino] == DSTATE) {
- lncntp[ino] = dp->di_nlink;
- lncntp[parent]++;
+ inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
+ if (inoinfo(ino)->ino_state == DSTATE) {
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
+ inoinfo(parent)->ino_linkcnt++;
}
dp = ginode(parent);
dp->di_nlink++;
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 4e0271d..81b2292 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -42,16 +42,35 @@
#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */
-#ifndef BUFSIZ
-#define BUFSIZ 1024
-#endif
-
+/*
+ * Each inode on the filesystem is described by the following structure.
+ * The linkcnt is initially set to the value in the inode. Each time it
+ * is found during the descent in passes 2, 3, and 4 the count is
+ * decremented. Any inodes whose count is non-zero after pass 4 needs to
+ * have its link count adjusted by the value remaining in ino_linkcnt.
+ */
+struct inostat {
+ char ino_state; /* state of inode, see below */
+ char ino_type; /* type of inode */
+ short ino_linkcnt; /* number of links not found */
+};
+/*
+ * Inode states.
+ */
#define USTATE 01 /* inode not allocated */
#define FSTATE 02 /* inode is file */
#define DSTATE 03 /* inode is directory */
#define DFOUND 04 /* directory found during descent */
#define DCLEAR 05 /* directory is to be cleared */
#define FCLEAR 06 /* file is to be cleared */
+/*
+ * Inode state information is contained on per cylinder group lists
+ * which are described by the following structure.
+ */
+struct inostatlist {
+ long il_numalloced; /* number of inodes allocated in this cg */
+ struct inostat *il_stat;/* inostat info for this cylinder group */
+} *inostathead;
/*
* buffer cache structure.
@@ -163,11 +182,12 @@ struct inoinfo {
ufs_daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, listmax, inplast;
+long countdirs; /* number of directories we actually found */
char *cdevname; /* name of device being checked */
long dev_bsize; /* computed value of DEV_BSIZE */
long secsize; /* actual disk sector size */
-char fflag; /* force fs check (ignore clean flag) */
+char fflag; /* force check, ignore clean flag */
char nflag; /* assume a no response */
char yflag; /* assume a yes response */
int bflag; /* location of alternate super block */
@@ -177,23 +197,19 @@ int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
-char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
+char rerun; /* rerun fsck. Only used in non-preen mode */
+int returntosingle; /* 1 => return to single user mode on exit */
+char resolved; /* cleared if unresolved changes => not clean */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */
int fsmodified; /* 1 => write done to file system */
int fsreadfd; /* file descriptor for reading file system */
int fswritefd; /* file descriptor for writing file system */
-int returntosingle; /* return to single user mode */
-int rerun; /* rerun fsck. Only used in non-preen mode */
ufs_daddr_t maxfsblock; /* number of blocks in the file system */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in file system */
-ino_t lastino; /* last inode in use */
-char *statemap; /* ptr to inode state table */
-u_char *typemap; /* ptr to inode type table */
-short *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
char *lfname; /* lost & found directory name */
@@ -219,6 +235,7 @@ struct dinode zino;
struct fstab;
+
void adjust __P((struct inodesc *, int lcnt));
ufs_daddr_t allocblk __P((long frags));
ino_t allocdir __P((ino_t parent, ino_t request, int mode));
@@ -239,6 +256,7 @@ int chkrange __P((ufs_daddr_t blk, int cnt));
void ckfini __P((int markclean));
int ckinode __P((struct dinode *dp, struct inodesc *));
void clri __P((struct inodesc *, char *type, int flag));
+int clearentry __P((struct inodesc *));
void direrror __P((ino_t ino, char *errmesg));
int dirscan __P((struct inodesc *));
int dofix __P((struct inodesc *, char *msg));
@@ -262,7 +280,8 @@ void getpathname __P((char *namebuf, ino_t curdir, ino_t ino));
struct dinode *ginode __P((ino_t inumber));
void inocleanup __P((void));
void inodirty __P((void));
-int linkup __P((ino_t orphan, ino_t parentdir));
+struct inostat *inoinfo __P((ino_t inum));
+int linkup __P((ino_t orphan, ino_t parentdir, char *name));
int makeentry __P((ino_t parent, ino_t ino, char *name));
void panic __P((const char *fmt, ...));
void pass1 __P((void));
@@ -278,6 +297,6 @@ void pinode __P((ino_t ino));
void propagate __P((void));
void pwarn __P((const char *fmt, ...));
int reply __P((char *question));
-void resetinodebuf __P((void));
+void setinodebuf __P((ino_t));
int setup __P((char *dev));
void voidquit __P((int));
diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8
index 51d1679..20c867f 100644
--- a/sbin/fsck_ffs/fsck_ffs.8
+++ b/sbin/fsck_ffs/fsck_ffs.8
@@ -1,3 +1,4 @@
+.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -10,7 +11,7 @@
.\" 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:
+.\" 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
@@ -30,9 +31,8 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
-.\" $Id: fsck.8,v 1.10 1997/03/12 16:35:26 bde Exp $
.\"
-.Dd May 9, 1995
+.Dd November 15, 1996
.Dt FSCK 8
.Os BSD 4
.Sh NAME
@@ -43,24 +43,25 @@
.Fl p
.Op Fl f
.Op Fl m Ar mode
+.Op Ar filesystem
+.Ar ...
.Nm fsck
+.Op Fl ny
.Op Fl b Ar block#
.Op Fl c Ar level
.Op Fl l Ar maxparallel
-.Op Fl y
-.Op Fl n
.Op Fl m Ar mode
.Op Ar filesystem
.Ar ...
.Sh DESCRIPTION
The first form of
-.Nm
+.Nm fsck
preens a standard set of filesystems or the specified filesystems.
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
Here
-.Nm
+.Nm fsck
reads the table
.Pa /etc/fstab
to determine which filesystems to check.
@@ -73,22 +74,18 @@ running one process per disk drive.
The disk drive containing each filesystem is inferred from the longest prefix
of the device name that ends in a digit; the remaining characters are assumed
to be the partition designator.
-.Pp
-The clean flag of each filesystem's superblock is examined and only those filesystems that
-are not marked clean are checked.
+In preening mode,
+filesystems that are marked clean are skipped.
Filesystems are marked clean when they are unmounted,
when they have been mounted read-only, or when
-.Nm
+.Nm fsck
runs on them successfully.
-If the
-.Fl f
-option is specified, the filesystems
-will be checked regardless of the state of their clean flag.
.Pp
The kernel takes care that only a restricted class of innocuous filesystem
inconsistencies can happen unless hardware or software failures intervene.
These are limited to the following:
-.Bl -item -compact
+.Pp
+.Bl -item -compact -offset indent
.It
Unreferenced inodes
.It
@@ -102,7 +99,7 @@ Counts in the super-block wrong
.El
.Pp
These are the only inconsistencies that
-.Nm
+.Nm fsck
with the
.Fl p
option will correct; if it encounters other inconsistencies, it exits
@@ -110,7 +107,7 @@ with an abnormal return status and an automatic reboot will then fail.
For each corrected inconsistency one or more lines will be printed
identifying the filesystem on which the correction will take place,
and the nature of the correction. After successfully correcting a filesystem,
-.Nm
+.Nm fsck
will print the number of files on that filesystem,
the number of used and free blocks,
and the percentage of fragmentation.
@@ -118,7 +115,7 @@ and the percentage of fragmentation.
If sent a
.Dv QUIT
signal,
-.Nm
+.Nm fsck
will finish the filesystem checks, then exit with an abnormal
return status that causes an automatic reboot to fail.
This is useful when you want to finish the filesystem checks during an
@@ -128,7 +125,7 @@ but do not want the machine to come up multiuser after the checks complete.
Without the
.Fl p
option,
-.Nm
+.Nm fsck
audits and interactively repairs inconsistent conditions for filesystems.
If the filesystem is inconsistent the operator is prompted for concurrence
before each correction is attempted.
@@ -144,7 +141,7 @@ is to wait for the operator to respond
or
.Li no .
If the operator does not have write permission on the filesystem
-.Nm
+.Nm fsck
will default to a
.Fl n
action.
@@ -158,38 +155,12 @@ and
combined.
.Pp
The following flags are interpreted by
-.Nm Ns .
+.Nm fsck .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the filesystem. Block 32 is usually
an alternate super block.
-.It Fl l
-Limit the number of parallel checks to the number specified in the following
-argument.
-By default, the limit is the number of disks, running one process per disk.
-If a smaller limit is given, the disks are checked round-robin, one filesystem
-at a time.
-.It Fl m
-Use the mode specified in octal immediately after the flag as the
-permission bits to use when creating the
-.Pa lost+found
-directory rather than the default 1777.
-In particular, systems that do not wish to have lost files accessible
-by all users on the system should use a more restrictive
-set of permissions such as 700.
-.It Fl y
-Assume a yes response to all questions asked by
-.Nm Ns ;
-this should be used with great caution as this is a free license
-to continue after essentially unlimited trouble has been encountered.
-.It Fl n
-Assume a no response to all questions asked by
-.Nm
-except for
-.Ql CONTINUE? ,
-which is assumed to be affirmative;
-do not open the filesystem for writing.
.It Fl c
Convert the filesystem to the specified level.
Note that the level of a filesystem can only be raised.
@@ -210,7 +181,7 @@ If maxcontig is equal to one, delete any existing segment maps.
.El
.Pp
In interactive mode,
-.Nm
+.Nm fsck
will list the conversion to be made
and ask whether the conversion should be done.
If a negative answer is given,
@@ -223,10 +194,44 @@ are being converted at once.
The format of a filesystem can be determined from the
first line of output from
.Xr dumpfs 8 .
+.It Fl f
+Force
+.Nm fsck
+to check
+.Sq clean
+filesystems when preening.
+.It Fl l
+Limit the number of parallel checks to the number specified in the following
+argument.
+By default, the limit is the number of disks, running one process per disk.
+If a smaller limit is given, the disks are checked round-robin, one filesystem
+at a time.
+.It Fl m
+Use the mode specified in octal immediately after the flag as the
+permission bits to use when creating the
+.Pa lost+found
+directory rather than the default 1777.
+In particular, systems that do not wish to have lost files accessible
+by all users on the system should use a more restrictive
+set of permissions such as 700.
+.It Fl n
+Assume a no response to all questions asked by
+.Nm fsck
+except for
+.Ql CONTINUE? ,
+which is assumed to be affirmative;
+do not open the filesystem for writing.
+.It Fl p
+Preen filesystems (see above).
+.It Fl y
+Assume a yes response to all questions asked by
+.Nm fsck ;
+this should be used with great caution as this is a free license
+to continue after essentially unlimited trouble has been encountered.
.El
.Pp
If no filesystems are given to
-.Nm
+.Nm fsck
then a default list of filesystems is read from
the file
.Pa /etc/fstab .
@@ -259,7 +264,7 @@ File pointing to unallocated inode.
.It
Inode number out of range.
.It
-Holes in directories.
+Directories with unallocated blocks (holes).
.It
Dot or dot-dot not the first two entries of a directory
or having the wrong inode number.
@@ -296,14 +301,13 @@ contains default list of filesystems to check.
.El
.Sh DIAGNOSTICS
The diagnostics produced by
-.Nm
+.Nm fsck
are fully enumerated and explained in Appendix A of
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
-.Xr fs 5 ,
.Xr fstab 5 ,
-.Xr fsdb 8 ,
+.Xr fs 5 ,
.Xr newfs 8 ,
.Xr reboot 8
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index b7e80cd..a54f2ce 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: inode.c,v 1.15 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -62,7 +58,8 @@ ckinode(dp, idesc)
register struct inodesc *idesc;
{
ufs_daddr_t *ap;
- long ret, n, ndb, offset;
+ int ret;
+ long n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
mode_t mode;
@@ -74,7 +71,7 @@ ckinode(dp, idesc)
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
- (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0)))
+ dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
@@ -239,8 +236,16 @@ chkrange(blk, cnt)
{
register int c;
- if (blk < 0 || blk >= maxfsblock || cnt < 0 || cnt > maxfsblock - blk)
+ if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
+ cnt - 1 > maxfsblock - blk)
return (1);
+ if (cnt > sblock.fs_frag ||
+ fragnum(&sblock, blk) + cnt > sblock.fs_frag) {
+ if (debug)
+ printf("bad size: blk %ld, offset %ld, size %ld\n",
+ blk, fragnum(&sblock, blk), cnt);
+ return (1);
+ }
c = dtog(&sblock, blk);
if (blk < cgdmin(&sblock, c)) {
if ((blk + cnt) > cgsblock(&sblock, c)) {
@@ -317,20 +322,29 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
- (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
+ /*
+ * If bread returns an error, it will already have zeroed
+ * out the buffer, so we do not need to do so here.
+ */
+ (void)bread(fsreadfd, (char *)inodebuf, dblk, size);
dp = inodebuf;
}
return (dp++);
}
void
-resetinodebuf()
+setinodebuf(inum)
+ ino_t inum;
{
+ if (inum % sblock.fs_ipg != 0)
+ errx(EEXIT, "bad inode number %d to setinodebuf", inum);
startinum = 0;
- nextino = 0;
- lastinum = 0;
+ nextino = inum;
+ lastinum = inum;
readcnt = 0;
+ if (inodebuf != NULL)
+ return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / sizeof(struct dinode);
readpercg = sblock.fs_ipg / fullcnt;
@@ -342,11 +356,8 @@ resetinodebuf()
partialcnt = fullcnt;
partialsize = inobufsize;
}
- if (inodebuf == NULL &&
- (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
+ if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
- while (nextino < ROOTINO)
- (void)getnextinode(nextino);
}
void
@@ -380,14 +391,11 @@ cacheino(dp, inumber)
inp = (struct inoinfo *)
malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
if (inp == NULL)
- return;
+ errx(EEXIT, "cannot increase directory list");
inpp = &inphead[inumber % numdirs];
inp->i_nexthash = *inpp;
*inpp = inp;
- if (inumber == ROOTINO)
- inp->i_parent = ROOTINO;
- else
- inp->i_parent = (ino_t)0;
+ inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = dp->di_size;
@@ -465,7 +473,7 @@ clri(idesc, type, flag)
n_files--;
(void)ckinode(dp, idesc);
clearinode(dp);
- statemap[idesc->id_number] = USTATE;
+ inoinfo(idesc->id_number)->ino_state = USTATE;
inodirty();
}
}
@@ -476,8 +484,10 @@ findname(idesc)
{
register struct direct *dirp = idesc->id_dirp;
- if (dirp->d_ino != idesc->id_parent)
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
return (KEEPON);
+ }
memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
return (STOP|FOUND);
}
@@ -498,6 +508,20 @@ findino(idesc)
return (KEEPON);
}
+int
+clearentry(idesc)
+ struct inodesc *idesc;
+{
+ register struct direct *dirp = idesc->id_dirp;
+
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
+ return (KEEPON);
+ }
+ dirp->d_ino = 0;
+ return (STOP|FOUND|ALTERED);
+}
+
void
pinode(ino)
ino_t ino;
@@ -534,14 +558,14 @@ blkerror(ino, type, blk)
pfatal("%ld %s I=%lu", blk, type, ino);
printf("\n");
- switch (statemap[ino]) {
+ switch (inoinfo(ino)->ino_state) {
case FSTATE:
- statemap[ino] = FCLEAR;
+ inoinfo(ino)->ino_state = FCLEAR;
return;
case DSTATE:
- statemap[ino] = DCLEAR;
+ inoinfo(ino)->ino_state = DCLEAR;
return;
case FCLEAR:
@@ -549,7 +573,7 @@ blkerror(ino, type, blk)
return;
default:
- errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]);
+ errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state);
/* NOTREACHED */
}
}
@@ -569,10 +593,10 @@ allocino(request, type)
if (request == 0)
request = ROOTINO;
- else if (statemap[request] != USTATE)
+ else if (inoinfo(request)->ino_state != USTATE)
return (0);
for (ino = request; ino < maxino; ino++)
- if (statemap[ino] == USTATE)
+ if (inoinfo(ino)->ino_state == USTATE)
break;
if (ino == maxino)
return (0);
@@ -584,12 +608,12 @@ allocino(request, type)
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
- statemap[ino] = DSTATE;
+ inoinfo(ino)->ino_state = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
- statemap[ino] = FSTATE;
+ inoinfo(ino)->ino_state = FSTATE;
break;
default:
return (0);
@@ -598,11 +622,11 @@ allocino(request, type)
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
return (0);
}
- dp->di_flags = 0;
dp->di_mode = type;
+ dp->di_flags = 0;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_size = sblock.fs_fsize;
@@ -610,7 +634,7 @@ allocino(request, type)
n_files++;
inodirty();
if (newinofmt)
- typemap[ino] = IFTODT(type);
+ inoinfo(ino)->ino_type = IFTODT(type);
return (ino);
}
@@ -632,6 +656,6 @@ freeino(ino)
(void)ckinode(dp, &idesc);
clearinode(dp);
inodirty();
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
n_files--;
}
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 317015b..681ee6dc 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -38,11 +38,7 @@ static const char copyright[] =
#endif /* not lint */
#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
-#endif
-static const char rcsid[] =
- "$Id: main.c,v 1.14 1998/06/15 07:07:16 charnier Exp $";
+static const char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif /* not lint */
#include <sys/param.h>
@@ -56,11 +52,10 @@ static const char rcsid[] =
#include <err.h>
#include <fstab.h>
+#include <string.h>
#include "fsck.h"
-int returntosingle;
-
static int argtoi __P((int flag, char *req, char *str, int base));
static int docheck __P((struct fstab *fsp));
static int checkfilesys __P((char *filesys, char *mntpt, long auxdata,
@@ -74,12 +69,8 @@ main(argc, argv)
{
int ch;
int ret, maxrun = 0;
- struct rlimit rlim;
+ struct rlimit rlimit;
- if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
- rlim.rlim_cur = rlim.rlim_max;
- (void) setrlimit(RLIMIT_DATA, &rlim);
- }
sync();
while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != -1) {
switch (ch) {
@@ -137,9 +128,24 @@ main(argc, argv)
(void)signal(SIGINT, catch);
if (preen)
(void)signal(SIGQUIT, catchquit);
+ /*
+ * Push up our allowed memory limit so we can cope
+ * with huge filesystems.
+ */
+ if (getrlimit(RLIMIT_DATA, &rlimit) == 0) {
+ rlimit.rlim_cur = rlimit.rlim_max;
+ (void)setrlimit(RLIMIT_DATA, &rlimit);
+ }
if (argc) {
- while (argc-- > 0)
- (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
+ while (argc-- > 0) {
+ char *path = blockcheck(*argv);
+
+ if (path == NULL)
+ pfatal("Can't check %s\n", *argv);
+ else
+ (void)checkfilesys(path, 0, 0L, 0);
+ ++argv;
+ }
exit(0);
}
ret = checkfstab(preen, maxrun, docheck, checkfilesys);
@@ -203,16 +209,10 @@ checkfilesys(filesys, mntpt, auxdata, child)
case 0:
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
- return (0);
+ /* fall through */
case -1:
- pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree +
- sblock.fs_frag * sblock.fs_cstotal.cs_nbfree);
- printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
- sblock.fs_cstotal.cs_nffree, sblock.fs_cstotal.cs_nbfree,
- sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
return (0);
}
-
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
@@ -304,7 +304,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
muldup = (struct dups *)0;
inocleanup();
if (fsmodified) {
- (void)time(&sblock.fs_time);
+ sblock.fs_time = time(NULL);
sbdirty();
}
if (cvtlevel && sblk.b_dirty) {
@@ -329,12 +329,13 @@ checkfilesys(filesys, mntpt, auxdata, child)
resolved = 0;
}
ckfini(resolved);
- free(blockmap);
- free(statemap);
- free((char *)lncntp);
- if (!fsmodified)
- return (0);
- if (!preen)
+
+ for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
+ if (inostathead[cylno].il_stat != NULL)
+ free((char *)inostathead[cylno].il_stat);
+ free((char *)inostathead);
+ inostathead = NULL;
+ if (fsmodified && !preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
@@ -354,6 +355,8 @@ checkfilesys(filesys, mntpt, auxdata, child)
if (ret == 0)
return (0);
}
+ if (!fsmodified)
+ return (0);
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 30c0e7d..1ce4471 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass1.c,v 1.11 1998/06/15 07:07:16 charnier Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -52,14 +49,17 @@ static const char rcsid[] =
static ufs_daddr_t badblk;
static ufs_daddr_t dupblk;
+static ino_t lastino; /* last inode in use */
static void checkinode __P((ino_t inumber, struct inodesc *));
void
pass1()
{
+ u_int8_t *cp;
ino_t inumber;
- int c, i, cgd;
+ int c, i, cgd, inosused;
+ struct inostat *info;
struct inodesc idesc;
/*
@@ -81,15 +81,84 @@ pass1()
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
- inumber = 0;
n_files = n_blks = 0;
- resetinodebuf();
for (c = 0; c < sblock.fs_ncg; c++) {
- for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
- if (inumber < ROOTINO)
+ inumber = c * sblock.fs_ipg;
+ setinodebuf(inumber);
+ inosused = sblock.fs_ipg;
+ /*
+ * If we are using soft updates, then we can trust the
+ * cylinder group inode allocation maps to tell us which
+ * inodes are allocated. We will scan the used inode map
+ * to find the inodes that are really in use, and then
+ * read only those inodes in from disk.
+ */
+ if (preen && usedsoftdep) {
+ getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
+ if (!cg_chkmagic(&cgrp))
+ pfatal("CG %d: BAD MAGIC NUMBER\n", c);
+ cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY];
+ for ( ; inosused > 0; inosused -= NBBY, cp--) {
+ if (*cp == 0)
+ continue;
+ for (i = 1 << (NBBY - 1); i > 0; i >>= 1) {
+ if (*cp & i)
+ break;
+ inosused--;
+ }
+ break;
+ }
+ if (inosused < 0)
+ inosused = 0;
+ }
+ /*
+ * Allocate inoinfo structures for the allocated inodes.
+ */
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ inostathead[c].il_stat = info;
+ /*
+ * Scan the allocated inodes.
+ */
+ for (i = 0; i < inosused; i++, inumber++) {
+ if (inumber < ROOTINO) {
+ (void)getnextinode(inumber);
continue;
+ }
checkinode(inumber, &idesc);
}
+ lastino += 1;
+ if (inosused < sblock.fs_ipg || inumber == lastino)
+ continue;
+ /*
+ * If we were not able to determine in advance which inodes
+ * were in use, then reduce the size of the inoinfo structure
+ * to the size necessary to describe the inodes that we
+ * really found.
+ */
+ inosused = lastino - (c * sblock.fs_ipg);
+ if (inosused < 0)
+ inosused = 0;
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = info;
}
freeinodebuf();
}
@@ -120,7 +189,7 @@ checkinode(inumber, idesc)
inodirty();
}
}
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
return;
}
lastino = inumber;
@@ -158,8 +227,7 @@ checkinode(inumber, idesc)
if (debug) {
symbuf[dp->di_size] = 0;
printf("convert symlink %lu(%s) of size %ld\n",
- (u_long)inumber, symbuf,
- (long)dp->di_size);
+ (u_long)inumber, symbuf, (long)dp->di_size);
}
dp = ginode(inumber);
memmove(dp->di_shortlink, symbuf, (long)dp->di_size);
@@ -170,8 +238,7 @@ checkinode(inumber, idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
- if (dp->di_size < sblock.fs_maxsymlinklen ||
- dp->di_blocks == 0) {
+ if (dp->di_size < sblock.fs_maxsymlinklen) {
ndb = howmany(dp->di_size, sizeof(ufs_daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
@@ -200,7 +267,7 @@ checkinode(inumber, idesc)
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
- lncntp[inumber] = dp->di_nlink;
+ inoinfo(inumber)->ino_linkcnt = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
@@ -217,13 +284,14 @@ checkinode(inumber, idesc)
}
if (mode == IFDIR) {
if (dp->di_size == 0)
- statemap[inumber] = DCLEAR;
+ inoinfo(inumber)->ino_state = DCLEAR;
else
- statemap[inumber] = DSTATE;
+ inoinfo(inumber)->ino_state = DSTATE;
cacheino(dp, inumber);
+ countdirs++;
} else
- statemap[inumber] = FSTATE;
- typemap[inumber] = IFTODT(mode);
+ inoinfo(inumber)->ino_state = FSTATE;
+ inoinfo(inumber)->ino_type = IFTODT(mode);
if (doinglevel2 &&
(dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) {
dp = ginode(inumber);
@@ -251,9 +319,9 @@ checkinode(inumber, idesc)
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
- statemap[inumber] = FCLEAR;
+ inoinfo(inumber)->ino_state = FCLEAR;
if (reply("CLEAR") == 1) {
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
diff --git a/sbin/fsck_ffs/pass1b.c b/sbin/fsck_ffs/pass1b.c
index 32a3be7..65ff49c 100644
--- a/sbin/fsck_ffs/pass1b.c
+++ b/sbin/fsck_ffs/pass1b.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1b.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -72,7 +69,7 @@ pass1b()
if (dp == NULL)
continue;
idesc.id_number = inumber;
- if (statemap[inumber] != USTATE &&
+ if (inoinfo(inumber)->ino_state != USTATE &&
(ckinode(dp, &idesc) & STOP))
return;
}
diff --git a/sbin/fsck_ffs/pass2.c b/sbin/fsck_ffs/pass2.c
index 4c24b23..7a61d1d 100644
--- a/sbin/fsck_ffs/pass2.c
+++ b/sbin/fsck_ffs/pass2.c
@@ -32,17 +32,15 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -64,7 +62,7 @@ pass2()
struct dinode dino;
char pathbuf[MAXPATHLEN + 1];
- switch (statemap[ROOTINO]) {
+ switch (inoinfo(ROOTINO)->ino_state) {
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
@@ -113,12 +111,13 @@ pass2()
break;
default:
- errx(EEXIT, "BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
+ errx(EEXIT, "BAD STATE %d FOR ROOT INODE",
+ inoinfo(ROOTINO)->ino_state);
}
- statemap[ROOTINO] = DFOUND;
+ inoinfo(ROOTINO)->ino_state = DFOUND;
if (newinofmt) {
- statemap[WINO] = FSTATE;
- typemap[WINO] = DT_WHT;
+ inoinfo(WINO)->ino_state = FSTATE;
+ inoinfo(WINO)->ino_type = DT_WHT;
}
/*
* Sort the directory list into disk block order.
@@ -181,9 +180,9 @@ pass2()
inp = *inpp;
if (inp->i_parent == 0 || inp->i_isize == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE)
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE)
+ inoinfo(inp->i_number)->ino_state = DFOUND;
if (inp->i_dotdot == inp->i_parent ||
inp->i_dotdot == (ino_t)-1)
continue;
@@ -193,15 +192,15 @@ pass2()
if (reply("FIX") == 0)
continue;
(void)makeentry(inp->i_number, inp->i_parent, "..");
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
- lncntp[inp->i_dotdot]++;
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
inp->i_dotdot = inp->i_parent;
(void)changeino(inp->i_number, "..", inp->i_parent);
}
@@ -228,7 +227,7 @@ pass2check(idesc)
* If converting, set directory entry type.
*/
if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
ret |= ALTERED;
}
/*
@@ -284,7 +283,7 @@ pass2check(idesc)
proto.d_reclen = entrysize;
memmove(dirp, &proto, (size_t)entrysize);
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + entrysize);
memset(dirp, 0, (size_t)n);
dirp->d_reclen = n;
@@ -319,7 +318,7 @@ chk1:
proto.d_reclen = dirp->d_reclen - n;
dirp->d_reclen = n;
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + n);
memset(dirp, 0, (size_t)proto.d_reclen);
dirp->d_reclen = proto.d_reclen;
@@ -356,7 +355,7 @@ chk1:
}
idesc->id_entryno++;
if (dirp->d_ino != 0)
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
return (ret|KEEPON);
chk2:
if (dirp->d_ino == 0)
@@ -394,7 +393,7 @@ chk2:
ret |= ALTERED;
} else {
again:
- switch (statemap[dirp->d_ino]) {
+ switch (inoinfo(dirp->d_ino)->ino_state) {
case USTATE:
if (idesc->id_entryno <= 2)
break;
@@ -406,7 +405,7 @@ again:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
- if (statemap[dirp->d_ino] == FCLEAR)
+ if (inoinfo(dirp->d_ino)->ino_state == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
@@ -418,14 +417,14 @@ again:
if ((n = reply("REMOVE")) == 1)
break;
dp = ginode(dirp->d_ino);
- statemap[dirp->d_ino] =
+ inoinfo(dirp->d_ino)->ino_state =
(dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
- lncntp[dirp->d_ino] = dp->di_nlink;
+ inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink;
goto again;
case DSTATE:
- if (statemap[idesc->id_number] == DFOUND)
- statemap[dirp->d_ino] = DFOUND;
+ if (inoinfo(idesc->id_number)->ino_state == DFOUND)
+ inoinfo(dirp->d_ino)->ino_state = DFOUND;
/* fall through */
case DFOUND:
@@ -439,10 +438,10 @@ again:
namebuf);
if (preen) {
printf(" (REMOVED)\n");
- n = 1;
- break;
+ n = 1;
+ break;
}
- else if ((n = reply("REMOVE")) == 1)
+ if ((n = reply("REMOVE")) == 1)
break;
}
if (idesc->id_entryno > 2)
@@ -450,19 +449,20 @@ again:
/* fall through */
case FSTATE:
- if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
+ if (newinofmt &&
+ dirp->d_type != inoinfo(dirp->d_ino)->ino_type) {
fileerror(idesc->id_number, dirp->d_ino,
"BAD TYPE VALUE");
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
if (reply("FIX") == 1)
ret |= ALTERED;
}
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
break;
default:
errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[dirp->d_ino], dirp->d_ino);
+ inoinfo(dirp->d_ino)->ino_state, dirp->d_ino);
}
}
if (n == 0)
diff --git a/sbin/fsck_ffs/pass3.c b/sbin/fsck_ffs/pass3.c
index 6524a11..6320755 100644
--- a/sbin/fsck_ffs/pass3.c
+++ b/sbin/fsck_ffs/pass3.c
@@ -32,45 +32,84 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass3.c 8.2 (Berkeley) 4/27/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+
+#include <string.h>
#include "fsck.h"
void
pass3()
{
- register struct inoinfo **inpp, *inp;
+ struct inoinfo *inp;
+ int loopcnt, inpindex, state;
ino_t orphan;
- int loopcnt;
+ struct inodesc idesc;
+ char namebuf[MAXNAMLEN+1];
- for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
- inp = *inpp;
+ for (inpindex = inplast - 1; inpindex >= 0; inpindex--) {
+ inp = inpsort[inpindex];
+ state = inoinfo(inp->i_number)->ino_state;
if (inp->i_number == ROOTINO ||
- !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
+ (inp->i_parent != 0 && state != DSTATE))
+ continue;
+ if (state == DCLEAR)
continue;
- if (statemap[inp->i_number] == DCLEAR)
+ /*
+ * If we are running with soft updates and we come
+ * across unreferenced directories, we just leave
+ * them in DSTATE which will cause them to be pitched
+ * in pass 4.
+ */
+ if (preen && resolved && usedsoftdep && state == DSTATE) {
+ if (inp->i_dotdot >= ROOTINO)
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
continue;
+ }
for (loopcnt = 0; ; loopcnt++) {
orphan = inp->i_number;
if (inp->i_parent == 0 ||
- statemap[inp->i_parent] != DSTATE ||
- loopcnt > numdirs)
+ inoinfo(inp->i_parent)->ino_state != DSTATE ||
+ loopcnt > countdirs)
break;
inp = getinoinfo(inp->i_parent);
}
- (void)linkup(orphan, inp->i_dotdot);
- inp->i_parent = inp->i_dotdot = lfdir;
- lncntp[lfdir]--;
- statemap[orphan] = DFOUND;
+ if (loopcnt <= countdirs) {
+ if (linkup(orphan, inp->i_dotdot, NULL)) {
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
+ propagate();
+ continue;
+ }
+ pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu", orphan);
+ if (reply("RECONNECT") == 0)
+ continue;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = DATA;
+ idesc.id_number = inp->i_parent;
+ idesc.id_parent = orphan;
+ idesc.id_func = findname;
+ idesc.id_name = namebuf;
+ if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0)
+ pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
+ if (linkup(orphan, inp->i_parent, namebuf)) {
+ idesc.id_func = clearentry;
+ if (ckinode(ginode(inp->i_parent), &idesc) & FOUND)
+ inoinfo(orphan)->ino_linkcnt++;
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
propagate();
}
}
diff --git a/sbin/fsck_ffs/pass4.c b/sbin/fsck_ffs/pass4.c
index b2f1fe9..48c5090 100644
--- a/sbin/fsck_ffs/pass4.c
+++ b/sbin/fsck_ffs/pass4.c
@@ -32,16 +32,14 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -55,22 +53,27 @@ pass4()
register struct zlncnt *zlnp;
struct dinode *dp;
struct inodesc idesc;
- int n;
+ int i, n, cg;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass4check;
- for (inumber = ROOTINO; inumber <= lastino; inumber++) {
- idesc.id_number = inumber;
- switch (statemap[inumber]) {
+ for (cg = 0; cg < sblock.fs_ncg; cg++) {
+ inumber = cg * sblock.fs_ipg;
+ for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) {
+ if (inumber < ROOTINO)
+ continue;
+ idesc.id_number = inumber;
+ switch (inoinfo(inumber)->ino_state) {
- case FSTATE:
- case DFOUND:
- n = lncntp[inumber];
- if (n)
- adjust(&idesc, (short)n);
- else {
- for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
+ case FSTATE:
+ case DFOUND:
+ n = inoinfo(inumber)->ino_linkcnt;
+ if (n) {
+ adjust(&idesc, (short)n);
+ break;
+ }
+ for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
if (zlnp->zlncnt == inumber) {
zlnp->zlncnt = zlnhead->zlncnt;
zlnp = zlnhead;
@@ -79,30 +82,31 @@ pass4()
clri(&idesc, "UNREF", 1);
break;
}
- }
- break;
+ }
+ break;
- case DSTATE:
- clri(&idesc, "UNREF", 1);
- break;
+ case DSTATE:
+ clri(&idesc, "UNREF", 1);
+ break;
- case DCLEAR:
- dp = ginode(inumber);
- if (dp->di_size == 0) {
- clri(&idesc, "ZERO LENGTH", 1);
+ case DCLEAR:
+ dp = ginode(inumber);
+ if (dp->di_size == 0) {
+ clri(&idesc, "ZERO LENGTH", 1);
+ break;
+ }
+ /* fall through */
+ case FCLEAR:
+ clri(&idesc, "BAD/DUP", 1);
break;
- }
- /* fall through */
- case FCLEAR:
- clri(&idesc, "BAD/DUP", 1);
- break;
- case USTATE:
- break;
+ case USTATE:
+ break;
- default:
- errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[inumber], inumber);
+ default:
+ errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
+ inoinfo(inumber)->ino_state, inumber);
+ }
}
}
}
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index f3994f8..d492a18 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass5.c,v 1.13 1998/08/04 09:19:03 phk Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -52,7 +49,7 @@ static const char rcsid[] =
void
pass5()
{
- int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
+ int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
@@ -66,7 +63,7 @@ pass5()
register struct cg *newcg = (struct cg *)buf;
struct ocg *ocg = (struct ocg *)buf;
- statemap[WINO] = USTATE;
+ inoinfo(WINO)->ino_state = USTATE;
memset(newcg, 0, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
if (cvtlevel >= 3) {
@@ -207,8 +204,8 @@ pass5()
if (fs->fs_postblformat == FS_42POSTBLFMT)
ocg->cg_magic = CG_MAGIC;
j = fs->fs_ipg * c;
- for (i = 0; i < fs->fs_ipg; j++, i++) {
- switch (statemap[j]) {
+ for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
+ switch (inoinfo(j)->ino_state) {
case USTATE:
break;
@@ -229,7 +226,7 @@ pass5()
if (j < ROOTINO)
break;
errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
- statemap[j], j);
+ inoinfo(j)->ino_state, j);
}
}
if (c == 0)
@@ -325,7 +322,7 @@ pass5()
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE\n",
- c * fs->fs_ipg + i * 8 + k);
+ c * fs->fs_ipg + i * NBBY + k);
}
}
for (i = 0; i < blkmapsize; i++) {
@@ -338,7 +335,7 @@ pass5()
if (cg_blksfree(newcg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE\n",
- c * fs->fs_fpg + i * 8 + k);
+ c * fs->fs_fpg + i * NBBY + k);
}
}
}
@@ -355,24 +352,7 @@ pass5()
&& dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
fs->fs_ronly = 0;
+ fs->fs_fmod = 0;
sbdirty();
}
- if (fs->fs_fmod != 0) {
- pwarn("MODIFIED FLAG SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_fmod = 0;
- sbdirty();
- }
- }
- if (fs->fs_clean == 0) {
- pwarn("CLEAN FLAG NOT SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_clean = 1;
- sbdirty();
- }
- }
}
diff --git a/sbin/fsck_ffs/preen.c b/sbin/fsck_ffs/preen.c
index 9705aee..ba0140b 100644
--- a/sbin/fsck_ffs/preen.c
+++ b/sbin/fsck_ffs/preen.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
@@ -46,7 +42,7 @@ static const char rcsid[] =
#include <ufs/ufs/dinode.h>
#include <ctype.h>
-#include <err.h>
+#include <errno.h>
#include <fstab.h>
#include <string.h>
@@ -93,7 +89,8 @@ checkfstab(preen, maxrun, docheck, chkit)
sumstatus = 0;
for (passno = 1; passno <= 2; passno++) {
if (setfsent() == 0) {
- warnx("can't open checklist file: %s", _PATH_FSTAB);
+ fprintf(stderr, "Can't open checklist file: %s\n",
+ _PATH_FSTAB);
return (8);
}
while ((fsp = getfsent()) != 0) {
@@ -222,11 +219,15 @@ finddisk(name)
dk->name[len] == 0)
return (dk);
}
- if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
- errx(8, "out of memory");
+ if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
dk = *dkp;
- if ((dk->name = malloc(len + 1)) == NULL)
- errx(8, "out of memory");
+ if ((dk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strncpy(dk->name, name, len);
dk->name[len] = '\0';
dk->part = NULL;
@@ -249,14 +250,20 @@ addpart(name, fsname, auxdata)
printf("%s in fstab more than once!\n", name);
return;
}
- if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
- errx(8, "out of memory");
+ if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
pt = *ppt;
- if ((pt->name = malloc(strlen(name) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->name, name);
- if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->fsname, fsname);
pt->next = NULL;
pt->auxdata = auxdata;
@@ -271,7 +278,7 @@ startdisk(dk, checkit)
dk->pid = fork();
if (dk->pid < 0) {
- warn("fork");
+ perror("fork");
return (8);
}
if (dk->pid == 0)
@@ -287,19 +294,17 @@ blockcheck(origname)
struct stat stslash, stblock, stchar;
char *newname, *raw;
struct fstab *fsinfo;
- int retried = 0, l;
+ int retried = 0, len;
hotroot = 0;
if (stat("/", &stslash) < 0) {
- warn("/");
- printf("Can't stat root\n");
+ printf("Can't stat /: %s\n", strerror(errno));
return (origname);
}
newname = origname;
retry:
if (stat(newname, &stblock) < 0) {
- warn("%s", newname);
- printf("Can't stat %s\n", newname);
+ printf("Can't stat %s: %s\n", newname, strerror(errno));
return (origname);
}
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
@@ -307,8 +312,7 @@ retry:
hotroot++;
raw = rawname(newname);
if (stat(raw, &stchar) < 0) {
- warn("%s", raw);
- printf("Can't stat %s\n", raw);
+ printf("Can't stat %s: %s\n", raw, strerror(errno));
return (origname);
}
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
@@ -318,15 +322,15 @@ retry:
return (origname);
}
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
- newname = unrawname(origname);
+ newname = unrawname(newname);
retried++;
goto retry;
} else if ((stblock.st_mode & S_IFMT) == S_IFDIR && !retried) {
- l = strlen(origname) - 1;
- if (l > 0 && origname[l] == '/')
+ len = strlen(origname) - 1;
+ if (len > 0 && origname[len] == '/')
/* remove trailing slash */
- origname[l] = '\0';
- if(!(fsinfo=getfsfile(origname))) {
+ origname[len] = '\0';
+ if ((fsinfo = getfsfile(origname)) == NULL) {
printf("Can't resolve %s to character special device",
origname);
return (0);
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 25dab92..5a842f4 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -32,16 +32,13 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
-#endif
-static const char rcsid[] =
- "$Id: setup.c,v 1.11 1998/06/15 07:07:21 charnier Exp $";
#endif /* not lint */
#define DKTYPENAMES
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
@@ -82,7 +79,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
- skipclean = preen;
+ skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
@@ -114,8 +111,7 @@ setup(dev)
asblk.b_un.b_buf = malloc(SBSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
- lp = getdisklabel((char *)NULL, fsreadfd);
- if (lp)
+ if ((lp = getdisklabel(NULL, fsreadfd)))
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
@@ -147,6 +143,10 @@ setup(dev)
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
bflag = 0;
}
+ if (skipclean && sblock.fs_clean) {
+ pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
+ return (-1);
+ }
maxfsblock = sblock.fs_size;
maxino = sblock.fs_ncg * sblock.fs_ipg;
/*
@@ -265,12 +265,6 @@ setup(dev)
}
}
/*
- * If we survive the above basic checks and are preening,
- * quit here unless forced.
- */
- if (skipclean && sblock.fs_clean && !fflag)
- return (-1);
- /*
* allocate and initialize the necessary maps
*/
bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short));
@@ -280,22 +274,11 @@ setup(dev)
(unsigned)bmapsize);
goto badsb;
}
- statemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (statemap == NULL) {
- printf("cannot alloc %u bytes for statemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- typemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (typemap == NULL) {
- printf("cannot alloc %u bytes for typemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
- if (lncntp == NULL) {
- printf("cannot alloc %u bytes for lncntp\n",
- (unsigned)(maxino + 1) * sizeof(short));
+ inostathead = calloc((unsigned)(sblock.fs_ncg),
+ sizeof(struct inostatlist));
+ if (inostathead == NULL) {
+ printf("cannot alloc %u bytes for inostathead\n",
+ (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg)));
goto badsb;
}
numdirs = sblock.fs_cstotal.cs_ndir;
@@ -474,9 +457,11 @@ calcsb(dev, devfd, fs)
fstypenames[pp->p_fstype] : "unknown");
return (0);
}
- if (pp->p_fsize == 0 || pp->p_frag == 0) {
- pfatal("%s: LABELED AS A %s FILE SYSTEM, BUT BLOCK SIZE IS 0\n",
- dev, fstypenames[pp->p_fstype]);
+ if (pp->p_fsize == 0 || pp->p_frag == 0 ||
+ pp->p_cpg == 0 || pp->p_size == 0) {
+ pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n",
+ dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype],
+ pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size);
return (0);
}
memset(fs, 0, sizeof(struct fs));
diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c
index 0d82d6e..5ea02b6 100644
--- a/sbin/fsck_ffs/utilities.c
+++ b/sbin/fsck_ffs/utilities.c
@@ -32,20 +32,16 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
-#include <ctype.h>
#include <err.h>
#include <string.h>
@@ -116,6 +112,26 @@ reply(question)
}
/*
+ * Look up state information for an inode.
+ */
+struct inostat *
+inoinfo(inum)
+ ino_t inum;
+{
+ static struct inostat unallocated = { USTATE, 0, 0 };
+ struct inostatlist *ilp;
+ int iloff;
+
+ if (inum > maxino)
+ errx(EEXIT, "inoinfo: inumber %d out of range", inum);
+ ilp = &inostathead[inum / sblock.fs_ipg];
+ iloff = inum % sblock.fs_ipg;
+ if (iloff >= ilp->il_numalloced)
+ return (&unallocated);
+ return (&ilp->il_stat[iloff]);
+}
+
+/*
* Malloc buffers and set up cache.
*/
void
@@ -270,16 +286,23 @@ ckfini(markclean)
free((char *)bp);
}
if (bufhead.b_size != cnt)
- errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt);
+ errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt);
pbp = pdirbp = (struct bufarea *)0;
- if (markclean && sblock.fs_clean == 0) {
- sblock.fs_clean = 1;
+ if (sblock.fs_clean != markclean) {
+ sblock.fs_clean = markclean;
sbdirty();
ofsmodified = fsmodified;
flush(fswritefd, &sblk);
fsmodified = ofsmodified;
- if (!preen)
- printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
+ if (!preen) {
+ printf("\n***** FILE SYSTEM MARKED %s *****\n",
+ markclean ? "CLEAN" : "DIRTY");
+ if (!markclean)
+ rerun = 1;
+ }
+ } else if (!preen && !markclean) {
+ printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
+ rerun = 1;
}
if (debug)
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
@@ -324,6 +347,8 @@ bread(fd, buf, blk, size)
}
}
printf("\n");
+ if (errs)
+ resolved = 0;
return (errs);
}
@@ -348,6 +373,7 @@ bwrite(fd, buf, blk, size)
fsmodified = 1;
return;
}
+ resolved = 0;
rwerror("WRITE", blk);
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
@@ -438,7 +464,8 @@ getpathname(namebuf, curdir, ino)
return;
}
if (busy ||
- (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
+ (inoinfo(curdir)->ino_state != DSTATE &&
+ inoinfo(curdir)->ino_state != DFOUND)) {
(void)strcpy(namebuf, "?");
return;
}
@@ -497,6 +524,7 @@ void
catchquit(sig)
int sig;
{
+
printf("returning to single-user after filesystem check\n");
returntosingle = 1;
(void)signal(SIGQUIT, SIG_DFL);
@@ -589,14 +617,16 @@ pfatal(fmt, va_alist)
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
- "\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
+ "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n");
return;
}
+ if (cdevname == NULL)
+ cdevname = "fsck";
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
- cdevname, usedsoftdep ? " SOFTDEP " : " ");
+ cdevname, usedsoftdep ? " SOFT UPDATE " : " ");
ckfini(0);
exit(EEXIT);
}
diff --git a/sbin/fsck_ifs/dir.c b/sbin/fsck_ifs/dir.c
index 91b507f..ceb66e6 100644
--- a/sbin/fsck_ifs/dir.c
+++ b/sbin/fsck_ifs/dir.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: dir.c,v 1.11 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -88,9 +85,9 @@ propagate()
inp = *inpp;
if (inp->i_parent == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE) {
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE) {
+ inoinfo(inp->i_number)->ino_state = DFOUND;
change++;
}
}
@@ -123,6 +120,8 @@ dirscan(idesc)
idesc->id_loc = 0;
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
+ if (dsize > sizeof(dbuf))
+ dsize = sizeof(dbuf);
memmove(dbuf, dp, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
@@ -235,8 +234,7 @@ dircheck(idesc, dp)
int spaceleft;
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
- if (dp->d_ino >= maxino ||
- dp->d_reclen == 0 ||
+ if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
@@ -306,13 +304,40 @@ adjust(idesc, lcnt)
register struct inodesc *idesc;
int lcnt;
{
- register struct dinode *dp;
+ struct dinode *dp;
+ int saveresolved;
dp = ginode(idesc->id_number);
if (dp->di_nlink == lcnt) {
- if (linkup(idesc->id_number, (ino_t)0) == 0)
- clri(idesc, "UNREF", 0);
- } else {
+ /*
+ * If we have not hit any unresolved problems, are running
+ * in preen mode, and are on a filesystem using soft updates,
+ * then just toss any partially allocated files.
+ */
+ if (resolved && preen && usedsoftdep) {
+ clri(idesc, "UNREF", 1);
+ return;
+ } else {
+ /*
+ * The filesystem can be marked clean even if
+ * a file is not linked up, but is cleared.
+ * Hence, resolved should not be cleared when
+ * linkup is answered no, but clri is answered yes.
+ */
+ saveresolved = resolved;
+ if (linkup(idesc->id_number, (ino_t)0, NULL) == 0) {
+ resolved = saveresolved;
+ clri(idesc, "UNREF", 0);
+ return;
+ }
+ /*
+ * Account for the new reference created by linkup().
+ */
+ dp = ginode(idesc->id_number);
+ lcnt--;
+ }
+ }
+ if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
@@ -355,7 +380,7 @@ mkentry(idesc)
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
dirp->d_reclen = newent.d_reclen;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
dirp->d_namlen = newent.d_namlen;
@@ -388,16 +413,17 @@ chgino(idesc)
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
- dirp->d_type = typemap[idesc->id_parent];
+ dirp->d_type = inoinfo(idesc->id_parent)->ino_type;
else
dirp->d_type = 0;
return (ALTERED|STOP);
}
int
-linkup(orphan, parentdir)
+linkup(orphan, parentdir, name)
ino_t orphan;
ino_t parentdir;
+ char *name;
{
register struct dinode *dp;
int lostdir;
@@ -410,7 +436,7 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
- if ((preen || usedsoftdep) && dp->di_size == 0)
+ if (preen && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
@@ -431,6 +457,7 @@ linkup(orphan, parentdir)
lfdir = allocdir(ROOTINO, (ino_t)0, lfmode);
if (lfdir != 0) {
if (makeentry(ROOTINO, lfdir, lfname) != 0) {
+ numdirs++;
if (preen)
printf(" (CREATED)\n");
} else {
@@ -466,21 +493,21 @@ linkup(orphan, parentdir)
idesc.id_type = ADDR;
idesc.id_func = pass4check;
idesc.id_number = oldlfdir;
- adjust(&idesc, lncntp[oldlfdir] + 1);
- lncntp[oldlfdir] = 0;
+ adjust(&idesc, inoinfo(oldlfdir)->ino_linkcnt + 1);
+ inoinfo(oldlfdir)->ino_linkcnt = 0;
dp = ginode(lfdir);
}
- if (statemap[lfdir] != DFOUND) {
+ if (inoinfo(lfdir)->ino_state != DFOUND) {
pfatal("SORRY. NO lost+found DIRECTORY\n\n");
return (0);
}
(void)lftempname(tempname, orphan);
- if (makeentry(lfdir, orphan, tempname) == 0) {
+ if (makeentry(lfdir, orphan, (name ? name : tempname)) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
printf("\n\n");
return (0);
}
- lncntp[orphan]--;
+ inoinfo(orphan)->ino_linkcnt--;
if (lostdir) {
if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
parentdir != (ino_t)-1)
@@ -488,19 +515,11 @@ linkup(orphan, parentdir)
dp = ginode(lfdir);
dp->di_nlink++;
inodirty();
- lncntp[lfdir]++;
+ inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", orphan);
if (parentdir != (ino_t)-1) {
printf("PARENT WAS I=%lu\n", (u_long)parentdir);
- /*
- * The parent directory, because of the ordering
- * guarantees, has had the link count incremented
- * for the child, but no entry was made. This
- * fixes the parent link count so that fsck does
- * not need to be rerun.
- */
- lncntp[parentdir]++;
-
+ inoinfo(parentdir)->ino_linkcnt++;
}
if (preen == 0)
printf("\n");
@@ -658,19 +677,20 @@ allocdir(parent, request, mode)
dp->di_nlink = 2;
inodirty();
if (ino == ROOTINO) {
- lncntp[ino] = dp->di_nlink;
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
cacheino(dp, ino);
return(ino);
}
- if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
+ if (inoinfo(parent)->ino_state != DSTATE &&
+ inoinfo(parent)->ino_state != DFOUND) {
freeino(ino);
return (0);
}
cacheino(dp, ino);
- statemap[ino] = statemap[parent];
- if (statemap[ino] == DSTATE) {
- lncntp[ino] = dp->di_nlink;
- lncntp[parent]++;
+ inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
+ if (inoinfo(ino)->ino_state == DSTATE) {
+ inoinfo(ino)->ino_linkcnt = dp->di_nlink;
+ inoinfo(parent)->ino_linkcnt++;
}
dp = ginode(parent);
dp->di_nlink++;
diff --git a/sbin/fsck_ifs/fsck.h b/sbin/fsck_ifs/fsck.h
index 4e0271d..81b2292 100644
--- a/sbin/fsck_ifs/fsck.h
+++ b/sbin/fsck_ifs/fsck.h
@@ -42,16 +42,35 @@
#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */
-#ifndef BUFSIZ
-#define BUFSIZ 1024
-#endif
-
+/*
+ * Each inode on the filesystem is described by the following structure.
+ * The linkcnt is initially set to the value in the inode. Each time it
+ * is found during the descent in passes 2, 3, and 4 the count is
+ * decremented. Any inodes whose count is non-zero after pass 4 needs to
+ * have its link count adjusted by the value remaining in ino_linkcnt.
+ */
+struct inostat {
+ char ino_state; /* state of inode, see below */
+ char ino_type; /* type of inode */
+ short ino_linkcnt; /* number of links not found */
+};
+/*
+ * Inode states.
+ */
#define USTATE 01 /* inode not allocated */
#define FSTATE 02 /* inode is file */
#define DSTATE 03 /* inode is directory */
#define DFOUND 04 /* directory found during descent */
#define DCLEAR 05 /* directory is to be cleared */
#define FCLEAR 06 /* file is to be cleared */
+/*
+ * Inode state information is contained on per cylinder group lists
+ * which are described by the following structure.
+ */
+struct inostatlist {
+ long il_numalloced; /* number of inodes allocated in this cg */
+ struct inostat *il_stat;/* inostat info for this cylinder group */
+} *inostathead;
/*
* buffer cache structure.
@@ -163,11 +182,12 @@ struct inoinfo {
ufs_daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, listmax, inplast;
+long countdirs; /* number of directories we actually found */
char *cdevname; /* name of device being checked */
long dev_bsize; /* computed value of DEV_BSIZE */
long secsize; /* actual disk sector size */
-char fflag; /* force fs check (ignore clean flag) */
+char fflag; /* force check, ignore clean flag */
char nflag; /* assume a no response */
char yflag; /* assume a yes response */
int bflag; /* location of alternate super block */
@@ -177,23 +197,19 @@ int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
-char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
+char rerun; /* rerun fsck. Only used in non-preen mode */
+int returntosingle; /* 1 => return to single user mode on exit */
+char resolved; /* cleared if unresolved changes => not clean */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */
int fsmodified; /* 1 => write done to file system */
int fsreadfd; /* file descriptor for reading file system */
int fswritefd; /* file descriptor for writing file system */
-int returntosingle; /* return to single user mode */
-int rerun; /* rerun fsck. Only used in non-preen mode */
ufs_daddr_t maxfsblock; /* number of blocks in the file system */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in file system */
-ino_t lastino; /* last inode in use */
-char *statemap; /* ptr to inode state table */
-u_char *typemap; /* ptr to inode type table */
-short *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
char *lfname; /* lost & found directory name */
@@ -219,6 +235,7 @@ struct dinode zino;
struct fstab;
+
void adjust __P((struct inodesc *, int lcnt));
ufs_daddr_t allocblk __P((long frags));
ino_t allocdir __P((ino_t parent, ino_t request, int mode));
@@ -239,6 +256,7 @@ int chkrange __P((ufs_daddr_t blk, int cnt));
void ckfini __P((int markclean));
int ckinode __P((struct dinode *dp, struct inodesc *));
void clri __P((struct inodesc *, char *type, int flag));
+int clearentry __P((struct inodesc *));
void direrror __P((ino_t ino, char *errmesg));
int dirscan __P((struct inodesc *));
int dofix __P((struct inodesc *, char *msg));
@@ -262,7 +280,8 @@ void getpathname __P((char *namebuf, ino_t curdir, ino_t ino));
struct dinode *ginode __P((ino_t inumber));
void inocleanup __P((void));
void inodirty __P((void));
-int linkup __P((ino_t orphan, ino_t parentdir));
+struct inostat *inoinfo __P((ino_t inum));
+int linkup __P((ino_t orphan, ino_t parentdir, char *name));
int makeentry __P((ino_t parent, ino_t ino, char *name));
void panic __P((const char *fmt, ...));
void pass1 __P((void));
@@ -278,6 +297,6 @@ void pinode __P((ino_t ino));
void propagate __P((void));
void pwarn __P((const char *fmt, ...));
int reply __P((char *question));
-void resetinodebuf __P((void));
+void setinodebuf __P((ino_t));
int setup __P((char *dev));
void voidquit __P((int));
diff --git a/sbin/fsck_ifs/fsck_ifs.8 b/sbin/fsck_ifs/fsck_ifs.8
index 51d1679..20c867f 100644
--- a/sbin/fsck_ifs/fsck_ifs.8
+++ b/sbin/fsck_ifs/fsck_ifs.8
@@ -1,3 +1,4 @@
+.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -10,7 +11,7 @@
.\" 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:
+.\" 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
@@ -30,9 +31,8 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
-.\" $Id: fsck.8,v 1.10 1997/03/12 16:35:26 bde Exp $
.\"
-.Dd May 9, 1995
+.Dd November 15, 1996
.Dt FSCK 8
.Os BSD 4
.Sh NAME
@@ -43,24 +43,25 @@
.Fl p
.Op Fl f
.Op Fl m Ar mode
+.Op Ar filesystem
+.Ar ...
.Nm fsck
+.Op Fl ny
.Op Fl b Ar block#
.Op Fl c Ar level
.Op Fl l Ar maxparallel
-.Op Fl y
-.Op Fl n
.Op Fl m Ar mode
.Op Ar filesystem
.Ar ...
.Sh DESCRIPTION
The first form of
-.Nm
+.Nm fsck
preens a standard set of filesystems or the specified filesystems.
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
Here
-.Nm
+.Nm fsck
reads the table
.Pa /etc/fstab
to determine which filesystems to check.
@@ -73,22 +74,18 @@ running one process per disk drive.
The disk drive containing each filesystem is inferred from the longest prefix
of the device name that ends in a digit; the remaining characters are assumed
to be the partition designator.
-.Pp
-The clean flag of each filesystem's superblock is examined and only those filesystems that
-are not marked clean are checked.
+In preening mode,
+filesystems that are marked clean are skipped.
Filesystems are marked clean when they are unmounted,
when they have been mounted read-only, or when
-.Nm
+.Nm fsck
runs on them successfully.
-If the
-.Fl f
-option is specified, the filesystems
-will be checked regardless of the state of their clean flag.
.Pp
The kernel takes care that only a restricted class of innocuous filesystem
inconsistencies can happen unless hardware or software failures intervene.
These are limited to the following:
-.Bl -item -compact
+.Pp
+.Bl -item -compact -offset indent
.It
Unreferenced inodes
.It
@@ -102,7 +99,7 @@ Counts in the super-block wrong
.El
.Pp
These are the only inconsistencies that
-.Nm
+.Nm fsck
with the
.Fl p
option will correct; if it encounters other inconsistencies, it exits
@@ -110,7 +107,7 @@ with an abnormal return status and an automatic reboot will then fail.
For each corrected inconsistency one or more lines will be printed
identifying the filesystem on which the correction will take place,
and the nature of the correction. After successfully correcting a filesystem,
-.Nm
+.Nm fsck
will print the number of files on that filesystem,
the number of used and free blocks,
and the percentage of fragmentation.
@@ -118,7 +115,7 @@ and the percentage of fragmentation.
If sent a
.Dv QUIT
signal,
-.Nm
+.Nm fsck
will finish the filesystem checks, then exit with an abnormal
return status that causes an automatic reboot to fail.
This is useful when you want to finish the filesystem checks during an
@@ -128,7 +125,7 @@ but do not want the machine to come up multiuser after the checks complete.
Without the
.Fl p
option,
-.Nm
+.Nm fsck
audits and interactively repairs inconsistent conditions for filesystems.
If the filesystem is inconsistent the operator is prompted for concurrence
before each correction is attempted.
@@ -144,7 +141,7 @@ is to wait for the operator to respond
or
.Li no .
If the operator does not have write permission on the filesystem
-.Nm
+.Nm fsck
will default to a
.Fl n
action.
@@ -158,38 +155,12 @@ and
combined.
.Pp
The following flags are interpreted by
-.Nm Ns .
+.Nm fsck .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the filesystem. Block 32 is usually
an alternate super block.
-.It Fl l
-Limit the number of parallel checks to the number specified in the following
-argument.
-By default, the limit is the number of disks, running one process per disk.
-If a smaller limit is given, the disks are checked round-robin, one filesystem
-at a time.
-.It Fl m
-Use the mode specified in octal immediately after the flag as the
-permission bits to use when creating the
-.Pa lost+found
-directory rather than the default 1777.
-In particular, systems that do not wish to have lost files accessible
-by all users on the system should use a more restrictive
-set of permissions such as 700.
-.It Fl y
-Assume a yes response to all questions asked by
-.Nm Ns ;
-this should be used with great caution as this is a free license
-to continue after essentially unlimited trouble has been encountered.
-.It Fl n
-Assume a no response to all questions asked by
-.Nm
-except for
-.Ql CONTINUE? ,
-which is assumed to be affirmative;
-do not open the filesystem for writing.
.It Fl c
Convert the filesystem to the specified level.
Note that the level of a filesystem can only be raised.
@@ -210,7 +181,7 @@ If maxcontig is equal to one, delete any existing segment maps.
.El
.Pp
In interactive mode,
-.Nm
+.Nm fsck
will list the conversion to be made
and ask whether the conversion should be done.
If a negative answer is given,
@@ -223,10 +194,44 @@ are being converted at once.
The format of a filesystem can be determined from the
first line of output from
.Xr dumpfs 8 .
+.It Fl f
+Force
+.Nm fsck
+to check
+.Sq clean
+filesystems when preening.
+.It Fl l
+Limit the number of parallel checks to the number specified in the following
+argument.
+By default, the limit is the number of disks, running one process per disk.
+If a smaller limit is given, the disks are checked round-robin, one filesystem
+at a time.
+.It Fl m
+Use the mode specified in octal immediately after the flag as the
+permission bits to use when creating the
+.Pa lost+found
+directory rather than the default 1777.
+In particular, systems that do not wish to have lost files accessible
+by all users on the system should use a more restrictive
+set of permissions such as 700.
+.It Fl n
+Assume a no response to all questions asked by
+.Nm fsck
+except for
+.Ql CONTINUE? ,
+which is assumed to be affirmative;
+do not open the filesystem for writing.
+.It Fl p
+Preen filesystems (see above).
+.It Fl y
+Assume a yes response to all questions asked by
+.Nm fsck ;
+this should be used with great caution as this is a free license
+to continue after essentially unlimited trouble has been encountered.
.El
.Pp
If no filesystems are given to
-.Nm
+.Nm fsck
then a default list of filesystems is read from
the file
.Pa /etc/fstab .
@@ -259,7 +264,7 @@ File pointing to unallocated inode.
.It
Inode number out of range.
.It
-Holes in directories.
+Directories with unallocated blocks (holes).
.It
Dot or dot-dot not the first two entries of a directory
or having the wrong inode number.
@@ -296,14 +301,13 @@ contains default list of filesystems to check.
.El
.Sh DIAGNOSTICS
The diagnostics produced by
-.Nm
+.Nm fsck
are fully enumerated and explained in Appendix A of
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
-.Xr fs 5 ,
.Xr fstab 5 ,
-.Xr fsdb 8 ,
+.Xr fs 5 ,
.Xr newfs 8 ,
.Xr reboot 8
diff --git a/sbin/fsck_ifs/inode.c b/sbin/fsck_ifs/inode.c
index b7e80cd..a54f2ce 100644
--- a/sbin/fsck_ifs/inode.c
+++ b/sbin/fsck_ifs/inode.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: inode.c,v 1.15 1998/06/28 19:23:02 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -62,7 +58,8 @@ ckinode(dp, idesc)
register struct inodesc *idesc;
{
ufs_daddr_t *ap;
- long ret, n, ndb, offset;
+ int ret;
+ long n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
mode_t mode;
@@ -74,7 +71,7 @@ ckinode(dp, idesc)
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
- (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0)))
+ dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
@@ -239,8 +236,16 @@ chkrange(blk, cnt)
{
register int c;
- if (blk < 0 || blk >= maxfsblock || cnt < 0 || cnt > maxfsblock - blk)
+ if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
+ cnt - 1 > maxfsblock - blk)
return (1);
+ if (cnt > sblock.fs_frag ||
+ fragnum(&sblock, blk) + cnt > sblock.fs_frag) {
+ if (debug)
+ printf("bad size: blk %ld, offset %ld, size %ld\n",
+ blk, fragnum(&sblock, blk), cnt);
+ return (1);
+ }
c = dtog(&sblock, blk);
if (blk < cgdmin(&sblock, c)) {
if ((blk + cnt) > cgsblock(&sblock, c)) {
@@ -317,20 +322,29 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
- (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
+ /*
+ * If bread returns an error, it will already have zeroed
+ * out the buffer, so we do not need to do so here.
+ */
+ (void)bread(fsreadfd, (char *)inodebuf, dblk, size);
dp = inodebuf;
}
return (dp++);
}
void
-resetinodebuf()
+setinodebuf(inum)
+ ino_t inum;
{
+ if (inum % sblock.fs_ipg != 0)
+ errx(EEXIT, "bad inode number %d to setinodebuf", inum);
startinum = 0;
- nextino = 0;
- lastinum = 0;
+ nextino = inum;
+ lastinum = inum;
readcnt = 0;
+ if (inodebuf != NULL)
+ return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / sizeof(struct dinode);
readpercg = sblock.fs_ipg / fullcnt;
@@ -342,11 +356,8 @@ resetinodebuf()
partialcnt = fullcnt;
partialsize = inobufsize;
}
- if (inodebuf == NULL &&
- (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
+ if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
- while (nextino < ROOTINO)
- (void)getnextinode(nextino);
}
void
@@ -380,14 +391,11 @@ cacheino(dp, inumber)
inp = (struct inoinfo *)
malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
if (inp == NULL)
- return;
+ errx(EEXIT, "cannot increase directory list");
inpp = &inphead[inumber % numdirs];
inp->i_nexthash = *inpp;
*inpp = inp;
- if (inumber == ROOTINO)
- inp->i_parent = ROOTINO;
- else
- inp->i_parent = (ino_t)0;
+ inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = dp->di_size;
@@ -465,7 +473,7 @@ clri(idesc, type, flag)
n_files--;
(void)ckinode(dp, idesc);
clearinode(dp);
- statemap[idesc->id_number] = USTATE;
+ inoinfo(idesc->id_number)->ino_state = USTATE;
inodirty();
}
}
@@ -476,8 +484,10 @@ findname(idesc)
{
register struct direct *dirp = idesc->id_dirp;
- if (dirp->d_ino != idesc->id_parent)
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
return (KEEPON);
+ }
memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
return (STOP|FOUND);
}
@@ -498,6 +508,20 @@ findino(idesc)
return (KEEPON);
}
+int
+clearentry(idesc)
+ struct inodesc *idesc;
+{
+ register struct direct *dirp = idesc->id_dirp;
+
+ if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
+ idesc->id_entryno++;
+ return (KEEPON);
+ }
+ dirp->d_ino = 0;
+ return (STOP|FOUND|ALTERED);
+}
+
void
pinode(ino)
ino_t ino;
@@ -534,14 +558,14 @@ blkerror(ino, type, blk)
pfatal("%ld %s I=%lu", blk, type, ino);
printf("\n");
- switch (statemap[ino]) {
+ switch (inoinfo(ino)->ino_state) {
case FSTATE:
- statemap[ino] = FCLEAR;
+ inoinfo(ino)->ino_state = FCLEAR;
return;
case DSTATE:
- statemap[ino] = DCLEAR;
+ inoinfo(ino)->ino_state = DCLEAR;
return;
case FCLEAR:
@@ -549,7 +573,7 @@ blkerror(ino, type, blk)
return;
default:
- errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]);
+ errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state);
/* NOTREACHED */
}
}
@@ -569,10 +593,10 @@ allocino(request, type)
if (request == 0)
request = ROOTINO;
- else if (statemap[request] != USTATE)
+ else if (inoinfo(request)->ino_state != USTATE)
return (0);
for (ino = request; ino < maxino; ino++)
- if (statemap[ino] == USTATE)
+ if (inoinfo(ino)->ino_state == USTATE)
break;
if (ino == maxino)
return (0);
@@ -584,12 +608,12 @@ allocino(request, type)
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
- statemap[ino] = DSTATE;
+ inoinfo(ino)->ino_state = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
- statemap[ino] = FSTATE;
+ inoinfo(ino)->ino_state = FSTATE;
break;
default:
return (0);
@@ -598,11 +622,11 @@ allocino(request, type)
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
return (0);
}
- dp->di_flags = 0;
dp->di_mode = type;
+ dp->di_flags = 0;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_size = sblock.fs_fsize;
@@ -610,7 +634,7 @@ allocino(request, type)
n_files++;
inodirty();
if (newinofmt)
- typemap[ino] = IFTODT(type);
+ inoinfo(ino)->ino_type = IFTODT(type);
return (ino);
}
@@ -632,6 +656,6 @@ freeino(ino)
(void)ckinode(dp, &idesc);
clearinode(dp);
inodirty();
- statemap[ino] = USTATE;
+ inoinfo(ino)->ino_state = USTATE;
n_files--;
}
diff --git a/sbin/fsck_ifs/main.c b/sbin/fsck_ifs/main.c
index 317015b..681ee6dc 100644
--- a/sbin/fsck_ifs/main.c
+++ b/sbin/fsck_ifs/main.c
@@ -38,11 +38,7 @@ static const char copyright[] =
#endif /* not lint */
#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
-#endif
-static const char rcsid[] =
- "$Id: main.c,v 1.14 1998/06/15 07:07:16 charnier Exp $";
+static const char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif /* not lint */
#include <sys/param.h>
@@ -56,11 +52,10 @@ static const char rcsid[] =
#include <err.h>
#include <fstab.h>
+#include <string.h>
#include "fsck.h"
-int returntosingle;
-
static int argtoi __P((int flag, char *req, char *str, int base));
static int docheck __P((struct fstab *fsp));
static int checkfilesys __P((char *filesys, char *mntpt, long auxdata,
@@ -74,12 +69,8 @@ main(argc, argv)
{
int ch;
int ret, maxrun = 0;
- struct rlimit rlim;
+ struct rlimit rlimit;
- if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
- rlim.rlim_cur = rlim.rlim_max;
- (void) setrlimit(RLIMIT_DATA, &rlim);
- }
sync();
while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != -1) {
switch (ch) {
@@ -137,9 +128,24 @@ main(argc, argv)
(void)signal(SIGINT, catch);
if (preen)
(void)signal(SIGQUIT, catchquit);
+ /*
+ * Push up our allowed memory limit so we can cope
+ * with huge filesystems.
+ */
+ if (getrlimit(RLIMIT_DATA, &rlimit) == 0) {
+ rlimit.rlim_cur = rlimit.rlim_max;
+ (void)setrlimit(RLIMIT_DATA, &rlimit);
+ }
if (argc) {
- while (argc-- > 0)
- (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
+ while (argc-- > 0) {
+ char *path = blockcheck(*argv);
+
+ if (path == NULL)
+ pfatal("Can't check %s\n", *argv);
+ else
+ (void)checkfilesys(path, 0, 0L, 0);
+ ++argv;
+ }
exit(0);
}
ret = checkfstab(preen, maxrun, docheck, checkfilesys);
@@ -203,16 +209,10 @@ checkfilesys(filesys, mntpt, auxdata, child)
case 0:
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
- return (0);
+ /* fall through */
case -1:
- pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree +
- sblock.fs_frag * sblock.fs_cstotal.cs_nbfree);
- printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
- sblock.fs_cstotal.cs_nffree, sblock.fs_cstotal.cs_nbfree,
- sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
return (0);
}
-
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
@@ -304,7 +304,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
muldup = (struct dups *)0;
inocleanup();
if (fsmodified) {
- (void)time(&sblock.fs_time);
+ sblock.fs_time = time(NULL);
sbdirty();
}
if (cvtlevel && sblk.b_dirty) {
@@ -329,12 +329,13 @@ checkfilesys(filesys, mntpt, auxdata, child)
resolved = 0;
}
ckfini(resolved);
- free(blockmap);
- free(statemap);
- free((char *)lncntp);
- if (!fsmodified)
- return (0);
- if (!preen)
+
+ for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
+ if (inostathead[cylno].il_stat != NULL)
+ free((char *)inostathead[cylno].il_stat);
+ free((char *)inostathead);
+ inostathead = NULL;
+ if (fsmodified && !preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
@@ -354,6 +355,8 @@ checkfilesys(filesys, mntpt, auxdata, child)
if (ret == 0)
return (0);
}
+ if (!fsmodified)
+ return (0);
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
diff --git a/sbin/fsck_ifs/pass1.c b/sbin/fsck_ifs/pass1.c
index 30c0e7d..1ce4471 100644
--- a/sbin/fsck_ifs/pass1.c
+++ b/sbin/fsck_ifs/pass1.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass1.c,v 1.11 1998/06/15 07:07:16 charnier Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -52,14 +49,17 @@ static const char rcsid[] =
static ufs_daddr_t badblk;
static ufs_daddr_t dupblk;
+static ino_t lastino; /* last inode in use */
static void checkinode __P((ino_t inumber, struct inodesc *));
void
pass1()
{
+ u_int8_t *cp;
ino_t inumber;
- int c, i, cgd;
+ int c, i, cgd, inosused;
+ struct inostat *info;
struct inodesc idesc;
/*
@@ -81,15 +81,84 @@ pass1()
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
- inumber = 0;
n_files = n_blks = 0;
- resetinodebuf();
for (c = 0; c < sblock.fs_ncg; c++) {
- for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
- if (inumber < ROOTINO)
+ inumber = c * sblock.fs_ipg;
+ setinodebuf(inumber);
+ inosused = sblock.fs_ipg;
+ /*
+ * If we are using soft updates, then we can trust the
+ * cylinder group inode allocation maps to tell us which
+ * inodes are allocated. We will scan the used inode map
+ * to find the inodes that are really in use, and then
+ * read only those inodes in from disk.
+ */
+ if (preen && usedsoftdep) {
+ getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
+ if (!cg_chkmagic(&cgrp))
+ pfatal("CG %d: BAD MAGIC NUMBER\n", c);
+ cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY];
+ for ( ; inosused > 0; inosused -= NBBY, cp--) {
+ if (*cp == 0)
+ continue;
+ for (i = 1 << (NBBY - 1); i > 0; i >>= 1) {
+ if (*cp & i)
+ break;
+ inosused--;
+ }
+ break;
+ }
+ if (inosused < 0)
+ inosused = 0;
+ }
+ /*
+ * Allocate inoinfo structures for the allocated inodes.
+ */
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ inostathead[c].il_stat = info;
+ /*
+ * Scan the allocated inodes.
+ */
+ for (i = 0; i < inosused; i++, inumber++) {
+ if (inumber < ROOTINO) {
+ (void)getnextinode(inumber);
continue;
+ }
checkinode(inumber, &idesc);
}
+ lastino += 1;
+ if (inosused < sblock.fs_ipg || inumber == lastino)
+ continue;
+ /*
+ * If we were not able to determine in advance which inodes
+ * were in use, then reduce the size of the inoinfo structure
+ * to the size necessary to describe the inodes that we
+ * really found.
+ */
+ inosused = lastino - (c * sblock.fs_ipg);
+ if (inosused < 0)
+ inosused = 0;
+ inostathead[c].il_numalloced = inosused;
+ if (inosused == 0) {
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = 0;
+ continue;
+ }
+ info = calloc((unsigned)inosused, sizeof(struct inostat));
+ if (info == NULL)
+ pfatal("cannot alloc %u bytes for inoinfo\n",
+ (unsigned)(sizeof(struct inostat) * inosused));
+ memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
+ free(inostathead[c].il_stat);
+ inostathead[c].il_stat = info;
}
freeinodebuf();
}
@@ -120,7 +189,7 @@ checkinode(inumber, idesc)
inodirty();
}
}
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
return;
}
lastino = inumber;
@@ -158,8 +227,7 @@ checkinode(inumber, idesc)
if (debug) {
symbuf[dp->di_size] = 0;
printf("convert symlink %lu(%s) of size %ld\n",
- (u_long)inumber, symbuf,
- (long)dp->di_size);
+ (u_long)inumber, symbuf, (long)dp->di_size);
}
dp = ginode(inumber);
memmove(dp->di_shortlink, symbuf, (long)dp->di_size);
@@ -170,8 +238,7 @@ checkinode(inumber, idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
- if (dp->di_size < sblock.fs_maxsymlinklen ||
- dp->di_blocks == 0) {
+ if (dp->di_size < sblock.fs_maxsymlinklen) {
ndb = howmany(dp->di_size, sizeof(ufs_daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
@@ -200,7 +267,7 @@ checkinode(inumber, idesc)
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
- lncntp[inumber] = dp->di_nlink;
+ inoinfo(inumber)->ino_linkcnt = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
@@ -217,13 +284,14 @@ checkinode(inumber, idesc)
}
if (mode == IFDIR) {
if (dp->di_size == 0)
- statemap[inumber] = DCLEAR;
+ inoinfo(inumber)->ino_state = DCLEAR;
else
- statemap[inumber] = DSTATE;
+ inoinfo(inumber)->ino_state = DSTATE;
cacheino(dp, inumber);
+ countdirs++;
} else
- statemap[inumber] = FSTATE;
- typemap[inumber] = IFTODT(mode);
+ inoinfo(inumber)->ino_state = FSTATE;
+ inoinfo(inumber)->ino_type = IFTODT(mode);
if (doinglevel2 &&
(dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) {
dp = ginode(inumber);
@@ -251,9 +319,9 @@ checkinode(inumber, idesc)
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
- statemap[inumber] = FCLEAR;
+ inoinfo(inumber)->ino_state = FCLEAR;
if (reply("CLEAR") == 1) {
- statemap[inumber] = USTATE;
+ inoinfo(inumber)->ino_state = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
diff --git a/sbin/fsck_ifs/pass1b.c b/sbin/fsck_ifs/pass1b.c
index 32a3be7..65ff49c 100644
--- a/sbin/fsck_ifs/pass1b.c
+++ b/sbin/fsck_ifs/pass1b.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass1b.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -72,7 +69,7 @@ pass1b()
if (dp == NULL)
continue;
idesc.id_number = inumber;
- if (statemap[inumber] != USTATE &&
+ if (inoinfo(inumber)->ino_state != USTATE &&
(ckinode(dp, &idesc) & STOP))
return;
}
diff --git a/sbin/fsck_ifs/pass2.c b/sbin/fsck_ifs/pass2.c
index 4c24b23..7a61d1d 100644
--- a/sbin/fsck_ifs/pass2.c
+++ b/sbin/fsck_ifs/pass2.c
@@ -32,17 +32,15 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -64,7 +62,7 @@ pass2()
struct dinode dino;
char pathbuf[MAXPATHLEN + 1];
- switch (statemap[ROOTINO]) {
+ switch (inoinfo(ROOTINO)->ino_state) {
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
@@ -113,12 +111,13 @@ pass2()
break;
default:
- errx(EEXIT, "BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
+ errx(EEXIT, "BAD STATE %d FOR ROOT INODE",
+ inoinfo(ROOTINO)->ino_state);
}
- statemap[ROOTINO] = DFOUND;
+ inoinfo(ROOTINO)->ino_state = DFOUND;
if (newinofmt) {
- statemap[WINO] = FSTATE;
- typemap[WINO] = DT_WHT;
+ inoinfo(WINO)->ino_state = FSTATE;
+ inoinfo(WINO)->ino_type = DT_WHT;
}
/*
* Sort the directory list into disk block order.
@@ -181,9 +180,9 @@ pass2()
inp = *inpp;
if (inp->i_parent == 0 || inp->i_isize == 0)
continue;
- if (statemap[inp->i_parent] == DFOUND &&
- statemap[inp->i_number] == DSTATE)
- statemap[inp->i_number] = DFOUND;
+ if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
+ inoinfo(inp->i_number)->ino_state == DSTATE)
+ inoinfo(inp->i_number)->ino_state = DFOUND;
if (inp->i_dotdot == inp->i_parent ||
inp->i_dotdot == (ino_t)-1)
continue;
@@ -193,15 +192,15 @@ pass2()
if (reply("FIX") == 0)
continue;
(void)makeentry(inp->i_number, inp->i_parent, "..");
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
- lncntp[inp->i_dotdot]++;
- lncntp[inp->i_parent]--;
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
+ inoinfo(inp->i_parent)->ino_linkcnt--;
inp->i_dotdot = inp->i_parent;
(void)changeino(inp->i_number, "..", inp->i_parent);
}
@@ -228,7 +227,7 @@ pass2check(idesc)
* If converting, set directory entry type.
*/
if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
ret |= ALTERED;
}
/*
@@ -284,7 +283,7 @@ pass2check(idesc)
proto.d_reclen = entrysize;
memmove(dirp, &proto, (size_t)entrysize);
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + entrysize);
memset(dirp, 0, (size_t)n);
dirp->d_reclen = n;
@@ -319,7 +318,7 @@ chk1:
proto.d_reclen = dirp->d_reclen - n;
dirp->d_reclen = n;
idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
dirp = (struct direct *)((char *)(dirp) + n);
memset(dirp, 0, (size_t)proto.d_reclen);
dirp->d_reclen = proto.d_reclen;
@@ -356,7 +355,7 @@ chk1:
}
idesc->id_entryno++;
if (dirp->d_ino != 0)
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
return (ret|KEEPON);
chk2:
if (dirp->d_ino == 0)
@@ -394,7 +393,7 @@ chk2:
ret |= ALTERED;
} else {
again:
- switch (statemap[dirp->d_ino]) {
+ switch (inoinfo(dirp->d_ino)->ino_state) {
case USTATE:
if (idesc->id_entryno <= 2)
break;
@@ -406,7 +405,7 @@ again:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
- if (statemap[dirp->d_ino] == FCLEAR)
+ if (inoinfo(dirp->d_ino)->ino_state == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
@@ -418,14 +417,14 @@ again:
if ((n = reply("REMOVE")) == 1)
break;
dp = ginode(dirp->d_ino);
- statemap[dirp->d_ino] =
+ inoinfo(dirp->d_ino)->ino_state =
(dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
- lncntp[dirp->d_ino] = dp->di_nlink;
+ inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink;
goto again;
case DSTATE:
- if (statemap[idesc->id_number] == DFOUND)
- statemap[dirp->d_ino] = DFOUND;
+ if (inoinfo(idesc->id_number)->ino_state == DFOUND)
+ inoinfo(dirp->d_ino)->ino_state = DFOUND;
/* fall through */
case DFOUND:
@@ -439,10 +438,10 @@ again:
namebuf);
if (preen) {
printf(" (REMOVED)\n");
- n = 1;
- break;
+ n = 1;
+ break;
}
- else if ((n = reply("REMOVE")) == 1)
+ if ((n = reply("REMOVE")) == 1)
break;
}
if (idesc->id_entryno > 2)
@@ -450,19 +449,20 @@ again:
/* fall through */
case FSTATE:
- if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
+ if (newinofmt &&
+ dirp->d_type != inoinfo(dirp->d_ino)->ino_type) {
fileerror(idesc->id_number, dirp->d_ino,
"BAD TYPE VALUE");
- dirp->d_type = typemap[dirp->d_ino];
+ dirp->d_type = inoinfo(dirp->d_ino)->ino_type;
if (reply("FIX") == 1)
ret |= ALTERED;
}
- lncntp[dirp->d_ino]--;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
break;
default:
errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[dirp->d_ino], dirp->d_ino);
+ inoinfo(dirp->d_ino)->ino_state, dirp->d_ino);
}
}
if (n == 0)
diff --git a/sbin/fsck_ifs/pass3.c b/sbin/fsck_ifs/pass3.c
index 6524a11..6320755 100644
--- a/sbin/fsck_ifs/pass3.c
+++ b/sbin/fsck_ifs/pass3.c
@@ -32,45 +32,84 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass3.c 8.2 (Berkeley) 4/27/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+
+#include <string.h>
#include "fsck.h"
void
pass3()
{
- register struct inoinfo **inpp, *inp;
+ struct inoinfo *inp;
+ int loopcnt, inpindex, state;
ino_t orphan;
- int loopcnt;
+ struct inodesc idesc;
+ char namebuf[MAXNAMLEN+1];
- for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
- inp = *inpp;
+ for (inpindex = inplast - 1; inpindex >= 0; inpindex--) {
+ inp = inpsort[inpindex];
+ state = inoinfo(inp->i_number)->ino_state;
if (inp->i_number == ROOTINO ||
- !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
+ (inp->i_parent != 0 && state != DSTATE))
+ continue;
+ if (state == DCLEAR)
continue;
- if (statemap[inp->i_number] == DCLEAR)
+ /*
+ * If we are running with soft updates and we come
+ * across unreferenced directories, we just leave
+ * them in DSTATE which will cause them to be pitched
+ * in pass 4.
+ */
+ if (preen && resolved && usedsoftdep && state == DSTATE) {
+ if (inp->i_dotdot >= ROOTINO)
+ inoinfo(inp->i_dotdot)->ino_linkcnt++;
continue;
+ }
for (loopcnt = 0; ; loopcnt++) {
orphan = inp->i_number;
if (inp->i_parent == 0 ||
- statemap[inp->i_parent] != DSTATE ||
- loopcnt > numdirs)
+ inoinfo(inp->i_parent)->ino_state != DSTATE ||
+ loopcnt > countdirs)
break;
inp = getinoinfo(inp->i_parent);
}
- (void)linkup(orphan, inp->i_dotdot);
- inp->i_parent = inp->i_dotdot = lfdir;
- lncntp[lfdir]--;
- statemap[orphan] = DFOUND;
+ if (loopcnt <= countdirs) {
+ if (linkup(orphan, inp->i_dotdot, NULL)) {
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
+ propagate();
+ continue;
+ }
+ pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu", orphan);
+ if (reply("RECONNECT") == 0)
+ continue;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = DATA;
+ idesc.id_number = inp->i_parent;
+ idesc.id_parent = orphan;
+ idesc.id_func = findname;
+ idesc.id_name = namebuf;
+ if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0)
+ pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
+ if (linkup(orphan, inp->i_parent, namebuf)) {
+ idesc.id_func = clearentry;
+ if (ckinode(ginode(inp->i_parent), &idesc) & FOUND)
+ inoinfo(orphan)->ino_linkcnt++;
+ inp->i_parent = inp->i_dotdot = lfdir;
+ inoinfo(lfdir)->ino_linkcnt--;
+ }
+ inoinfo(orphan)->ino_state = DFOUND;
propagate();
}
}
diff --git a/sbin/fsck_ifs/pass4.c b/sbin/fsck_ifs/pass4.c
index b2f1fe9..48c5090 100644
--- a/sbin/fsck_ifs/pass4.c
+++ b/sbin/fsck_ifs/pass4.c
@@ -32,16 +32,14 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <string.h>
@@ -55,22 +53,27 @@ pass4()
register struct zlncnt *zlnp;
struct dinode *dp;
struct inodesc idesc;
- int n;
+ int i, n, cg;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass4check;
- for (inumber = ROOTINO; inumber <= lastino; inumber++) {
- idesc.id_number = inumber;
- switch (statemap[inumber]) {
+ for (cg = 0; cg < sblock.fs_ncg; cg++) {
+ inumber = cg * sblock.fs_ipg;
+ for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) {
+ if (inumber < ROOTINO)
+ continue;
+ idesc.id_number = inumber;
+ switch (inoinfo(inumber)->ino_state) {
- case FSTATE:
- case DFOUND:
- n = lncntp[inumber];
- if (n)
- adjust(&idesc, (short)n);
- else {
- for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
+ case FSTATE:
+ case DFOUND:
+ n = inoinfo(inumber)->ino_linkcnt;
+ if (n) {
+ adjust(&idesc, (short)n);
+ break;
+ }
+ for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
if (zlnp->zlncnt == inumber) {
zlnp->zlncnt = zlnhead->zlncnt;
zlnp = zlnhead;
@@ -79,30 +82,31 @@ pass4()
clri(&idesc, "UNREF", 1);
break;
}
- }
- break;
+ }
+ break;
- case DSTATE:
- clri(&idesc, "UNREF", 1);
- break;
+ case DSTATE:
+ clri(&idesc, "UNREF", 1);
+ break;
- case DCLEAR:
- dp = ginode(inumber);
- if (dp->di_size == 0) {
- clri(&idesc, "ZERO LENGTH", 1);
+ case DCLEAR:
+ dp = ginode(inumber);
+ if (dp->di_size == 0) {
+ clri(&idesc, "ZERO LENGTH", 1);
+ break;
+ }
+ /* fall through */
+ case FCLEAR:
+ clri(&idesc, "BAD/DUP", 1);
break;
- }
- /* fall through */
- case FCLEAR:
- clri(&idesc, "BAD/DUP", 1);
- break;
- case USTATE:
- break;
+ case USTATE:
+ break;
- default:
- errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
- statemap[inumber], inumber);
+ default:
+ errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
+ inoinfo(inumber)->ino_state, inumber);
+ }
}
}
}
diff --git a/sbin/fsck_ifs/pass5.c b/sbin/fsck_ifs/pass5.c
index f3994f8..d492a18 100644
--- a/sbin/fsck_ifs/pass5.c
+++ b/sbin/fsck_ifs/pass5.c
@@ -32,14 +32,11 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id: pass5.c,v 1.13 1998/08/04 09:19:03 phk Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -52,7 +49,7 @@ static const char rcsid[] =
void
pass5()
{
- int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
+ int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
@@ -66,7 +63,7 @@ pass5()
register struct cg *newcg = (struct cg *)buf;
struct ocg *ocg = (struct ocg *)buf;
- statemap[WINO] = USTATE;
+ inoinfo(WINO)->ino_state = USTATE;
memset(newcg, 0, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
if (cvtlevel >= 3) {
@@ -207,8 +204,8 @@ pass5()
if (fs->fs_postblformat == FS_42POSTBLFMT)
ocg->cg_magic = CG_MAGIC;
j = fs->fs_ipg * c;
- for (i = 0; i < fs->fs_ipg; j++, i++) {
- switch (statemap[j]) {
+ for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
+ switch (inoinfo(j)->ino_state) {
case USTATE:
break;
@@ -229,7 +226,7 @@ pass5()
if (j < ROOTINO)
break;
errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
- statemap[j], j);
+ inoinfo(j)->ino_state, j);
}
}
if (c == 0)
@@ -325,7 +322,7 @@ pass5()
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE\n",
- c * fs->fs_ipg + i * 8 + k);
+ c * fs->fs_ipg + i * NBBY + k);
}
}
for (i = 0; i < blkmapsize; i++) {
@@ -338,7 +335,7 @@ pass5()
if (cg_blksfree(newcg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE\n",
- c * fs->fs_fpg + i * 8 + k);
+ c * fs->fs_fpg + i * NBBY + k);
}
}
}
@@ -355,24 +352,7 @@ pass5()
&& dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
fs->fs_ronly = 0;
+ fs->fs_fmod = 0;
sbdirty();
}
- if (fs->fs_fmod != 0) {
- pwarn("MODIFIED FLAG SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_fmod = 0;
- sbdirty();
- }
- }
- if (fs->fs_clean == 0) {
- pwarn("CLEAN FLAG NOT SET IN SUPERBLOCK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- fs->fs_clean = 1;
- sbdirty();
- }
- }
}
diff --git a/sbin/fsck_ifs/preen.c b/sbin/fsck_ifs/preen.c
index 9705aee..ba0140b 100644
--- a/sbin/fsck_ifs/preen.c
+++ b/sbin/fsck_ifs/preen.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
@@ -46,7 +42,7 @@ static const char rcsid[] =
#include <ufs/ufs/dinode.h>
#include <ctype.h>
-#include <err.h>
+#include <errno.h>
#include <fstab.h>
#include <string.h>
@@ -93,7 +89,8 @@ checkfstab(preen, maxrun, docheck, chkit)
sumstatus = 0;
for (passno = 1; passno <= 2; passno++) {
if (setfsent() == 0) {
- warnx("can't open checklist file: %s", _PATH_FSTAB);
+ fprintf(stderr, "Can't open checklist file: %s\n",
+ _PATH_FSTAB);
return (8);
}
while ((fsp = getfsent()) != 0) {
@@ -222,11 +219,15 @@ finddisk(name)
dk->name[len] == 0)
return (dk);
}
- if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
- errx(8, "out of memory");
+ if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
dk = *dkp;
- if ((dk->name = malloc(len + 1)) == NULL)
- errx(8, "out of memory");
+ if ((dk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strncpy(dk->name, name, len);
dk->name[len] = '\0';
dk->part = NULL;
@@ -249,14 +250,20 @@ addpart(name, fsname, auxdata)
printf("%s in fstab more than once!\n", name);
return;
}
- if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
- errx(8, "out of memory");
+ if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
pt = *ppt;
- if ((pt->name = malloc(strlen(name) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->name, name);
- if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->fsname, fsname);
pt->next = NULL;
pt->auxdata = auxdata;
@@ -271,7 +278,7 @@ startdisk(dk, checkit)
dk->pid = fork();
if (dk->pid < 0) {
- warn("fork");
+ perror("fork");
return (8);
}
if (dk->pid == 0)
@@ -287,19 +294,17 @@ blockcheck(origname)
struct stat stslash, stblock, stchar;
char *newname, *raw;
struct fstab *fsinfo;
- int retried = 0, l;
+ int retried = 0, len;
hotroot = 0;
if (stat("/", &stslash) < 0) {
- warn("/");
- printf("Can't stat root\n");
+ printf("Can't stat /: %s\n", strerror(errno));
return (origname);
}
newname = origname;
retry:
if (stat(newname, &stblock) < 0) {
- warn("%s", newname);
- printf("Can't stat %s\n", newname);
+ printf("Can't stat %s: %s\n", newname, strerror(errno));
return (origname);
}
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
@@ -307,8 +312,7 @@ retry:
hotroot++;
raw = rawname(newname);
if (stat(raw, &stchar) < 0) {
- warn("%s", raw);
- printf("Can't stat %s\n", raw);
+ printf("Can't stat %s: %s\n", raw, strerror(errno));
return (origname);
}
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
@@ -318,15 +322,15 @@ retry:
return (origname);
}
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
- newname = unrawname(origname);
+ newname = unrawname(newname);
retried++;
goto retry;
} else if ((stblock.st_mode & S_IFMT) == S_IFDIR && !retried) {
- l = strlen(origname) - 1;
- if (l > 0 && origname[l] == '/')
+ len = strlen(origname) - 1;
+ if (len > 0 && origname[len] == '/')
/* remove trailing slash */
- origname[l] = '\0';
- if(!(fsinfo=getfsfile(origname))) {
+ origname[len] = '\0';
+ if ((fsinfo = getfsfile(origname)) == NULL) {
printf("Can't resolve %s to character special device",
origname);
return (0);
diff --git a/sbin/fsck_ifs/setup.c b/sbin/fsck_ifs/setup.c
index 25dab92..5a842f4 100644
--- a/sbin/fsck_ifs/setup.c
+++ b/sbin/fsck_ifs/setup.c
@@ -32,16 +32,13 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
-#endif
-static const char rcsid[] =
- "$Id: setup.c,v 1.11 1998/06/15 07:07:21 charnier Exp $";
#endif /* not lint */
#define DKTYPENAMES
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
@@ -82,7 +79,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
- skipclean = preen;
+ skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
@@ -114,8 +111,7 @@ setup(dev)
asblk.b_un.b_buf = malloc(SBSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
- lp = getdisklabel((char *)NULL, fsreadfd);
- if (lp)
+ if ((lp = getdisklabel(NULL, fsreadfd)))
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
@@ -147,6 +143,10 @@ setup(dev)
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
bflag = 0;
}
+ if (skipclean && sblock.fs_clean) {
+ pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
+ return (-1);
+ }
maxfsblock = sblock.fs_size;
maxino = sblock.fs_ncg * sblock.fs_ipg;
/*
@@ -265,12 +265,6 @@ setup(dev)
}
}
/*
- * If we survive the above basic checks and are preening,
- * quit here unless forced.
- */
- if (skipclean && sblock.fs_clean && !fflag)
- return (-1);
- /*
* allocate and initialize the necessary maps
*/
bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short));
@@ -280,22 +274,11 @@ setup(dev)
(unsigned)bmapsize);
goto badsb;
}
- statemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (statemap == NULL) {
- printf("cannot alloc %u bytes for statemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- typemap = calloc((unsigned)(maxino + 1), sizeof(char));
- if (typemap == NULL) {
- printf("cannot alloc %u bytes for typemap\n",
- (unsigned)(maxino + 1));
- goto badsb;
- }
- lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
- if (lncntp == NULL) {
- printf("cannot alloc %u bytes for lncntp\n",
- (unsigned)(maxino + 1) * sizeof(short));
+ inostathead = calloc((unsigned)(sblock.fs_ncg),
+ sizeof(struct inostatlist));
+ if (inostathead == NULL) {
+ printf("cannot alloc %u bytes for inostathead\n",
+ (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg)));
goto badsb;
}
numdirs = sblock.fs_cstotal.cs_ndir;
@@ -474,9 +457,11 @@ calcsb(dev, devfd, fs)
fstypenames[pp->p_fstype] : "unknown");
return (0);
}
- if (pp->p_fsize == 0 || pp->p_frag == 0) {
- pfatal("%s: LABELED AS A %s FILE SYSTEM, BUT BLOCK SIZE IS 0\n",
- dev, fstypenames[pp->p_fstype]);
+ if (pp->p_fsize == 0 || pp->p_frag == 0 ||
+ pp->p_cpg == 0 || pp->p_size == 0) {
+ pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n",
+ dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype],
+ pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size);
return (0);
}
memset(fs, 0, sizeof(struct fs));
diff --git a/sbin/fsck_ifs/utilities.c b/sbin/fsck_ifs/utilities.c
index 0d82d6e..5ea02b6 100644
--- a/sbin/fsck_ifs/utilities.c
+++ b/sbin/fsck_ifs/utilities.c
@@ -32,20 +32,16 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
-#include <ctype.h>
#include <err.h>
#include <string.h>
@@ -116,6 +112,26 @@ reply(question)
}
/*
+ * Look up state information for an inode.
+ */
+struct inostat *
+inoinfo(inum)
+ ino_t inum;
+{
+ static struct inostat unallocated = { USTATE, 0, 0 };
+ struct inostatlist *ilp;
+ int iloff;
+
+ if (inum > maxino)
+ errx(EEXIT, "inoinfo: inumber %d out of range", inum);
+ ilp = &inostathead[inum / sblock.fs_ipg];
+ iloff = inum % sblock.fs_ipg;
+ if (iloff >= ilp->il_numalloced)
+ return (&unallocated);
+ return (&ilp->il_stat[iloff]);
+}
+
+/*
* Malloc buffers and set up cache.
*/
void
@@ -270,16 +286,23 @@ ckfini(markclean)
free((char *)bp);
}
if (bufhead.b_size != cnt)
- errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt);
+ errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt);
pbp = pdirbp = (struct bufarea *)0;
- if (markclean && sblock.fs_clean == 0) {
- sblock.fs_clean = 1;
+ if (sblock.fs_clean != markclean) {
+ sblock.fs_clean = markclean;
sbdirty();
ofsmodified = fsmodified;
flush(fswritefd, &sblk);
fsmodified = ofsmodified;
- if (!preen)
- printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
+ if (!preen) {
+ printf("\n***** FILE SYSTEM MARKED %s *****\n",
+ markclean ? "CLEAN" : "DIRTY");
+ if (!markclean)
+ rerun = 1;
+ }
+ } else if (!preen && !markclean) {
+ printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
+ rerun = 1;
}
if (debug)
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
@@ -324,6 +347,8 @@ bread(fd, buf, blk, size)
}
}
printf("\n");
+ if (errs)
+ resolved = 0;
return (errs);
}
@@ -348,6 +373,7 @@ bwrite(fd, buf, blk, size)
fsmodified = 1;
return;
}
+ resolved = 0;
rwerror("WRITE", blk);
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
@@ -438,7 +464,8 @@ getpathname(namebuf, curdir, ino)
return;
}
if (busy ||
- (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
+ (inoinfo(curdir)->ino_state != DSTATE &&
+ inoinfo(curdir)->ino_state != DFOUND)) {
(void)strcpy(namebuf, "?");
return;
}
@@ -497,6 +524,7 @@ void
catchquit(sig)
int sig;
{
+
printf("returning to single-user after filesystem check\n");
returntosingle = 1;
(void)signal(SIGQUIT, SIG_DFL);
@@ -589,14 +617,16 @@ pfatal(fmt, va_alist)
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
- "\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
+ "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n");
return;
}
+ if (cdevname == NULL)
+ cdevname = "fsck";
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
- cdevname, usedsoftdep ? " SOFTDEP " : " ");
+ cdevname, usedsoftdep ? " SOFT UPDATE " : " ");
ckfini(0);
exit(EEXIT);
}
diff --git a/sbin/quotacheck/preen.c b/sbin/quotacheck/preen.c
index 9705aee..ba0140b 100644
--- a/sbin/quotacheck/preen.c
+++ b/sbin/quotacheck/preen.c
@@ -32,11 +32,7 @@
*/
#ifndef lint
-#if 0
static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$Id$";
#endif /* not lint */
#include <sys/param.h>
@@ -46,7 +42,7 @@ static const char rcsid[] =
#include <ufs/ufs/dinode.h>
#include <ctype.h>
-#include <err.h>
+#include <errno.h>
#include <fstab.h>
#include <string.h>
@@ -93,7 +89,8 @@ checkfstab(preen, maxrun, docheck, chkit)
sumstatus = 0;
for (passno = 1; passno <= 2; passno++) {
if (setfsent() == 0) {
- warnx("can't open checklist file: %s", _PATH_FSTAB);
+ fprintf(stderr, "Can't open checklist file: %s\n",
+ _PATH_FSTAB);
return (8);
}
while ((fsp = getfsent()) != 0) {
@@ -222,11 +219,15 @@ finddisk(name)
dk->name[len] == 0)
return (dk);
}
- if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
- errx(8, "out of memory");
+ if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
dk = *dkp;
- if ((dk->name = malloc(len + 1)) == NULL)
- errx(8, "out of memory");
+ if ((dk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strncpy(dk->name, name, len);
dk->name[len] = '\0';
dk->part = NULL;
@@ -249,14 +250,20 @@ addpart(name, fsname, auxdata)
printf("%s in fstab more than once!\n", name);
return;
}
- if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
- errx(8, "out of memory");
+ if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
pt = *ppt;
- if ((pt->name = malloc(strlen(name) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->name, name);
- if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL)
- errx(8, "out of memory");
+ if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
(void)strcpy(pt->fsname, fsname);
pt->next = NULL;
pt->auxdata = auxdata;
@@ -271,7 +278,7 @@ startdisk(dk, checkit)
dk->pid = fork();
if (dk->pid < 0) {
- warn("fork");
+ perror("fork");
return (8);
}
if (dk->pid == 0)
@@ -287,19 +294,17 @@ blockcheck(origname)
struct stat stslash, stblock, stchar;
char *newname, *raw;
struct fstab *fsinfo;
- int retried = 0, l;
+ int retried = 0, len;
hotroot = 0;
if (stat("/", &stslash) < 0) {
- warn("/");
- printf("Can't stat root\n");
+ printf("Can't stat /: %s\n", strerror(errno));
return (origname);
}
newname = origname;
retry:
if (stat(newname, &stblock) < 0) {
- warn("%s", newname);
- printf("Can't stat %s\n", newname);
+ printf("Can't stat %s: %s\n", newname, strerror(errno));
return (origname);
}
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
@@ -307,8 +312,7 @@ retry:
hotroot++;
raw = rawname(newname);
if (stat(raw, &stchar) < 0) {
- warn("%s", raw);
- printf("Can't stat %s\n", raw);
+ printf("Can't stat %s: %s\n", raw, strerror(errno));
return (origname);
}
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
@@ -318,15 +322,15 @@ retry:
return (origname);
}
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
- newname = unrawname(origname);
+ newname = unrawname(newname);
retried++;
goto retry;
} else if ((stblock.st_mode & S_IFMT) == S_IFDIR && !retried) {
- l = strlen(origname) - 1;
- if (l > 0 && origname[l] == '/')
+ len = strlen(origname) - 1;
+ if (len > 0 && origname[len] == '/')
/* remove trailing slash */
- origname[l] = '\0';
- if(!(fsinfo=getfsfile(origname))) {
+ origname[len] = '\0';
+ if ((fsinfo = getfsfile(origname)) == NULL) {
printf("Can't resolve %s to character special device",
origname);
return (0);
OpenPOWER on IntegriCloud