summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/pass1.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2009-02-04 01:02:56 +0000
committermckusick <mckusick@FreeBSD.org>2009-02-04 01:02:56 +0000
commit174c989fd92913f6e372eb9f2731d0cc8053a676 (patch)
tree5e316590ff535c59da8f548fe219c5c6d8d14fac /sbin/fsck_ffs/pass1.c
parenta142097876818fa2a5871c6b7b4195c2a40a67c3 (diff)
downloadFreeBSD-src-174c989fd92913f6e372eb9f2731d0cc8053a676.zip
FreeBSD-src-174c989fd92913f6e372eb9f2731d0cc8053a676.tar.gz
Update the actions previously attempted by the -D option to make them
robust. With these changes fsck is now able to detect and reliably rebuild corrupted cylinder group maps. The -D option is no longer necessary as it has been replaced by a prompt asking whether the corrupted cylinder group should be rebuilt and doing so when requested. These actions are only offered and taken when running fsck in manual mode. Corrupted cylinder groups found during preen mode cause the fsck to fail. Add the -r option to free up excess unused inodes. Decreasing the number of preallocated inodes reduces the running time of future runs of fsck and frees up space that can allocated to files. The -r option is ignored when running in preen mode. Reviewed by: Xin LI <delphij@> Sponsored by: Rsync.net
Diffstat (limited to 'sbin/fsck_ffs/pass1.c')
-rw-r--r--sbin/fsck_ffs/pass1.c81
1 files changed, 60 insertions, 21 deletions
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 9bfc95d..73b6419 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -54,17 +54,17 @@ static ufs2_daddr_t badblk;
static ufs2_daddr_t dupblk;
static ino_t lastino; /* last inode in use */
-static void checkinode(ino_t inumber, struct inodesc *);
+static int checkinode(ino_t inumber, struct inodesc *, int rebuildcg);
void
pass1(void)
{
struct inostat *info;
struct inodesc idesc;
- ino_t inumber, inosused;
+ ino_t inumber, inosused, mininos;
ufs2_daddr_t i, cgd;
u_int8_t *cp;
- int c;
+ int c, rebuildcg;
/*
* Set file system reserved blocks in used block map.
@@ -93,7 +93,10 @@ pass1(void)
inumber = c * sblock.fs_ipg;
setinodebuf(inumber);
getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
- if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ rebuildcg = 0;
+ if (!check_cgmagic(c, &cgrp))
+ rebuildcg = 1;
+ if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
inosused = cgrp.cg_initediblk;
if (inosused > sblock.fs_ipg)
inosused = sblock.fs_ipg;
@@ -117,9 +120,7 @@ pass1(void)
* to find the inodes that are really in use, and then
* read only those inodes in from disk.
*/
- if (preen && usedsoftdep) {
- if (!cg_chkmagic(&cgrp))
- pfatal("CG %d: BAD MAGIC NUMBER\n", c);
+ if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
cp = &cg_inosused(&cgrp)[(inosused - 1) / CHAR_BIT];
for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
if (*cp == 0)
@@ -152,24 +153,60 @@ pass1(void)
*/
for (i = 0; i < inosused; i++, inumber++) {
if (inumber < ROOTINO) {
- (void)getnextinode(inumber);
+ (void)getnextinode(inumber, rebuildcg);
continue;
}
- checkinode(inumber, &idesc);
+ /*
+ * NULL return indicates probable end of allocated
+ * inodes during cylinder group rebuild attempt.
+ * We always keep trying until we get to the minimum
+ * valid number for this cylinder group.
+ */
+ if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
+ i > cgrp.cg_initediblk)
+ break;
}
- lastino += 1;
- if (inosused < sblock.fs_ipg || inumber == lastino)
+ /*
+ * This optimization speeds up future runs of fsck
+ * by trimming down the number of inodes in cylinder
+ * groups that formerly had many inodes but now have
+ * fewer in use.
+ */
+ mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
+ if (inoopt && !preen && !rebuildcg &&
+ sblock.fs_magic == FS_UFS2_MAGIC &&
+ cgrp.cg_initediblk > 2 * INOPB(&sblock) &&
+ mininos < cgrp.cg_initediblk) {
+ i = cgrp.cg_initediblk;
+ if (mininos < 2 * INOPB(&sblock))
+ cgrp.cg_initediblk = 2 * INOPB(&sblock);
+ else
+ cgrp.cg_initediblk = mininos;
+ pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n",
+ c, i, cgrp.cg_initediblk, "VALID INODES");
+ cgdirty();
+ }
+ if (inosused < sblock.fs_ipg)
continue;
+ lastino += 1;
+ if (lastino < (c * sblock.fs_ipg))
+ inosused = 0;
+ else
+ inosused = lastino - (c * sblock.fs_ipg);
+ if (rebuildcg && inosused > cgrp.cg_initediblk &&
+ sblock.fs_magic == FS_UFS2_MAGIC) {
+ cgrp.cg_initediblk = roundup(inosused, INOPB(&sblock));
+ pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
+ cgrp.cg_initediblk);
+ }
/*
* 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.
*/
- if (lastino < (c * sblock.fs_ipg))
- inosused = 0;
- else
- inosused = lastino - (c * sblock.fs_ipg);
+ if (inumber == lastino)
+ continue;
inostathead[c].il_numalloced = inosused;
if (inosused == 0) {
free(inostathead[c].il_stat);
@@ -187,8 +224,8 @@ pass1(void)
freeinodebuf();
}
-static void
-checkinode(ino_t inumber, struct inodesc *idesc)
+static int
+checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
{
union dinode *dp;
off_t kernmaxfilesize;
@@ -196,7 +233,8 @@ checkinode(ino_t inumber, struct inodesc *idesc)
mode_t mode;
int j, ret, offset;
- dp = getnextinode(inumber);
+ if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
+ return (0);
mode = DIP(dp, di_mode) & IFMT;
if (mode == 0) {
if ((sblock.fs_magic == FS_UFS1_MAGIC &&
@@ -220,7 +258,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
inoinfo(inumber)->ino_state = USTATE;
- return;
+ return (1);
}
lastino = inumber;
/* This should match the file size limit in ffs_mountfs(). */
@@ -352,7 +390,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
- return;
+ return (1);
if (bkgrdflag == 0) {
dp = ginode(inumber);
DIP_SET(dp, di_blocks, idesc->id_entryno);
@@ -368,7 +406,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
}
}
- return;
+ return (1);
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber);
inoinfo(inumber)->ino_state = FCLEAR;
@@ -378,6 +416,7 @@ unknown:
clearinode(dp);
inodirty();
}
+ return (1);
}
int
OpenPOWER on IntegriCloud