summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/pass1.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/fsck_ffs/pass1.c')
-rw-r--r--sbin/fsck_ffs/pass1.c110
1 files changed, 89 insertions, 21 deletions
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();
OpenPOWER on IntegriCloud