diff options
author | iedowse <iedowse@FreeBSD.org> | 2001-01-15 18:30:40 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2001-01-15 18:30:40 +0000 |
commit | 5cc8ff22fa0677114bfd33f769881dabb84ca4db (patch) | |
tree | 09bf1796322782a26e1cea09661ff15cfb3b988a /sys/ufs/ffs/ffs_vfsops.c | |
parent | 77edbf4641ec8272ace4ef23c52578a20859f337 (diff) | |
download | FreeBSD-src-5cc8ff22fa0677114bfd33f769881dabb84ca4db.zip FreeBSD-src-5cc8ff22fa0677114bfd33f769881dabb84ca4db.tar.gz |
The ffs superblock includes a 128-byte region for use by temporary
in-core pointers to summary information. An array in this region
(fs_csp) could overflow on filesystems with a very large number of
cylinder groups (~16000 on i386 with 8k blocks). When this happens,
other fields in the superblock get corrupted, and fsck refuses to
check the filesystem.
Solve this problem by replacing the fs_csp array in 'struct fs'
with a single pointer, and add padding to keep the length of the
128-byte region fixed. Update the kernel and userland utilities
to use just this single pointer.
With this change, the kernel no longer makes use of the superblock
fields 'fs_csshift' and 'fs_csmask'. Add a comment to newfs/mkfs.c
to indicate that these fields must be calculated for compatibility
with older kernels.
Reviewed by: mckusick
Diffstat (limited to 'sys/ufs/ffs/ffs_vfsops.c')
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b103394..c05beef 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -365,7 +365,7 @@ ffs_reload(mp, cred, p) { 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 @@ ffs_reload(mp, cred, p) * 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 @@ ffs_reload(mp, cred, p) * 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 @@ ffs_reload(mp, cred, p) 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 @@ ffs_mountfs(devvp, mp, p, malloctype) 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 @@ ffs_mountfs(devvp, mp, p, malloctype) 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 @@ ffs_mountfs(devvp, mp, p, malloctype) 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 @@ ffs_unmount(mp, mntflags, p) 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 @@ ffs_sbupdate(mp, waitfor) 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 @@ ffs_sbupdate(mp, waitfor) 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) |