summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/fsutil.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/fsutil.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/fsutil.c')
-rw-r--r--sbin/fsck_ffs/fsutil.c96
1 files changed, 71 insertions, 25 deletions
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 91628ea..4ce2ef2 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -333,9 +333,13 @@ ckfini(int markclean)
if (!markclean)
rerun = 1;
}
- } else if (!preen && !markclean) {
- printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
- rerun = 1;
+ } else if (!preen) {
+ if (markclean) {
+ printf("\n***** FILE SYSTEM IS CLEAN *****\n");
+ } else {
+ printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
+ rerun = 1;
+ }
}
if (debug && totalreads > 0)
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
@@ -418,32 +422,73 @@ blwrite(int fd, char *buf, ufs2_daddr_t blk, long size)
}
/*
- * 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.
+ * Verify cylinder group's magic number and other parameters. If the
+ * test fails, offer an option to rebuild the whole cylinder group.
*/
-void
+int
check_cgmagic(int cg, struct cg *cgp)
{
- if (!cg_chkmagic(cgp)) {
- pwarn("CG %d: BAD MAGIC NUMBER\n", cg);
- if (damagedflag) {
- 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 -D IF IT CRASHED.\n");
+ /*
+ * Extended cylinder group checks.
+ */
+ if (cg_chkmagic(cgp) &&
+ ((sblock.fs_magic == FS_UFS1_MAGIC &&
+ cgp->cg_old_niblk == sblock.fs_ipg &&
+ cgp->cg_ndblk <= sblock.fs_fpg &&
+ cgp->cg_old_ncyl == sblock.fs_old_cpg) ||
+ (sblock.fs_magic == FS_UFS2_MAGIC &&
+ cgp->cg_niblk == sblock.fs_ipg &&
+ cgp->cg_ndblk <= sblock.fs_fpg &&
+ cgp->cg_initediblk <= sblock.fs_ipg))) {
+ return (1);
+ }
+ pfatal("CYLINDER GROUP %d: BAD MAGIC NUMBER", cg);
+ if (!reply("REBUILD CYLINDER GROUP")) {
+ printf("YOU WILL NEED TO RERUN FSCK.\n");
+ rerun = 1;
+ return (1);
+ }
+ /*
+ * Zero out the cylinder group and then initialize critical fields.
+ * Bit maps and summaries will be recalculated by later passes.
+ */
+ memset(cgp, 0, (size_t)sblock.fs_cgsize);
+ cgp->cg_magic = CG_MAGIC;
+ cgp->cg_cgx = cg;
+ cgp->cg_niblk = sblock.fs_ipg;
+ cgp->cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
+ sblock.fs_ipg : 2 * INOPB(&sblock);
+ if (cgbase(&sblock, cg) + sblock.fs_fpg < sblock.fs_size)
+ cgp->cg_ndblk = sblock.fs_fpg;
+ else
+ cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg);
+ cgp->cg_iusedoff = &cgp->cg_space[0] - (u_char *)(&cgp->cg_firstfield);
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ cgp->cg_niblk = 0;
+ cgp->cg_initediblk = 0;
+ cgp->cg_old_ncyl = sblock.fs_old_cpg;
+ cgp->cg_old_niblk = sblock.fs_ipg;
+ cgp->cg_old_btotoff = cgp->cg_iusedoff;
+ cgp->cg_old_boff = cgp->cg_old_btotoff +
+ sblock.fs_old_cpg * sizeof(int32_t);
+ cgp->cg_iusedoff = cgp->cg_old_boff +
+ sblock.fs_old_cpg * sizeof(u_int16_t);
+ }
+ cgp->cg_freeoff = cgp->cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
+ cgp->cg_nextfreeoff = cgp->cg_freeoff + howmany(sblock.fs_fpg,CHAR_BIT);
+ if (sblock.fs_contigsumsize > 0) {
+ cgp->cg_nclusterblks = cgp->cg_ndblk / sblock.fs_frag;
+ cgp->cg_clustersumoff =
+ roundup(cgp->cg_nextfreeoff, sizeof(u_int32_t));
+ cgp->cg_clustersumoff -= sizeof(u_int32_t);
+ cgp->cg_clusteroff = cgp->cg_clustersumoff +
+ (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
+ cgp->cg_nextfreeoff = cgp->cg_clusteroff +
+ howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
}
+ cgdirty();
+ return (0);
}
/*
@@ -470,7 +515,8 @@ allocblk(long frags)
}
cg = dtog(&sblock, i + j);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
- check_cgmagic(cg, cgp);
+ if (!check_cgmagic(cg, cgp))
+ return (0);
baseblk = dtogd(&sblock, i + j);
for (k = 0; k < frags; k++) {
setbmap(i + j + k);
OpenPOWER on IntegriCloud