Ensure that newfs will never create a filesystem with more than 2^32

inodes by cutting back on the number of inodes per cylinder group if
necessary to stay under the limit. For a default (16K block) file
system, this limit begins to take effect for file systems above 32Tb.

This fix is in addition to -r203763 which corrected a problem in the
kernel that treated 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.

Reported by: Scott Burns, John Kilburg, Bruce Evans
Followup by: Jeff Roberson
PR:          133980
MFC after:   2 weeks
This commit is contained in:
Kirk McKusick 2010-02-10 20:17:46 +00:00
parent e870d1e6f9
commit cb464c69c0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203764
3 changed files with 67 additions and 47 deletions

View File

@ -118,6 +118,8 @@ mkfs(struct partition *pp, char *fsys)
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 +172,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 +220,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 +231,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 +329,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 +437,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;

View File

@ -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;

View File

@ -40,6 +40,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.
*/