mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-25 11:37:56 +00:00
3 important fixes for growfs:
1) ginode() is passed a cylinder group number and inode number. The inode number is relative to the cg. Use this relative number rather than the absolute inode number when searching the cg inode bitmap to see if the inode is allocated. Using the absolute number quickly runs the check off the end of the array and causes invalid inodes to be referenced. 2) ginode() checks the absolute indoe number to make sure that it is greater than ROOTINO. However, the caller loops through all of the possible inode numbers and directly passes in values that are < ROOTINO. Instead of halting the program with an error, just return NULL. 3) When allocating new cylinder groups, growfs was initializing all of the inodes in the group regardless of this only being required for UFS1. Not doing this for UFS2 provides a significant performance increase. These fixes allow growing a filesystem beyond a trivial amount and have been tested to grow an 8GB filesystem to 1.9TB. Much more testing would be appreciated. Obtained from: Sandvine, Inc.
This commit is contained in:
parent
42c7735ce5
commit
e7c4605481
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136289
@ -447,22 +447,30 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
|
||||
setbit(cg_inosused(&acg), i);
|
||||
acg.cg_cs.cs_nifree--;
|
||||
}
|
||||
bzero(iobuf, sblock.fs_bsize);
|
||||
for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
|
||||
dp1 = (struct ufs1_dinode *)iobuf;
|
||||
dp2 = (struct ufs2_dinode *)iobuf;
|
||||
/*
|
||||
* XXX Newfs writes out two blocks of initialized inodes
|
||||
* unconditionally. Should we check here to make sure that they
|
||||
* were actually written?
|
||||
*/
|
||||
if (sblock.fs_magic == FS_UFS1_MAGIC) {
|
||||
bzero(iobuf, sblock.fs_bsize);
|
||||
for (i = 2 * sblock.fs_frag; i < sblock.fs_ipg / INOPF(&sblock);
|
||||
i += sblock.fs_frag) {
|
||||
dp1 = (struct ufs1_dinode *)iobuf;
|
||||
dp2 = (struct ufs2_dinode *)iobuf;
|
||||
#ifdef FSIRAND
|
||||
for (j = 0; j < INOPB(&sblock); j++)
|
||||
if (sblock.fs_magic == FS_UFS1_MAGIC) {
|
||||
dp1->di_gen = random();
|
||||
dp1++;
|
||||
} else {
|
||||
dp2->di_gen = random();
|
||||
dp2++;
|
||||
}
|
||||
for (j = 0; j < INOPB(&sblock); j++)
|
||||
if (sblock.fs_magic == FS_UFS1_MAGIC) {
|
||||
dp1->di_gen = random();
|
||||
dp1++;
|
||||
} else {
|
||||
dp2->di_gen = random();
|
||||
dp2++;
|
||||
}
|
||||
#endif
|
||||
wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
|
||||
sblock.fs_bsize, iobuf, fso, Nflag);
|
||||
wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
|
||||
sblock.fs_bsize, iobuf, fso, Nflag);
|
||||
}
|
||||
}
|
||||
if (cylno > 0) {
|
||||
/*
|
||||
@ -1493,7 +1501,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
|
||||
for(cylno=0; cylno<osblock.fs_ncg; cylno++) {
|
||||
DBG_PRINT1("scg doing cg (%d)\n",
|
||||
cylno);
|
||||
for(inc=osblock.fs_ipg-1 ; inc>=0 ; inc--) {
|
||||
for(inc=osblock.fs_ipg-1 ; inc>0 ; inc--) {
|
||||
updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag);
|
||||
}
|
||||
}
|
||||
@ -1549,6 +1557,9 @@ rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi)
|
||||
|
||||
DBG_ENTER;
|
||||
|
||||
if (bno < 0) {
|
||||
err(32, "rdfs: attempting to read negative block number\n");
|
||||
}
|
||||
if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) {
|
||||
err(33, "rdfs: seek error: %jd", (intmax_t)bno);
|
||||
}
|
||||
@ -1846,12 +1857,24 @@ ginode(ino_t inumber, int fsi, int cg)
|
||||
|
||||
DBG_ENTER;
|
||||
|
||||
inumber += (cg * sblock.fs_ipg);
|
||||
/*
|
||||
* The inumber passed in is relative to the cg, so use it here to see
|
||||
* if the inode has been allocated yet.
|
||||
*/
|
||||
if (isclr(cg_inosused(&aocg), inumber)) {
|
||||
DBG_LEAVE;
|
||||
return NULL;
|
||||
}
|
||||
if (inumber < ROOTINO || inumber > maxino)
|
||||
/*
|
||||
* Now make the inumber relative to the entire inode space so it can
|
||||
* be sanity checked.
|
||||
*/
|
||||
inumber += (cg * sblock.fs_ipg);
|
||||
if (inumber < ROOTINO) {
|
||||
DBG_LEAVE;
|
||||
return NULL;
|
||||
}
|
||||
if (inumber > maxino)
|
||||
errx(8, "bad inode number %d to ginode", inumber);
|
||||
if (startinum == 0 ||
|
||||
inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
|
||||
@ -2385,10 +2408,6 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
|
||||
|
||||
DBG_ENTER;
|
||||
|
||||
/*
|
||||
* XXX We should skip unused inodes even from being read from disk
|
||||
* here by using the bitmap.
|
||||
*/
|
||||
ino = ginode(in, fsi, cg);
|
||||
if (ino == NULL) {
|
||||
DBG_LEAVE;
|
||||
@ -2399,7 +2418,8 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
|
||||
DBG_LEAVE;
|
||||
return; /* only check DIR, FILE, LINK */
|
||||
}
|
||||
if (mode == IFLNK && DIP(ino, di_size) < (u_int64_t) sblock.fs_maxsymlinklen) {
|
||||
if (mode == IFLNK &&
|
||||
DIP(ino, di_size) < (u_int64_t) sblock.fs_maxsymlinklen) {
|
||||
DBG_LEAVE;
|
||||
return; /* skip short symlinks */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user