[moved to -fs]
In message [EMAIL PROTECTED], Ian Dowse writes:
Jaye sent me a ktrace.out for the fsck that was failing. It appears
that the kernel had overshot the end of the superblock fs_csp[] array
in ffs_mountfs(), since the list of pointers there extended through
fs_maxcluster, fs_cpc, and fs_opostbl. This caused the mismatch between
the master and alternate superblocks.
The filesystem parameters were 8k/1k, and the total number of cylinder
groups was 29782. fs_cssize was 29782*sizeof(struct csum) = 477184
bytes. Hence 477184/8192 = ~59 entries were being used in fs_csp,
but fs_csp[] is only 31 entries long (15 on alpha).
Here is a patch which should avoid the possibility of overflowing
the fs_csp[] array. The idea is that since all summary blocks are
stored in one contiguous malloc'd region, there is no need to
have a separate pointer to the start of each block within that
region.
This is achieved by simplifying the 'fs_cs' macro from
fs_csp[(indx) (fs)-fs_csshift][(indx) ~(fs)-fs_csmask]
to
fs_csp[0][indx]
so that only the start of the malloc'd region is needed, and can always
be placed in fs_csp[0] without the risk of overflow.
I have only tested this to the extent that the kernel compiles and
runs, and only on -stable.
Any comments or suggestions?
Ian
Index: ffs/ffs_vfsops.c
===
RCS file: /home/iedowse/CVS/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.134
diff -u -r1.134 ffs_vfsops.c
--- ffs/ffs_vfsops.c2000/12/13 10:03:52 1.134
+++ ffs/ffs_vfsops.c2001/01/07 19:04:06
@@ -365,7 +365,7 @@
{
register struct vnode *vp, *nvp, *devvp;
struct inode *ip;
- struct csum *space;
+ caddr_t space;
struct buf *bp;
struct fs *fs, *newfs;
struct partinfo dpart;
@@ -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 = (caddr_t)fs-fs_csp[0];
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 += size;
brelse(bp);
}
/*
@@ -513,7 +514,7 @@
register struct fs *fs;
dev_t dev;
struct partinfo dpart;
- caddr_t base, space;
+ caddr_t space;
int error, i, blks, size, ronly;
int32_t *lp;
struct ucred *cred;
@@ -623,18 +624,18 @@
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[0] = (struct csum *)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[0], M_UFSMNT);
goto out;
}
bcopy(bp-b_data, space, (u_int)size);
- fs-fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
space += size;
brelse(bp);
bp = NULL;
@@ -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[0], M_UFSMNT);
goto out;
}
if (fs-fs_snapinum[0] != 0)
Index: ffs/fs.h
===
RCS file: /home/iedowse/CVS/src/sys/ufs/ffs/fs.h,v
retrieving revision 1.16
diff -u -r1.16 fs.h
--- ffs/fs.h2000/07/04 04:55:48 1.16
+++ ffs/fs.h2001/01/07 18:55:44
@@ -108,10 +108,10 @@
/*
* 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.
+ * size of 128 bytes. One pointer is taken away to point to an array
+ * of cluster sizes that is computed as cylinder groups are inspected.
+ *
+ * Currently, the ffs code uses only the first entry.
*/
#define