mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Skip Pass 5 in fsck_ffs(8) when corrupt cylinder groups remain unfixed.
Pass 1 of fsck_ffs checks the integrity of all the cylinder groups. If any are found to have been corrupted it offers to rebuild them. Pass 5 then makes a second pass over the cylinder groups to validate their block and inode maps. Pass 5 assumes that the cylinder groups are not corrupted and can segment fault if they are corrupted. Rather than rerunning the corruption checks a second time in pass 5, this fix keeps track whether any corrupt cylinder groups were found but not fixed in pass 1 either due to running with the -n flag or by explicitly answering `no' when asked whether to fix a corrupted cylinder group. If any corrupted cylinder groups remain after pass 1, fsck_ffs will decline to run pass 5. Instead it marks the filesystem as unclean so that fsck_ffs will need to be run again before the filesystem can be mounted. This patch cleans up and documents the return value from check_cgmagic(). It also renames the variable / parameter "rebuildcg" to "rebuiltcg". This parameter describes whether the cylinder group has been rebuilt rather than whether it should be rebuilt. Reported by: Chuck Silvers Reviewed by: Chuck Silvers MFC after: 1 week
This commit is contained in:
parent
18746531a8
commit
da86e7a20d
6 changed files with 36 additions and 20 deletions
|
|
@ -346,6 +346,7 @@ extern off_t bflag; /* location of alternate super block */
|
|||
extern int bkgrdflag; /* use a snapshot to run on an active system */
|
||||
extern char *blockmap; /* ptr to primary blk allocation map */
|
||||
extern char *cdevname; /* name of device being checked */
|
||||
extern int cgheader_corrupt; /* one or more CG headers are corrupt */
|
||||
extern char ckclean; /* only do work if not cleanly unmounted */
|
||||
extern int ckhashadd; /* check hashes to be added */
|
||||
extern char *copybuf; /* buffer to copy snapshot blocks */
|
||||
|
|
@ -493,7 +494,7 @@ int ftypeok(union dinode *dp);
|
|||
void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
|
||||
struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type);
|
||||
struct inoinfo *getinoinfo(ino_t inumber);
|
||||
union dinode *getnextinode(ino_t inumber, int rebuildcg);
|
||||
union dinode *getnextinode(ino_t inumber, int rebuiltcg);
|
||||
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
|
||||
void ginode(ino_t, struct inode *);
|
||||
void gjournal_check(const char *filesys);
|
||||
|
|
|
|||
|
|
@ -988,6 +988,10 @@ blzero(int fd, ufs2_daddr_t blk, long size)
|
|||
/*
|
||||
* Verify cylinder group's magic number and other parameters. If the
|
||||
* test fails, offer an option to rebuild the whole cylinder group.
|
||||
*
|
||||
* Return 1 if the cylinder group is good or if repair is requested
|
||||
* and is completed successfully. Return 0 if it is bad or if a repair
|
||||
* has been requested but is not completed successfully.
|
||||
*/
|
||||
#undef CHK
|
||||
#define CHK(lhs, op, rhs, fmt) \
|
||||
|
|
@ -1080,7 +1084,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
|
|||
if (!reply("REBUILD CYLINDER GROUP")) {
|
||||
printf("YOU WILL NEED TO RERUN FSCK.\n");
|
||||
rerun = 1;
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Zero out the cylinder group and then initialize critical fields.
|
||||
|
|
@ -1123,7 +1127,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
|
|||
}
|
||||
cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
|
||||
cgdirty(cgbp);
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ ino_t lfdir; /* lost & found directory inode number */
|
|||
const char *lfname; /* lost & found directory name */
|
||||
int lfmode; /* lost & found directory creation mode */
|
||||
ufs2_daddr_t n_blks; /* number of blocks in use */
|
||||
int cgheader_corrupt; /* one or more CG headers are corrupt */
|
||||
ino_t n_files; /* number of files in use */
|
||||
volatile sig_atomic_t got_siginfo; /* received a SIGINFO */
|
||||
volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */
|
||||
|
|
@ -164,6 +165,7 @@ fsckinit(void)
|
|||
lfmode = 0700;
|
||||
n_blks = 0;
|
||||
n_files = 0;
|
||||
cgheader_corrupt = 0;
|
||||
got_siginfo = 0;
|
||||
got_sigalarm = 0;
|
||||
bzero(&zino.dp1, sizeof(struct ufs1_dinode));
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ static ino_t nextinum, lastvalidinum;
|
|||
static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
|
||||
|
||||
union dinode *
|
||||
getnextinode(ino_t inumber, int rebuildcg)
|
||||
getnextinode(ino_t inumber, int rebuiltcg)
|
||||
{
|
||||
int j;
|
||||
long size;
|
||||
|
|
@ -569,7 +569,7 @@ getnextinode(ino_t inumber, int rebuildcg)
|
|||
dirty(&inobuf);
|
||||
}
|
||||
}
|
||||
if (rebuildcg && (char *)dp == inobuf.b_un.b_buf) {
|
||||
if (rebuiltcg && (char *)dp == inobuf.b_un.b_buf) {
|
||||
/*
|
||||
* Try to determine if we have reached the end of the
|
||||
* allocated inodes.
|
||||
|
|
|
|||
|
|
@ -490,8 +490,13 @@ checkfilesys(char *filesys)
|
|||
if (preen == 0)
|
||||
printf("** Phase 5 - Check Cyl groups\n");
|
||||
snapflush(std_checkblkavail);
|
||||
pass5();
|
||||
IOstats("Pass5");
|
||||
if (cgheader_corrupt) {
|
||||
printf("PHASE 5 SKIPPED DUE TO CORRUPT CYLINDER GROUP "
|
||||
"HEADER(S)\n");
|
||||
} else {
|
||||
pass5();
|
||||
IOstats("Pass5");
|
||||
}
|
||||
|
||||
/*
|
||||
* print out summary statistics
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ static ufs2_daddr_t badblk;
|
|||
static ufs2_daddr_t dupblk;
|
||||
static ino_t lastino; /* last inode in use */
|
||||
|
||||
static int checkinode(ino_t inumber, struct inodesc *, int rebuildcg);
|
||||
static int checkinode(ino_t inumber, struct inodesc *, int rebuiltcg);
|
||||
|
||||
void
|
||||
pass1(void)
|
||||
|
|
@ -68,7 +68,7 @@ pass1(void)
|
|||
ino_t inumber, inosused, mininos;
|
||||
ufs2_daddr_t i, cgd;
|
||||
u_int8_t *cp;
|
||||
int c, rebuildcg;
|
||||
int c, rebuiltcg;
|
||||
|
||||
badblk = dupblk = lastino = 0;
|
||||
|
||||
|
|
@ -99,10 +99,14 @@ pass1(void)
|
|||
inumber = c * sblock.fs_ipg;
|
||||
cgbp = cglookup(c);
|
||||
cgp = cgbp->b_un.b_cg;
|
||||
rebuildcg = 0;
|
||||
if (!check_cgmagic(c, cgbp, 1))
|
||||
rebuildcg = 1;
|
||||
if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
|
||||
rebuiltcg = 0;
|
||||
if (!check_cgmagic(c, cgbp, 0)) {
|
||||
if (!check_cgmagic(c, cgbp, 1))
|
||||
cgheader_corrupt = 1;
|
||||
else
|
||||
rebuiltcg = 1;
|
||||
}
|
||||
if (!rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC) {
|
||||
inosused = cgp->cg_initediblk;
|
||||
if (inosused > sblock.fs_ipg) {
|
||||
pfatal("Too many initialized inodes (%ju > %d) "
|
||||
|
|
@ -132,7 +136,7 @@ pass1(void)
|
|||
* to find the inodes that are really in use, and then
|
||||
* read only those inodes in from disk.
|
||||
*/
|
||||
if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
|
||||
if ((preen || inoopt) && usedsoftdep && !rebuiltcg) {
|
||||
cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
|
||||
for ( ; inosused != 0; cp--) {
|
||||
if (*cp == 0) {
|
||||
|
|
@ -169,7 +173,7 @@ pass1(void)
|
|||
setinodebuf(c, inosused);
|
||||
for (i = 0; i < inosused; i++, inumber++) {
|
||||
if (inumber < UFS_ROOTINO) {
|
||||
(void)getnextinode(inumber, rebuildcg);
|
||||
(void)getnextinode(inumber, rebuiltcg);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
|
|
@ -178,7 +182,7 @@ pass1(void)
|
|||
* We always keep trying until we get to the minimum
|
||||
* valid number for this cylinder group.
|
||||
*/
|
||||
if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
|
||||
if (checkinode(inumber, &idesc, rebuiltcg) == 0 &&
|
||||
i > cgp->cg_initediblk)
|
||||
break;
|
||||
}
|
||||
|
|
@ -189,7 +193,7 @@ pass1(void)
|
|||
* fewer in use.
|
||||
*/
|
||||
mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
|
||||
if (inoopt && !preen && !rebuildcg &&
|
||||
if (inoopt && !preen && !rebuiltcg &&
|
||||
sblock.fs_magic == FS_UFS2_MAGIC &&
|
||||
cgp->cg_initediblk > 2 * INOPB(&sblock) &&
|
||||
mininos < cgp->cg_initediblk) {
|
||||
|
|
@ -209,7 +213,7 @@ pass1(void)
|
|||
inosused = 0;
|
||||
else
|
||||
inosused = lastino - (c * sblock.fs_ipg);
|
||||
if (rebuildcg && inosused > cgp->cg_initediblk &&
|
||||
if (rebuiltcg && inosused > cgp->cg_initediblk &&
|
||||
sblock.fs_magic == FS_UFS2_MAGIC) {
|
||||
cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
|
||||
pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
|
||||
|
|
@ -242,7 +246,7 @@ pass1(void)
|
|||
}
|
||||
|
||||
static int
|
||||
checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
|
||||
checkinode(ino_t inumber, struct inodesc *idesc, int rebuiltcg)
|
||||
{
|
||||
struct inode ip;
|
||||
union dinode *dp;
|
||||
|
|
@ -252,7 +256,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
|
|||
intmax_t size, fixsize;
|
||||
int j, ret, offset;
|
||||
|
||||
if ((dp = getnextinode(inumber, rebuildcg)) == NULL) {
|
||||
if ((dp = getnextinode(inumber, rebuiltcg)) == NULL) {
|
||||
pfatal("INVALID INODE");
|
||||
goto unknown;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue