summaryrefslogtreecommitdiffstats
path: root/sbin
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 /sbin
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 'sbin')
-rw-r--r--sbin/dumpfs/dumpfs.c4
-rw-r--r--sbin/fsck_ffs/fsutil.c2
-rw-r--r--sbin/fsck_ffs/setup.c7
-rw-r--r--sbin/fsck_ifs/fsutil.c2
-rw-r--r--sbin/fsck_ifs/setup.c7
-rw-r--r--sbin/newfs/mkfs.c5
6 files changed, 17 insertions, 10 deletions
diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c
index 8e0416e..b5d1df0 100644
--- a/sbin/dumpfs/dumpfs.c
+++ b/sbin/dumpfs/dumpfs.c
@@ -205,15 +205,15 @@ dumpfs(name)
}
}
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++) {
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 2cdb252..2217f3c 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -249,7 +249,7 @@ flush(fd, bp)
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);
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 6c4098c..0c2e8ac 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -258,11 +258,11 @@ setup(dev)
* 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 @@ readsb(listerr)
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,
diff --git a/sbin/fsck_ifs/fsutil.c b/sbin/fsck_ifs/fsutil.c
index 2cdb252..2217f3c 100644
--- a/sbin/fsck_ifs/fsutil.c
+++ b/sbin/fsck_ifs/fsutil.c
@@ -249,7 +249,7 @@ flush(fd, bp)
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);
diff --git a/sbin/fsck_ifs/setup.c b/sbin/fsck_ifs/setup.c
index b9c3148..52fb849 100644
--- a/sbin/fsck_ifs/setup.c
+++ b/sbin/fsck_ifs/setup.c
@@ -258,11 +258,11 @@ setup(dev)
* 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 @@ readsb(listerr)
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,
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index 7e5ea14..4cf854b 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -633,6 +633,11 @@ next:
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)
OpenPOWER on IntegriCloud