Add a new flag, '-C' which enables a special mode that is intended for
catastrophic recovery. Currently, this mode only validates whether a cylindergroup has good signature data, and prompts the user to decide whether to clear it as a whole. This mode is useful when there is data damage on a disk and you are working on copy of the original disk, as fsck_ffs(8) tends to abnormally exit in such case, as a last resort to recover data from the disk.
This commit is contained in:
parent
30f94bb497
commit
14320f1e7f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178088
@ -270,6 +270,7 @@ char yflag; /* assume a yes response */
|
|||||||
int bkgrdflag; /* use a snapshot to run on an active system */
|
int bkgrdflag; /* use a snapshot to run on an active system */
|
||||||
int bflag; /* location of alternate super block */
|
int bflag; /* location of alternate super block */
|
||||||
int debug; /* output debugging info */
|
int debug; /* output debugging info */
|
||||||
|
char catastrophicflag; /* run in catastrophic mode */
|
||||||
int cvtlevel; /* convert to newer file system format */
|
int cvtlevel; /* convert to newer file system format */
|
||||||
int bkgrdcheck; /* determine if background check is possible */
|
int bkgrdcheck; /* determine if background check is possible */
|
||||||
int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */
|
int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */
|
||||||
@ -335,6 +336,7 @@ void cacheino(union dinode *dp, ino_t inumber);
|
|||||||
void catch(int);
|
void catch(int);
|
||||||
void catchquit(int);
|
void catchquit(int);
|
||||||
int changeino(ino_t dir, const char *name, ino_t newnum);
|
int changeino(ino_t dir, const char *name, ino_t newnum);
|
||||||
|
void check_cgmagic(int cg, struct cg *cgp);
|
||||||
int chkrange(ufs2_daddr_t blk, int cnt);
|
int chkrange(ufs2_daddr_t blk, int cnt);
|
||||||
void ckfini(int markclean);
|
void ckfini(int markclean);
|
||||||
int ckinode(union dinode *dp, struct inodesc *);
|
int ckinode(union dinode *dp, struct inodesc *);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
|
.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 24, 2001
|
.Dd April 10, 2008
|
||||||
.Dt FSCK_FFS 8
|
.Dt FSCK_FFS 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -38,7 +38,7 @@
|
|||||||
.Nd file system consistency check and interactive repair
|
.Nd file system consistency check and interactive repair
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl BFpfny
|
.Op Fl BCFpfny
|
||||||
.Op Fl b Ar block
|
.Op Fl b Ar block
|
||||||
.Op Fl c Ar level
|
.Op Fl c Ar level
|
||||||
.Op Fl m Ar mode
|
.Op Fl m Ar mode
|
||||||
@ -175,6 +175,26 @@ Use the block specified immediately after the flag as
|
|||||||
the super block for the file system.
|
the super block for the file system.
|
||||||
An alternate super block is usually located at block 32 for UFS1,
|
An alternate super block is usually located at block 32 for UFS1,
|
||||||
and block 160 for UFS2.
|
and block 160 for UFS2.
|
||||||
|
.It Fl C
|
||||||
|
Run
|
||||||
|
.Nm
|
||||||
|
in 'catastrophic recovery' mode, which will enable certain aggressive
|
||||||
|
operations that can make
|
||||||
|
.Nm
|
||||||
|
to survive with file systems that has very serious data damage, which
|
||||||
|
is an useful last resort when on disk data damage is very serious
|
||||||
|
and causes
|
||||||
|
.Nm
|
||||||
|
to crash otherwise. Be
|
||||||
|
.Em very careful
|
||||||
|
using this flag, is dangerous if there are data transmission hazards
|
||||||
|
because a false positive cylinder group magic number mismatch could
|
||||||
|
cause
|
||||||
|
.Em irrevertible data loss!
|
||||||
|
.Pp
|
||||||
|
This option implies the
|
||||||
|
.Fl f
|
||||||
|
flag.
|
||||||
.It Fl c
|
.It Fl c
|
||||||
Convert the file system to the specified level.
|
Convert the file system to the specified level.
|
||||||
Note that the level of a file system can only be raised.
|
Note that the level of a file system can only be raised.
|
||||||
|
@ -417,6 +417,35 @@ blwrite(int fd, char *buf, ufs2_daddr_t blk, long size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check cg's magic number. If catastrophic mode is enabled and the cg's
|
||||||
|
* magic number is bad, offer an option to clear the whole cg.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
check_cgmagic(int cg, struct cg *cgp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!cg_chkmagic(cgp)) {
|
||||||
|
pwarn("CG %d: BAD MAGIC NUMBER\n", cg);
|
||||||
|
if (catastrophicflag) {
|
||||||
|
if (reply("CLEAR CG")) {
|
||||||
|
memset(cgp, 0, (size_t)sblock.fs_cgsize);
|
||||||
|
cgp->cg_initediblk = sblock.fs_ipg;
|
||||||
|
cgp->cg_old_niblk = sblock.fs_ipg;
|
||||||
|
cgp->cg_old_ncyl = sblock.fs_old_cpg;
|
||||||
|
cgp->cg_cgx = cg;
|
||||||
|
cgp->cg_niblk = sblock.fs_ipg;
|
||||||
|
cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg);
|
||||||
|
cgp->cg_magic = CG_MAGIC;
|
||||||
|
cgdirty();
|
||||||
|
printf("PLEASE RERUN FSCK.\n");
|
||||||
|
rerun = 1;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
printf("YOU MAY NEED TO RERUN FSCK WITH -C IF IT CRASHED.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate a data block with the specified number of fragments
|
* allocate a data block with the specified number of fragments
|
||||||
*/
|
*/
|
||||||
@ -441,8 +470,7 @@ allocblk(long frags)
|
|||||||
}
|
}
|
||||||
cg = dtog(&sblock, i + j);
|
cg = dtog(&sblock, i + j);
|
||||||
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
|
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
|
||||||
if (!cg_chkmagic(cgp))
|
check_cgmagic(cg, cgp);
|
||||||
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
|
|
||||||
baseblk = dtogd(&sblock, i + j);
|
baseblk = dtogd(&sblock, i + j);
|
||||||
for (k = 0; k < frags; k++) {
|
for (k = 0; k < frags; k++) {
|
||||||
setbmap(i + j + k);
|
setbmap(i + j + k);
|
||||||
|
@ -617,8 +617,7 @@ allocino(ino_t request, int type)
|
|||||||
return (0);
|
return (0);
|
||||||
cg = ino_to_cg(&sblock, ino);
|
cg = ino_to_cg(&sblock, ino);
|
||||||
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
|
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
|
||||||
if (!cg_chkmagic(cgp))
|
check_cgmagic(cg, cgp);
|
||||||
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
|
|
||||||
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
|
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
|
||||||
cgp->cg_cs.cs_nifree--;
|
cgp->cg_cs.cs_nifree--;
|
||||||
switch (type & IFMT) {
|
switch (type & IFMT) {
|
||||||
|
@ -81,7 +81,8 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
sync();
|
sync();
|
||||||
skipclean = 1;
|
skipclean = 1;
|
||||||
while ((ch = getopt(argc, argv, "b:Bc:dfFm:npy")) != -1) {
|
catastrophicflag = 0;
|
||||||
|
while ((ch = getopt(argc, argv, "b:Bc:CdfFm:npy")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'b':
|
case 'b':
|
||||||
skipclean = 0;
|
skipclean = 0;
|
||||||
@ -105,6 +106,10 @@ main(int argc, char *argv[])
|
|||||||
debug++;
|
debug++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
catastrophicflag = 1;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
skipclean = 0;
|
skipclean = 0;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user