summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2010-02-26 21:49:11 +0000
committermckusick <mckusick@FreeBSD.org>2010-02-26 21:49:11 +0000
commitddfa9b895b20fc04a73aee44c52f2db7b47d48b6 (patch)
tree50841b62bf102e5e0e804d7853a81fa5bf846be9 /sbin
parentc9d1943ae9cdd1e4995d0fcf22efa13be20616ab (diff)
downloadFreeBSD-src-ddfa9b895b20fc04a73aee44c52f2db7b47d48b6.zip
FreeBSD-src-ddfa9b895b20fc04a73aee44c52f2db7b47d48b6.tar.gz
MFC of 203763, 203764, 203768, 203769, 203770, 203782, and 203784.
These fixes correct a problem in the file system that treats large inode numbers as negative rather than unsigned. For a default (16K block) file system, this bug began to show up at a file system size above about 16Tb. These fixes also update newfs to ensure that it will never create a filesystem with more than 2^32 inodes. They also update libufs, tunefs, and growfs so that they properly handle inode numbers as unsigned. Reported by: Scott Burns, John Kilburg, and Bruce Evans Followup by: Jeff Roberson PR: 133980
Diffstat (limited to 'sbin')
-rw-r--r--sbin/growfs/growfs.c16
-rw-r--r--sbin/newfs/mkfs.c59
-rw-r--r--sbin/newfs/newfs.c46
-rw-r--r--sbin/newfs/newfs.h32
-rw-r--r--sbin/tunefs/tunefs.c4
5 files changed, 90 insertions, 67 deletions
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index cc58fc6..bf803ac 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -174,10 +174,9 @@ static void
growfs(int fsi, int fso, unsigned int Nflag)
{
DBG_FUNC("growfs")
- int i;
- int cylno, j;
time_t utime;
- int width;
+ uint cylno;
+ int i, j, width;
char tmpbuf[100];
#ifdef FSIRAND
static int randinit=0;
@@ -373,10 +372,11 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
{
DBG_FUNC("initcg")
static void *iobuf;
- long d, dlower, dupper, blkno, start;
+ long blkno, start;
ufs2_daddr_t i, cbase, dmax;
struct ufs1_dinode *dp1;
struct csum *cs;
+ uint d, dupper, dlower;
if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize)) == NULL) {
errx(37, "panic: cannot allocate I/O buffer");
@@ -431,7 +431,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
acg.cg_nextfreeoff = acg.cg_clusteroff +
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
}
- if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
+ if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
/*
* This should never happen as we would have had that panic
* already on file system creation
@@ -746,7 +746,7 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
* needed, update the free space in the superblock.
*/
acg.cg_time = utime;
- if (cylno == sblock.fs_ncg - 1) {
+ if ((unsigned)cylno == sblock.fs_ncg - 1) {
/*
* This is still the last cylinder group.
*/
@@ -940,8 +940,8 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
int ocscg, ncscg;
int blocks;
ufs2_daddr_t cbase, dupper, odupper, d, f, g;
- int ind;
- int cylno, inc;
+ int ind, inc;
+ uint cylno;
struct gfs_bpp *bp;
int i, l;
int lcs=0;
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index f99cb14..b7a6b52 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -114,10 +114,13 @@ void
mkfs(struct partition *pp, char *fsys)
{
int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
- long i, j, cylno, csfrags;
+ long i, j, csfrags;
+ uint cg;
time_t utime;
quad_t sizepb;
int width;
+ ino_t maxinum;
+ int minfragsperinode; /* minimum ratio of frags to inodes */
char tmpbuf[100]; /* XXX this will break in about 2,500 years */
union {
struct fs fdummy;
@@ -170,6 +173,8 @@ mkfs(struct partition *pp, char *fsys)
if (sblock.fs_avgfpdir <= 0)
printf("illegal expected number of files per directory %d\n",
sblock.fs_avgfpdir), exit(15);
+
+restart:
/*
* collect and verify the block and fragment sizes
*/
@@ -216,6 +221,8 @@ mkfs(struct partition *pp, char *fsys)
sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG);
sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
}
+ if (maxbsize == 0)
+ maxbsize = bsize;
if (maxbsize < bsize || !POWEROF2(maxbsize)) {
sblock.fs_maxbsize = sblock.fs_bsize;
printf("Extent size set to %d\n", sblock.fs_maxbsize);
@@ -225,6 +232,14 @@ mkfs(struct partition *pp, char *fsys)
} else {
sblock.fs_maxbsize = maxbsize;
}
+ /*
+ * Maxcontig sets the default for the maximum number of blocks
+ * that may be allocated sequentially. With file system clustering
+ * it is possible to allocate contiguous blocks up to the maximum
+ * transfer size permitted by the controller or buffering.
+ */
+ if (maxcontig == 0)
+ maxcontig = MAX(1, MAXPHYS / bsize);
sblock.fs_maxcontig = maxcontig;
if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
@@ -315,9 +330,26 @@ mkfs(struct partition *pp, char *fsys)
* can put into each cylinder group. If this is too big, we reduce
* the density until it fits.
*/
+ maxinum = (((int64_t)(1)) << 32) - INOPB(&sblock);
+ minfragsperinode = 1 + fssize / maxinum;
+ if (density == 0) {
+ density = MAX(NFPI, minfragsperinode) * fsize;
+ } else if (density < minfragsperinode * fsize) {
+ origdensity = density;
+ density = minfragsperinode * fsize;
+ fprintf(stderr, "density increased from %d to %d\n",
+ origdensity, density);
+ }
origdensity = density;
for (;;) {
fragsperinode = MAX(numfrags(&sblock, density), 1);
+ if (fragsperinode < minfragsperinode) {
+ bsize <<= 1;
+ fsize <<= 1;
+ printf("Block size too small for a file system %s %d\n",
+ "of this size. Increasing blocksize to", bsize);
+ goto restart;
+ }
minfpg = fragsperinode * INOPB(&sblock);
if (minfpg > sblock.fs_size)
minfpg = sblock.fs_size;
@@ -406,7 +438,10 @@ mkfs(struct partition *pp, char *fsys)
if (sblock.fs_sbsize > SBLOCKSIZE)
sblock.fs_sbsize = SBLOCKSIZE;
sblock.fs_minfree = minfree;
- sblock.fs_maxbpg = maxbpg;
+ if (maxbpg == 0)
+ sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
+ else
+ sblock.fs_maxbpg = maxbpg;
sblock.fs_optim = opt;
sblock.fs_cgrotor = 0;
sblock.fs_pendingblocks = 0;
@@ -476,9 +511,9 @@ mkfs(struct partition *pp, char *fsys)
fsdummy.fs_magic = 0;
bwrite(&disk, part_ofs + SBLOCK_UFS1 / disk.d_bsize,
chdummy, SBLOCKSIZE);
- for (i = 0; i < fsdummy.fs_ncg; i++)
+ for (cg = 0; cg < fsdummy.fs_ncg; cg++)
bwrite(&disk, part_ofs + fsbtodb(&fsdummy,
- cgsblock(&fsdummy, i)), chdummy, SBLOCKSIZE);
+ cgsblock(&fsdummy, cg)), chdummy, SBLOCKSIZE);
}
}
if (!Nflag)
@@ -516,11 +551,11 @@ mkfs(struct partition *pp, char *fsys)
* writing out in each cylinder group.
*/
bcopy((char *)&sblock, iobuf, SBLOCKSIZE);
- for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
- initcg(cylno, utime);
+ for (cg = 0; cg < sblock.fs_ncg; cg++) {
+ initcg(cg, utime);
j = snprintf(tmpbuf, sizeof(tmpbuf), " %jd%s",
- (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
- cylno < (sblock.fs_ncg-1) ? "," : "");
+ (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cg)),
+ cg < (sblock.fs_ncg-1) ? "," : "");
if (j < 0)
tmpbuf[j = 0] = '\0';
if (i + j >= width) {
@@ -574,7 +609,8 @@ mkfs(struct partition *pp, char *fsys)
void
initcg(int cylno, time_t utime)
{
- long i, j, d, dlower, dupper, blkno, start;
+ long blkno, start;
+ uint i, j, d, dlower, dupper;
ufs2_daddr_t cbase, dmax;
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
@@ -631,7 +667,7 @@ initcg(int cylno, time_t utime)
acg.cg_nextfreeoff = acg.cg_clusteroff +
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
}
- if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
+ if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
printf("Panic: cylinder group too big\n");
exit(37);
}
@@ -880,7 +916,8 @@ makedir(struct direct *protodir, int entries)
ufs2_daddr_t
alloc(int size, int mode)
{
- int i, d, blkno, frag;
+ int i, blkno, frag;
+ uint d;
bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
sblock.fs_cgsize);
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index b70ce1b..8867306 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -79,38 +79,6 @@ __FBSDID("$FreeBSD$");
#include "newfs.h"
-/*
- * The following two constants set the default block and fragment sizes.
- * Both constants must be a power of 2 and meet the following constraints:
- * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
- * sectorsize <= DESFRAGSIZE <= DESBLKSIZE
- * DESBLKSIZE / DESFRAGSIZE <= 8
- */
-#define DFL_FRAGSIZE 2048
-#define DFL_BLKSIZE 16384
-
-/*
- * Cylinder groups may have up to MAXBLKSPERCG blocks. The actual
- * number used depends upon how much information can be stored
- * in a cylinder group map which must fit in a single file system
- * block. The default is to use as many as possible blocks per group.
- */
-#define MAXBLKSPERCG 0x7fffffff /* desired fs_fpg ("infinity") */
-
-/*
- * MAXBLKPG determines the maximum number of data blocks which are
- * placed in a single cylinder group. The default is one indirect
- * block worth of data blocks.
- */
-#define MAXBLKPG(bsize) ((bsize) / sizeof(ufs2_daddr_t))
-
-/*
- * Each file system has a number of inodes statically allocated.
- * We allocate one inode slot per NFPI fragments, expecting this
- * to be far more than we will ever need.
- */
-#define NFPI 4
-
int Eflag; /* Erase previous disk contents */
int Lflag; /* add a volume label */
int Nflag; /* run without writing file system */
@@ -387,25 +355,11 @@ main(int argc, char *argv[])
fsize = MAX(DFL_FRAGSIZE, sectorsize);
if (bsize <= 0)
bsize = MIN(DFL_BLKSIZE, 8 * fsize);
- if (maxbsize == 0)
- maxbsize = bsize;
- /*
- * Maxcontig sets the default for the maximum number of blocks
- * that may be allocated sequentially. With file system clustering
- * it is possible to allocate contiguous blocks up to the maximum
- * transfer size permitted by the controller or buffering.
- */
- if (maxcontig == 0)
- maxcontig = MAX(1, MAXPHYS / bsize);
- if (density == 0)
- density = NFPI * fsize;
if (minfree < MINFREE && opt != FS_OPTSPACE) {
fprintf(stderr, "Warning: changing optimization to space ");
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
opt = FS_OPTSPACE;
}
- if (maxbpg == 0)
- maxbpg = MAXBLKPG(bsize);
realsectorsize = sectorsize;
if (sectorsize != DEV_BSIZE) { /* XXX */
int secperblk = sectorsize / DEV_BSIZE;
diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h
index 0d7cb62..9da3226 100644
--- a/sbin/newfs/newfs.h
+++ b/sbin/newfs/newfs.h
@@ -41,6 +41,38 @@
#include <libufs.h>
/*
+ * The following two constants set the default block and fragment sizes.
+ * Both constants must be a power of 2 and meet the following constraints:
+ * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
+ * sectorsize <= DESFRAGSIZE <= DESBLKSIZE
+ * DESBLKSIZE / DESFRAGSIZE <= 8
+ */
+#define DFL_FRAGSIZE 2048
+#define DFL_BLKSIZE 16384
+
+/*
+ * Cylinder groups may have up to MAXBLKSPERCG blocks. The actual
+ * number used depends upon how much information can be stored
+ * in a cylinder group map which must fit in a single file system
+ * block. The default is to use as many as possible blocks per group.
+ */
+#define MAXBLKSPERCG 0x7fffffff /* desired fs_fpg ("infinity") */
+
+/*
+ * MAXBLKPG determines the maximum number of data blocks which are
+ * placed in a single cylinder group. The default is one indirect
+ * block worth of data blocks.
+ */
+#define MAXBLKPG(bsize) ((bsize) / sizeof(ufs2_daddr_t))
+
+/*
+ * Each file system has a number of inodes statically allocated.
+ * We allocate one inode slot per NFPI fragments, expecting this
+ * to be far more than we will ever need.
+ */
+#define NFPI 4
+
+/*
* variables set up by front end.
*/
extern int Eflag; /* Erase previous disk contents */
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index 2b263bb..57dfbcb 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -286,7 +286,7 @@ main(int argc, char *argv[])
}
if (fflag) {
name = "average file size";
- if (sblock.fs_avgfilesize == fvalue) {
+ if (sblock.fs_avgfilesize == (unsigned)fvalue) {
warnx("%s remains unchanged as %d", name, fvalue);
}
else {
@@ -389,7 +389,7 @@ main(int argc, char *argv[])
}
if (sflag) {
name = "expected number of files per directory";
- if (sblock.fs_avgfpdir == svalue) {
+ if (sblock.fs_avgfpdir == (unsigned)svalue) {
warnx("%s remains unchanged as %d", name, svalue);
}
else {
OpenPOWER on IntegriCloud