summaryrefslogtreecommitdiffstats
path: root/sbin/growfs
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2004-10-09 02:53:47 +0000
committerscottl <scottl@FreeBSD.org>2004-10-09 02:53:47 +0000
commitbcad702d798cdd2d713e31f5f56c99261d297531 (patch)
tree39c06af27273e92145959cee51378ca8be3bb672 /sbin/growfs
parent7e9cf9f93431762f97cd654c8a0db849c20b6a5b (diff)
downloadFreeBSD-src-bcad702d798cdd2d713e31f5f56c99261d297531.zip
FreeBSD-src-bcad702d798cdd2d713e31f5f56c99261d297531.tar.gz
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.
Diffstat (limited to 'sbin/growfs')
-rw-r--r--sbin/growfs/growfs.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index cf58071..8423743 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -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 */
}
OpenPOWER on IntegriCloud