Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Jan 2001 23:25:41 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        freebsd-fs@FreeBSD.ORG
Cc:        iedowse@maths.tcd.ie
Subject:   Re: fsck problem on large vinum volume 
Message-ID:   <200101122325.aa07194@salmon.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help

Here is an updated patch which I shall commit in a few days (Kirk
has already said in a private mail that he is in agreement with
these changes). This patch modifies the declaration of the 128-byte
summary pointer area in the superblock from

	struct  csum *fs_csp[MAXCSBUFS];
	int32_t  *fs_maxcluster;

to

	void    *fs_ocsp[NOCSPTRS];	/* padding */
	struct csum *fs_csp;		/* cg summary info buffer */
	int32_t *fs_maxcluster;

and updates all files and utilities to match. A summary of the
other changes is:

 * Use fs_csp to store a pointer to the start of a single contiguous
   array of cylinder group summary information (struct csum). This
   is done in the kernel (ffs_vfsops.c, ffs_snapshot.c) and in the
   userland utilities dumpfs, fsck_ffs, fsck_ifs.

 * Update the 'fs_cs' macro to access elements in this array directly
   i.e. as
		fs_csp[cg]
   instead of:
		fs_csp[cg summary block][cg summary block offset]

 * Add a comment in newfs/mkfs.c to indicate that while fs_csmask
   and fs_csshift are no longer used, we do need to initialise them
   for compatibility with old kernels.

(Just to be clear before someone asks, this region of the superblock
is used only for temporary in-core storage - this change introduces
no filesystem compatibility issues).

Ian

Index: sbin/dumpfs/dumpfs.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/dumpfs/dumpfs.c,v
retrieving revision 1.13
diff -u -r1.13 dumpfs.c
--- sbin/dumpfs/dumpfs.c	1999/08/28 00:12:42	1.13
+++ sbin/dumpfs/dumpfs.c	2001/01/09 22:54:16
@@ -205,15 +205,15 @@
 		}
 	}
 	printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
+	afs.fs_csp = calloc(1, afs.fs_cssize);
 	for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
 		size = afs.fs_cssize - i < afs.fs_bsize ?
 		    afs.fs_cssize - i : afs.fs_bsize;
-		afs.fs_csp[j] = calloc(1, size);
 		if (lseek(fd,
 		    (off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag))) *
 		    (off_t)dev_bsize, SEEK_SET) == (off_t)-1)
 			goto err;
-		if (read(fd, afs.fs_csp[j], size) != size)
+		if (read(fd, (char *)afs.fs_csp + i, size) != size)
 			goto err;
 	}
 	for (i = 0; i < afs.fs_ncg; i++) {
Index: sbin/fsck_ffs/fsutil.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ffs/fsutil.c,v
retrieving revision 1.2
diff -u -r1.2 fsutil.c
--- sbin/fsck_ffs/fsutil.c	2000/10/09 09:42:51	1.2
+++ sbin/fsck_ffs/fsutil.c	2001/01/09 22:58:57
@@ -249,7 +249,7 @@
 	if (bp != &sblk)
 		return;
 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
-		bwrite(fswritefd, (char *)sblock.fs_csp[j],
+		bwrite(fswritefd, (char *)sblock.fs_csp + i,
 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
 		    sblock.fs_cssize - i < sblock.fs_bsize ?
 		    sblock.fs_cssize - i : sblock.fs_bsize);
Index: sbin/fsck_ffs/setup.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ffs/setup.c,v
retrieving revision 1.18
diff -u -r1.18 setup.c
--- sbin/fsck_ffs/setup.c	2000/07/06 02:03:11	1.18
+++ sbin/fsck_ffs/setup.c	2001/01/09 22:57:34
@@ -258,11 +258,11 @@
 	 * read in the summary info.
 	 */
 	asked = 0;
+	sblock.fs_csp = calloc(1, sblock.fs_cssize);
 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
 		    sblock.fs_cssize - i : sblock.fs_bsize;
-		sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size);
-		if (bread(fsreadfd, (char *)sblock.fs_csp[j],
+		if (bread(fsreadfd, (char *)sblock.fs_csp + i,
 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
 		    size) != 0 && !asked) {
 			pfatal("BAD SUMMARY INFORMATION");
@@ -380,7 +380,8 @@
 	altsblock.fs_optim = sblock.fs_optim;
 	altsblock.fs_rotdelay = sblock.fs_rotdelay;
 	altsblock.fs_maxbpg = sblock.fs_maxbpg;
-	memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
+	memmove(altsblock.fs_ocsp, sblock.fs_ocsp, sizeof sblock.fs_ocsp);
+	altsblock.fs_csp = sblock.fs_csp;
 	altsblock.fs_maxcluster = sblock.fs_maxcluster;
 	memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
 	memmove(altsblock.fs_snapinum, sblock.fs_snapinum,
Index: sbin/fsck_ifs/fsutil.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ifs/fsutil.c,v
retrieving revision 1.2
diff -u -r1.2 fsutil.c
--- sbin/fsck_ifs/fsutil.c	2000/10/09 09:42:51	1.2
+++ sbin/fsck_ifs/fsutil.c	2001/01/12 19:33:52
@@ -249,7 +249,7 @@
 	if (bp != &sblk)
 		return;
 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
-		bwrite(fswritefd, (char *)sblock.fs_csp[j],
+		bwrite(fswritefd, (char *)sblock.fs_csp + i,
 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
 		    sblock.fs_cssize - i < sblock.fs_bsize ?
 		    sblock.fs_cssize - i : sblock.fs_bsize);
Index: sbin/fsck_ifs/setup.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ifs/setup.c,v
retrieving revision 1.19
diff -u -r1.19 setup.c
--- sbin/fsck_ifs/setup.c	2000/10/14 02:44:53	1.19
+++ sbin/fsck_ifs/setup.c	2001/01/12 19:35:18
@@ -258,11 +258,11 @@
 	 * read in the summary info.
 	 */
 	asked = 0;
+	sblock.fs_csp = calloc(1, sblock.fs_cssize);
 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
 		    sblock.fs_cssize - i : sblock.fs_bsize;
-		sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size);
-		if (bread(fsreadfd, (char *)sblock.fs_csp[j],
+		if (bread(fsreadfd, (char *)sblock.fs_csp + i,
 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
 		    size) != 0 && !asked) {
 			pfatal("BAD SUMMARY INFORMATION");
@@ -382,7 +382,8 @@
 	altsblock.fs_optim = sblock.fs_optim;
 	altsblock.fs_rotdelay = sblock.fs_rotdelay;
 	altsblock.fs_maxbpg = sblock.fs_maxbpg;
-	memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
+	memmove(altsblock.fs_ocsp, sblock.fs_ocsp, sizeof sblock.fs_ocsp);
+	altsblock.fs_csp = sblock.fs_csp;
 	altsblock.fs_maxcluster = sblock.fs_maxcluster;
 	memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
 	memmove(altsblock.fs_snapinum, sblock.fs_snapinum,
Index: sbin/newfs/mkfs.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/newfs/mkfs.c,v
retrieving revision 1.32
diff -u -r1.32 mkfs.c
--- sbin/newfs/mkfs.c	2000/10/24 03:28:59	1.32
+++ sbin/newfs/mkfs.c	2001/01/12 22:55:00
@@ -633,6 +633,11 @@
 	sblock.fs_csaddr = cgdmin(&sblock, 0);
 	sblock.fs_cssize =
 	    fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
+	/*
+	 * The superblock fields 'fs_csmask' and 'fs_csshift' are no
+	 * longer used. However, we still initialise them so that the
+	 * filesystem remains compatible with old kernels.
+	 */
 	i = sblock.fs_bsize / sizeof(struct csum);
 	sblock.fs_csmask = ~(i - 1);
 	for (sblock.fs_csshift = 0; i > 1; i >>= 1)
Index: sys/ufs/ffs/ffs_snapshot.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/ffs_snapshot.c,v
retrieving revision 1.8
diff -u -r1.8 ffs_snapshot.c
--- sys/ufs/ffs/ffs_snapshot.c	2001/01/12 21:56:55	1.8
+++ sys/ufs/ffs/ffs_snapshot.c	2001/01/12 22:40:25
@@ -83,6 +83,7 @@
 	int error, cg, snaploc, indiroff, numblks;
 	int i, size, base, len, loc, inoblkcnt;
 	int blksperindir, flag = mp->mnt_flag;
+	void *space;
 	struct fs *copy_fs, *fs = VFSTOUFS(mp)->um_fs;
 	struct proc *p = CURPROC;
 	struct inode *devip, *ip, *xp;
@@ -346,6 +347,7 @@
 	blkno = fragstoblks(fs, fs->fs_csaddr);
 	len = howmany(fs->fs_cssize, fs->fs_bsize) - 1;
 	size = fs->fs_bsize;
+	space = fs->fs_csp;
 	for (loc = 0; loc <= len; loc++) {
 		error = VOP_BALLOC(vp, lblktosize(fs, (off_t)(blkno + loc)),
 		    fs->fs_bsize, KERNCRED, 0, &nbp);
@@ -355,7 +357,8 @@
 			readblock(nbp, blkno + loc);
 			size = fs->fs_cssize - loc * fs->fs_bsize;
 		}
-		bcopy(fs->fs_csp[loc], nbp->b_data, size);
+		bcopy(space, nbp->b_data, size);
+		space = (char *)space + size;
 		nbp->b_flags |= B_VALIDSUSPWRT;
 		bawrite(nbp);
 	}
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.134
diff -u -r1.134 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	2000/12/13 10:03:52	1.134
+++ sys/ufs/ffs/ffs_vfsops.c	2001/01/09 22:48:28
@@ -365,7 +365,7 @@
 {
 	register struct vnode *vp, *nvp, *devvp;
 	struct inode *ip;
-	struct csum *space;
+	void *space;
 	struct buf *bp;
 	struct fs *fs, *newfs;
 	struct partinfo dpart;
@@ -419,7 +419,7 @@
 	 * new superblock. These should really be in the ufsmount.	XXX
 	 * Note that important parameters (eg fs_ncg) are unchanged.
 	 */
-	bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
+	newfs->fs_csp = fs->fs_csp;
 	newfs->fs_maxcluster = fs->fs_maxcluster;
 	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
 	if (fs->fs_sbsize < SBSIZE)
@@ -432,7 +432,7 @@
 	 * Step 3: re-read summary information from disk.
 	 */
 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
-	space = fs->fs_csp[0];
+	space = fs->fs_csp;
 	for (i = 0; i < blks; i += fs->fs_frag) {
 		size = fs->fs_bsize;
 		if (i + fs->fs_frag > blks)
@@ -441,7 +441,8 @@
 		    NOCRED, &bp);
 		if (error)
 			return (error);
-		bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
+		bcopy(bp->b_data, space, (u_int)size);
+		space = (char *)space + size;
 		brelse(bp);
 	}
 	/*
@@ -513,7 +514,7 @@
 	register struct fs *fs;
 	dev_t dev;
 	struct partinfo dpart;
-	caddr_t base, space;
+	void *space;
 	int error, i, blks, size, ronly;
 	int32_t *lp;
 	struct ucred *cred;
@@ -623,24 +624,24 @@
 	blks = howmany(size, fs->fs_fsize);
 	if (fs->fs_contigsumsize > 0)
 		size += fs->fs_ncg * sizeof(int32_t);
-	base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
+	space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
+	fs->fs_csp = space;
 	for (i = 0; i < blks; i += fs->fs_frag) {
 		size = fs->fs_bsize;
 		if (i + fs->fs_frag > blks)
 			size = (blks - i) * fs->fs_fsize;
 		if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
 		    cred, &bp)) != 0) {
-			free(base, M_UFSMNT);
+			free(fs->fs_csp, M_UFSMNT);
 			goto out;
 		}
 		bcopy(bp->b_data, space, (u_int)size);
-		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
-		space += size;
+		space = (char *)space + size;
 		brelse(bp);
 		bp = NULL;
 	}
 	if (fs->fs_contigsumsize > 0) {
-		fs->fs_maxcluster = lp = (int32_t *)space;
+		fs->fs_maxcluster = lp = space;
 		for (i = 0; i < fs->fs_ncg; i++)
 			*lp++ = fs->fs_contigsumsize;
 	}
@@ -691,7 +692,7 @@
 	if (ronly == 0) {
 		if ((fs->fs_flags & FS_DOSOFTDEP) &&
 		    (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
-			free(base, M_UFSMNT);
+			free(fs->fs_csp, M_UFSMNT);
 			goto out;
 		}
 		if (fs->fs_snapinum[0] != 0)
@@ -808,7 +809,7 @@
 
 	vrele(ump->um_devvp);
 
-	free(fs->fs_csp[0], M_UFSMNT);
+	free(fs->fs_csp, M_UFSMNT);
 	free(fs, M_UFSMNT);
 	free(ump, M_UFSMNT);
 	mp->mnt_data = (qaddr_t)0;
@@ -1263,14 +1264,14 @@
 	register struct fs *dfs, *fs = mp->um_fs;
 	register struct buf *bp;
 	int blks;
-	caddr_t space;
+	void *space;
 	int i, size, error, allerror = 0;
 
 	/*
 	 * First write back the summary information.
 	 */
 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
-	space = (caddr_t)fs->fs_csp[0];
+	space = fs->fs_csp;
 	for (i = 0; i < blks; i += fs->fs_frag) {
 		size = fs->fs_bsize;
 		if (i + fs->fs_frag > blks)
@@ -1278,7 +1279,7 @@
 		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
 		    size, 0, 0);
 		bcopy(space, bp->b_data, (u_int)size);
-		space += size;
+		space = (char *)space + size;
 		if (waitfor != MNT_WAIT)
 			bawrite(bp);
 		else if ((error = bwrite(bp)) != 0)
Index: sys/ufs/ffs/fs.h
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/fs.h,v
retrieving revision 1.16
diff -u -r1.16 fs.h
--- sys/ufs/ffs/fs.h	2000/07/04 04:55:48	1.16
+++ sys/ufs/ffs/fs.h	2001/01/12 22:42:44
@@ -106,14 +106,17 @@
 #define MAXMNTLEN	512
 
 /*
- * The limit on the amount of summary information per file system
- * is defined by MAXCSBUFS. It is currently parameterized for a
- * size of 128 bytes (2 million cylinder groups on machines with
- * 32-bit pointers, and 1 million on 64-bit machines). One pointer
- * is taken away to point to an array of cluster sizes that is
- * computed as cylinder groups are inspected.
+ * There is a 128-byte region in the superblock reserved for in-core
+ * pointers to summary information. Originally this included an array
+ * of pointers to blocks of struct csum; now there are just two
+ * pointers and the remaining space is padded with fs_ocsp[].
+ *
+ * NOCSPTRS determines the size of this padding. One pointer (fs_csp)
+ * is taken away to point to a contiguous array of struct csum for
+ * all cylinder groups; a second (fs_maxcluster) points to an array
+ * of cluster sizes that is computed as cylinder groups are inspected.
  */
-#define	MAXCSBUFS	((128 / sizeof(void *)) - 1)
+#define	NOCSPTRS	((128 / sizeof(void *)) - 2)
 
 /*
  * A summary of contiguous blocks of various sizes is maintained
@@ -167,9 +170,6 @@
  * from first cylinder group data blocks.  These blocks have to be
  * read in from fs_csaddr (size fs_cssize) in addition to the
  * super block.
- *
- * N.B. sizeof(struct csum) must be a power of two in order for
- * the ``fs_cs'' macro to work (see below).
  */
 struct csum {
 	int32_t	cs_ndir;		/* number of directories */
@@ -213,8 +213,8 @@
 	int32_t	 fs_fragshift;		/* block to frag shift */
 	int32_t	 fs_fsbtodb;		/* fsbtodb and dbtofsb shift constant */
 	int32_t	 fs_sbsize;		/* actual size of super block */
-	int32_t	 fs_csmask;		/* csum block offset */
-	int32_t	 fs_csshift;		/* csum block number */
+	int32_t	 fs_csmask;		/* csum block offset (now unused) */
+	int32_t	 fs_csshift;		/* csum block number (now unused) */
 	int32_t	 fs_nindir;		/* value of NINDIR */
 	int32_t	 fs_inopb;		/* value of INOPB */
 	int32_t	 fs_nspf;		/* value of NSPF */
@@ -250,8 +250,9 @@
 	u_char	 fs_fsmnt[MAXMNTLEN];	/* name mounted on */
 /* these fields retain the current block allocation info */
 	int32_t	 fs_cgrotor;		/* last cg searched */
-	struct	csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */
-	int32_t	 *fs_maxcluster;	/* max cluster in each cyl group */
+	void 	*fs_ocsp[NOCSPTRS];	/* padding; was list of fs_cs buffers */
+	struct csum *fs_csp;		/* cg summary info buffer for fs_cs */
+	int32_t	*fs_maxcluster;		/* max cluster in each cyl group */
 	int32_t	 fs_cpc;		/* cyl per cycle in postbl */
 	int16_t	 fs_opostbl[16][8];	/* old rotation block list head */
 	int32_t	 fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
@@ -328,11 +329,8 @@
 
 /*
  * Convert cylinder group to base address of its global summary info.
- *
- * N.B. This macro assumes that sizeof(struct csum) is a power of two.
  */
-#define fs_cs(fs, indx) \
-	fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask]
+#define fs_cs(fs, indx) fs_csp[indx]
 
 /*
  * Cylinder group block for a file system.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-fs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200101122325.aa07194>