summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2007-02-16 08:34:30 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2007-02-16 08:34:30 +0000
commit5066e68b81c9309d61a1c3186a9aab6d328c512b (patch)
treeb04a2fb33530c9abc2ae83727152591ffa37c18c /sbin
parent3785927835d9a409f8e57c22fee8d3bd324c90b4 (diff)
Fix a row of bugs in the code that computes the alternate superblock
locations based on the disklabel. - unit bug: disklabel size is in sectors, but superblock fs size is in fragments. - The disklabel contains the maximum superblock size, not the actual as used by newfs. - problem is that mkfs reduces track/sector and secors/track to make the cylindergroup fit in a fs block. In this case the values in the disklabel do not predict what's in the superblock. This fixes all these problems. It correctly predicts the location of all superblocks on all my filesystems I have online (sized between 100MB and 1000GB). Also tested with filesystems with different block and fragment sizes. Written this with a goto to make the diff easier to read. ok krw@ deraadt@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/setup.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 44cfcafcb69..875237a010f 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setup.c,v 1.28 2007/02/13 15:56:22 otto Exp $ */
+/* $OpenBSD: setup.c,v 1.29 2007/02/16 08:34:29 otto Exp $ */
/* $NetBSD: setup.c,v 1.27 1996/09/27 22:45:19 christos Exp $ */
/*
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
#else
-static const char rcsid[] = "$OpenBSD: setup.c,v 1.28 2007/02/13 15:56:22 otto Exp $";
+static const char rcsid[] = "$OpenBSD: setup.c,v 1.29 2007/02/16 08:34:29 otto Exp $";
#endif
#endif /* not lint */
@@ -573,15 +573,19 @@ calcsb(char *dev, int devfd, struct fs *fs)
memset(fs, 0, sizeof(struct fs));
fs->fs_fsize = pp->p_fsize;
fs->fs_frag = pp->p_frag;
+ fs->fs_bsize = fs->fs_fsize * fs->fs_frag;
fs->fs_cpg = pp->p_cpg;
- fs->fs_size = pp->p_size;
+ fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
+ /* unit for fs->fs_size is fragments, for pp->p_size it is sectors */
+ fs->fs_size = pp->p_size / fs->fs_nspf;
fs->fs_ntrak = lp->d_ntracks;
fs->fs_nsect = lp->d_nsectors;
fs->fs_spc = lp->d_secpercyl;
- fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
+ /* we can't use lp->d_sbsize, it is the max sb size */
fs->fs_sblkno = roundup(
- howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
+ howmany(lp->d_bbsize + SBSIZE, fs->fs_fsize),
fs->fs_frag);
+again:
fs->fs_cgmask = 0xffffffff;
for (i = fs->fs_ntrak; i > 1; i >>= 1)
fs->fs_cgmask <<= 1;
@@ -590,9 +594,19 @@ calcsb(char *dev, int devfd, struct fs *fs)
fs->fs_cgoffset = roundup(
howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
- fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
+ fs->fs_ncg = howmany(pp->p_size / fs->fs_spc, fs->fs_cpg);
for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
fs->fs_fsbtodb++;
+ /*
+ * Mimick what mkfs is doing to get an acceptable cgsize,
+ * not all fields used by CGSIZE() are filled in, but it's a best
+ * effort anyway.
+ */
+ if (CGSIZE(fs) > fs->fs_bsize && fs->fs_ntrak > 1) {
+ fs->fs_ntrak >>= 1;
+ fs->fs_spc >>= 1;
+ goto again;
+ }
dev_bsize = lp->d_secsize;
return (1);
}