summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_vfsops.c
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2001-01-15 18:30:40 +0000
committeriedowse <iedowse@FreeBSD.org>2001-01-15 18:30:40 +0000
commit5cc8ff22fa0677114bfd33f769881dabb84ca4db (patch)
tree09bf1796322782a26e1cea09661ff15cfb3b988a /sys/ufs/ffs/ffs_vfsops.c
parent77edbf4641ec8272ace4ef23c52578a20859f337 (diff)
downloadFreeBSD-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.c31
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)
OpenPOWER on IntegriCloud