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:
parent
e870d1e6f9
commit
cb464c69c0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203764
@ -118,6 +118,8 @@ mkfs(struct partition *pp, char *fsys)
|
|||||||
time_t utime;
|
time_t utime;
|
||||||
quad_t sizepb;
|
quad_t sizepb;
|
||||||
int width;
|
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 */
|
char tmpbuf[100]; /* XXX this will break in about 2,500 years */
|
||||||
union {
|
union {
|
||||||
struct fs fdummy;
|
struct fs fdummy;
|
||||||
@ -170,6 +172,8 @@ mkfs(struct partition *pp, char *fsys)
|
|||||||
if (sblock.fs_avgfpdir <= 0)
|
if (sblock.fs_avgfpdir <= 0)
|
||||||
printf("illegal expected number of files per directory %d\n",
|
printf("illegal expected number of files per directory %d\n",
|
||||||
sblock.fs_avgfpdir), exit(15);
|
sblock.fs_avgfpdir), exit(15);
|
||||||
|
|
||||||
|
restart:
|
||||||
/*
|
/*
|
||||||
* collect and verify the block and fragment sizes
|
* 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, MAXFRAG, sblock.fs_bsize / MAXFRAG);
|
||||||
sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
|
sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
|
||||||
}
|
}
|
||||||
|
if (maxbsize == 0)
|
||||||
|
maxbsize = bsize;
|
||||||
if (maxbsize < bsize || !POWEROF2(maxbsize)) {
|
if (maxbsize < bsize || !POWEROF2(maxbsize)) {
|
||||||
sblock.fs_maxbsize = sblock.fs_bsize;
|
sblock.fs_maxbsize = sblock.fs_bsize;
|
||||||
printf("Extent size set to %d\n", sblock.fs_maxbsize);
|
printf("Extent size set to %d\n", sblock.fs_maxbsize);
|
||||||
@ -225,6 +231,14 @@ mkfs(struct partition *pp, char *fsys)
|
|||||||
} else {
|
} else {
|
||||||
sblock.fs_maxbsize = maxbsize;
|
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;
|
sblock.fs_maxcontig = maxcontig;
|
||||||
if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
|
if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
|
||||||
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
|
* can put into each cylinder group. If this is too big, we reduce
|
||||||
* the density until it fits.
|
* 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;
|
origdensity = density;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fragsperinode = MAX(numfrags(&sblock, density), 1);
|
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);
|
minfpg = fragsperinode * INOPB(&sblock);
|
||||||
if (minfpg > sblock.fs_size)
|
if (minfpg > sblock.fs_size)
|
||||||
minfpg = sblock.fs_size;
|
minfpg = sblock.fs_size;
|
||||||
@ -406,6 +437,9 @@ mkfs(struct partition *pp, char *fsys)
|
|||||||
if (sblock.fs_sbsize > SBLOCKSIZE)
|
if (sblock.fs_sbsize > SBLOCKSIZE)
|
||||||
sblock.fs_sbsize = SBLOCKSIZE;
|
sblock.fs_sbsize = SBLOCKSIZE;
|
||||||
sblock.fs_minfree = minfree;
|
sblock.fs_minfree = minfree;
|
||||||
|
if (maxbpg == 0)
|
||||||
|
sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
|
||||||
|
else
|
||||||
sblock.fs_maxbpg = maxbpg;
|
sblock.fs_maxbpg = maxbpg;
|
||||||
sblock.fs_optim = opt;
|
sblock.fs_optim = opt;
|
||||||
sblock.fs_cgrotor = 0;
|
sblock.fs_cgrotor = 0;
|
||||||
|
@ -79,38 +79,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "newfs.h"
|
#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 Eflag; /* Erase previous disk contents */
|
||||||
int Lflag; /* add a volume label */
|
int Lflag; /* add a volume label */
|
||||||
int Nflag; /* run without writing file system */
|
int Nflag; /* run without writing file system */
|
||||||
@ -387,25 +355,11 @@ main(int argc, char *argv[])
|
|||||||
fsize = MAX(DFL_FRAGSIZE, sectorsize);
|
fsize = MAX(DFL_FRAGSIZE, sectorsize);
|
||||||
if (bsize <= 0)
|
if (bsize <= 0)
|
||||||
bsize = MIN(DFL_BLKSIZE, 8 * fsize);
|
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) {
|
if (minfree < MINFREE && opt != FS_OPTSPACE) {
|
||||||
fprintf(stderr, "Warning: changing optimization to space ");
|
fprintf(stderr, "Warning: changing optimization to space ");
|
||||||
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
|
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
|
||||||
opt = FS_OPTSPACE;
|
opt = FS_OPTSPACE;
|
||||||
}
|
}
|
||||||
if (maxbpg == 0)
|
|
||||||
maxbpg = MAXBLKPG(bsize);
|
|
||||||
realsectorsize = sectorsize;
|
realsectorsize = sectorsize;
|
||||||
if (sectorsize != DEV_BSIZE) { /* XXX */
|
if (sectorsize != DEV_BSIZE) { /* XXX */
|
||||||
int secperblk = sectorsize / DEV_BSIZE;
|
int secperblk = sectorsize / DEV_BSIZE;
|
||||||
|
@ -40,6 +40,38 @@
|
|||||||
|
|
||||||
#include <libufs.h>
|
#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.
|
* variables set up by front end.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user