Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Sep 2001 18:06:45 -0700 (PDT)
From:      Matt Dillon <dillon@earth.backplane.com>
To:        freebsd-stable@freebsd.org
Cc:        Mike Silbersack <silby@silby.com>, Ian Dowse <iedowse@maths.tcd.ie>, Kirk McKusick <mckusick@mckusick.com>, Grigoriy Orlov <gluk@ptci.ru>
Subject:   dirpref MFC to -stable: patch set to test
Message-ID:  <200109190106.f8J16jv50999@earth.backplane.com>

next in thread | raw e-mail | index | archive | help
    Ok folks, here is a patchset that MFC's the dirpref code from -current
    to -stable.  I have done some very simple testing, but I need a couple
    more eyes on the code.  I want to make sure that I have MFC'd all
    necessary rcs pieces.

    This is what I have MFC'd:

	1.36                    src/sbin/newfs/mkfs.c
	1.35                    src/sbin/newfs/newfs.c
	1.16                    src/sbin/tunefs/tunefs.c
	1.75                    src/sys/ufs/ffs/ffs_alloc.c
	1.144, 1.148, 1.159     src/sys/ufs/ffs/ffs_vfsops.c
	1.20                    src/sys/ufs/ffs/fs.h

	1.37                    src/sbin/newfs/newfs.8
	1.15                    src/sbin/tunefs/tunefs.8

	1.22, 1.25              src/sbin/fsck_ffs/setup.c (note: fsck/setup.c
							in -stable)

    I have also incorporated the snapshot changes to the superblock (fs.h)
    and some of the initialization code for fsck (setup.c) to try to make
    the -stable fsck compatible with a -current filesystem.

    I intend to commit this patchset to -stable on Friday if no issues come
    up.

    testers testers...

						-Matt

Index: sbin/fsck/setup.c
===================================================================
RCS file: /home/ncvs/src/sbin/fsck/Attic/setup.c,v
retrieving revision 1.17.2.2
diff -u -r1.17.2.2 setup.c
--- sbin/fsck/setup.c	2001/02/06 20:39:09	1.17.2.2
+++ sbin/fsck/setup.c	2001/09/19 00:29:36
@@ -380,6 +380,11 @@
 	memmove(altsblock.fs_ocsp, sblock.fs_ocsp, sizeof sblock.fs_ocsp);
 	altsblock.fs_csp = sblock.fs_csp;
 	altsblock.fs_maxcluster = sblock.fs_maxcluster;
+	altsblock.fs_contigdirs = sblock.fs_contigdirs;
+	altsblock.fs_avgfilesize = sblock.fs_avgfilesize;
+	altsblock.fs_avgfpdir = sblock.fs_avgfpdir;
+	altsblock.fs_pendingblocks = sblock.fs_pendingblocks;
+	altsblock.fs_pendinginodes = sblock.fs_pendinginodes;
 	memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
 	memmove(altsblock.fs_sparecon,
 		sblock.fs_sparecon, sizeof sblock.fs_sparecon);
Index: sbin/newfs/mkfs.c
===================================================================
RCS file: /home/ncvs/src/sbin/newfs/mkfs.c,v
retrieving revision 1.29.2.5
diff -u -r1.29.2.5 mkfs.c
--- sbin/newfs/mkfs.c	2001/08/01 08:41:02	1.29.2.5
+++ sbin/newfs/mkfs.c	2001/09/19 00:07:12
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)mkfs.c	8.11 (Berkeley) 5/3/95";
 #endif
 static const char rcsid[] =
-  "$FreeBSD: src/sbin/newfs/mkfs.c,v 1.29.2.5 2001/08/01 08:41:02 obrien Exp $";
+  "$FreeBSD: src/sbin/newfs/mkfs.c,v 1.36 2001/04/10 08:38:52 mckusick Exp $";
 #endif /* not lint */
 
 #include <err.h>
@@ -119,6 +119,8 @@
 extern int	nrpos;		/* # of distinguished rotational positions */
 extern int	bbsize;		/* boot block size */
 extern int	sbsize;		/* superblock size */
+extern int	avgfilesize;	/* expected average file size */
+extern int	avgfilesperdir;	/* expected number of files per directory */
 extern u_long	memleft;	/* virtual memory available */
 extern caddr_t	membase;	/* start address of memory based filesystem */
 extern char *	filename;
@@ -273,6 +275,17 @@
 		printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14);
 	if (sblock.fs_nsect <= 0)
 		printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
+	/*
+	 * collect and verify the filesystem density info
+	 */
+	sblock.fs_avgfilesize = avgfilesize;
+	sblock.fs_avgfpdir = avgfilesperdir;
+	if (sblock.fs_avgfilesize <= 0)
+		printf("illegal expected average file size %d\n",
+		    sblock.fs_avgfilesize), exit(14);
+	if (sblock.fs_avgfpdir <= 0)
+		printf("illegal expected number of files per directory %d\n",
+		    sblock.fs_avgfpdir), exit(15);
 	/*
 	 * collect and verify the block and fragment sizes
 	 */
Index: sbin/newfs/newfs.8
===================================================================
RCS file: /home/ncvs/src/sbin/newfs/newfs.8,v
retrieving revision 1.26.2.7
diff -u -r1.26.2.7 newfs.8
--- sbin/newfs/newfs.8	2001/07/22 11:32:31	1.26.2.7
+++ sbin/newfs/newfs.8	2001/09/19 00:27:33
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)newfs.8	8.6 (Berkeley) 5/3/95
-.\" $FreeBSD: src/sbin/newfs/newfs.8,v 1.26.2.7 2001/07/22 11:32:31 dd Exp $
+.\" $FreeBSD: src/sbin/newfs/newfs.8,v 1.37 2001/04/10 10:36:43 nik Exp $
 .\"
 .Dd December 19, 2000
 .Dt NEWFS 8
@@ -50,6 +50,8 @@
 .Op Fl d Ar rotdelay
 .Op Fl e Ar maxbpg
 .Op Fl f Ar frag-size
+.Op Fl g Ar avgfilesize
+.Op Fl h Ar avfpdir
 .Op Fl i Ar bytes
 .Op Fl k Ar skew
 .Op Fl l Ar interleave
@@ -196,6 +198,10 @@
 and
 .Ar blocksize .
 The default is 1024 bytes.
+.It Fl g Ar avgfilesize
+The expected average file size for the file system.
+.It Fl h Ar avgfpdir
+The expected average number of files per directory on the file system.
 .It Fl i Ar number of bytes per inode
 Specify the density of inodes in the file system.
 The default is to create an inode for every
Index: sbin/newfs/newfs.c
===================================================================
RCS file: /home/ncvs/src/sbin/newfs/newfs.c,v
retrieving revision 1.30.2.4
diff -u -r1.30.2.4 newfs.c
--- sbin/newfs/newfs.c	2001/05/28 02:34:31	1.30.2.4
+++ sbin/newfs/newfs.c	2001/09/19 00:07:36
@@ -42,7 +42,7 @@
 static char sccsid[] = "@(#)newfs.c	8.13 (Berkeley) 5/1/95";
 #endif
 static const char rcsid[] =
-  "$FreeBSD: src/sbin/newfs/newfs.c,v 1.30.2.4 2001/05/28 02:34:31 obrien Exp $";
+  "$FreeBSD: src/sbin/newfs/newfs.c,v 1.35 2001/04/10 08:38:52 mckusick Exp $";
 #endif /* not lint */
 
 /*
@@ -162,9 +162,7 @@
  * The number of sectors are used to determine the size of a cyl-group.
  * Kirk suggested one or two meg per "cylinder" so we say two.
  */
-
 #define NTRACKS		1	/* number of heads */
-
 #define NSECTORS	4096	/* number of sectors */
 
 int	mfs;			/* run as the memory based filesystem */
@@ -198,6 +196,8 @@
 int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
 int	maxbpg;			/* maximum blocks per file in a cyl group */
 int	nrpos = NRPOS;		/* # of distinguished rotational positions */
+int	avgfilesize = AVFILESIZ;/* expected average file size */
+int	avgfilesperdir = AFPDIR;/* expected number of files per directory */
 int	bbsize = BBSIZE;	/* boot block size */
 int	sbsize = SBSIZE;	/* superblock size */
 int	mntflags = MNT_ASYNC;	/* flags to be passed to mount */
@@ -249,8 +249,8 @@
 	}
 
 	opstring = mfs ?
-	    "NF:T:Ua:b:c:d:e:f:i:m:o:s:" :
-	    "NOS:T:Ua:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:vx:";
+	    "NF:T:Ua:b:c:d:e:f:g:h:i:m:o:s:" :
+	    "NOS:T:Ua:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:vx:";
 	while ((ch = getopt(argc, argv, opstring)) != -1)
 		switch (ch) {
 		case 'N':
@@ -301,6 +301,14 @@
 			if ((fsize = atoi(optarg)) <= 0)
 				fatal("%s: bad fragment size", optarg);
 			break;
+		case 'g':
+			if ((avgfilesize = atoi(optarg)) <= 0)
+				fatal("%s: bad average file size", optarg);
+			break;
+		case 'h':
+			if ((avgfilesperdir = atoi(optarg)) <= 0)
+				fatal("%s: bad average files per dir", optarg);
+			break;
 		case 'i':
 			if ((density = atoi(optarg)) <= 0)
 				fatal("%s: bad bytes per inode", optarg);
@@ -761,6 +769,8 @@
 	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
 	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
 	fprintf(stderr, "\t-f frag size\n");
+	fprintf(stderr, "\t-g average file size\n");
+	fprintf(stderr, "\t-h average files per directory\n");
 	fprintf(stderr, "\t-i number of bytes per inode\n");
 	fprintf(stderr, "\t-k sector 0 skew, per track\n");
 	fprintf(stderr, "\t-l hardware sector interleave\n");
Index: sbin/tunefs/tunefs.8
===================================================================
RCS file: /home/ncvs/src/sbin/tunefs/tunefs.8,v
retrieving revision 1.11.2.1
diff -u -r1.11.2.1 tunefs.8
--- sbin/tunefs/tunefs.8	2000/12/08 14:04:21	1.11.2.1
+++ sbin/tunefs/tunefs.8	2001/09/19 00:27:17
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)tunefs.8	8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/sbin/tunefs/tunefs.8,v 1.11.2.1 2000/12/08 14:04:21 ru Exp $
+.\" $FreeBSD: src/sbin/tunefs/tunefs.8,v 1.15 2001/04/10 10:36:44 nik Exp $
 .\"
 .Dd December 11, 1993
 .Dt TUNEFS 8
@@ -44,11 +44,13 @@
 .Op Fl a Ar maxcontig
 .Op Fl d Ar rotdelay
 .Op Fl e Ar maxbpg
+.Op Fl f Ar avgfilesize
 .Op Fl m Ar minfree
 .Bk -words
 .Op Fl n Ar enable | disable
 .Op Fl o Ar optimize_preference
 .Op Fl p
+.Op Fl s Ar avgfpdir
 .Ek
 .Op Ar special | Ar filesystem
 .Sh DESCRIPTION
@@ -92,6 +94,8 @@
 in a cylinder group before seeking elsewhere.
 For file systems with exclusively large files,
 this parameter should be set higher.
+.It Fl f Ar avgfilezsize
+Specify the expected average file size.
 .It Fl m Ar minfree
 Specify the percentage of space held back
 from normal users; the minimum free space threshold.
@@ -122,6 +126,8 @@
 obtained in the
 .Xr dumpfs 8
 manual page.
+.It Fl s Ar avgfpdir
+Specify the expected number of files per directory.
 .El
 .Sh ERRORS
 If
Index: sbin/tunefs/tunefs.c
===================================================================
RCS file: /home/ncvs/src/sbin/tunefs/tunefs.c,v
retrieving revision 1.11.2.3
diff -u -r1.11.2.3 tunefs.c
--- sbin/tunefs/tunefs.c	2001/08/01 23:13:18	1.11.2.3
+++ sbin/tunefs/tunefs.c	2001/09/19 00:50:46
@@ -180,6 +180,24 @@
 				sblock.fs_maxbpg = i;
 				continue;
 
+			case 'f':
+				name = "average file size";
+				if (argc < 1)
+					errx(10, "-a: missing %s", name);
+				argc--, argv++;
+				i = atoi(*argv);
+				if (i < 1)
+					errx(10, "%s must be >= 1 (was %s)", name, *argv);
+				if (sblock.fs_avgfilesize == i) {
+					warnx("%s remains unchanged as %d",
+						name, i);
+				} else {
+					warnx("%s changes from %d to %d",
+						name, sblock.fs_avgfilesize, i);
+					sblock.fs_avgfilesize = i;
+				}
+				break;
+
 			case 'm':
 				name = "minimum percentage of free space";
 				if (argc < 1)
@@ -247,6 +265,24 @@
 					warnx(OPTWARN, "space", "<", MINFREE);
 				continue;
 
+			case 's':
+				name = "expected number of files per directory";
+				if (argc < 1)
+					errx(10, "-a: missing %s", name);
+				argc--, argv++;
+				i = atoi(*argv);
+				if (i < 1)
+					errx(10, "%s must be >= 1 (was %s)", name, *argv);
+				if (sblock.fs_avgfpdir == i) {
+					warnx("%s remains unchanged as %d",
+						name, i);
+				} else {
+					warnx("%s changes from %d to %d",
+						name, sblock.fs_avgfpdir, i);
+					sblock.fs_avgfpdir = i;
+				}
+				break;
+
 			default:
 				usage();
 			}
@@ -268,9 +304,9 @@
 usage()
 {
 	fprintf(stderr, "%s\n%s\n%s\n",
-"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-m minfree]",
-"              [-p] [-n enable | disable] [-o optimize_preference]",
-"              [special | filesystem]");
+"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-f avgfilesize]",
+"              [-m minfree] [-p] [-n enable | disable] [-o space | time]",
+"              [-s filesperdir] [special | filesystem]");
 	exit(2);
 }
 
@@ -327,6 +363,10 @@
 	      sblock.fs_rotdelay);
 	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
 	      sblock.fs_maxbpg);
+	warnx("average file size: (-f)                            %d",
+	      sblock.fs_avgfilesize);
+	warnx("average number of files in a directory: (-s)       %d",
+	      sblock.fs_avgfpdir);
 	warnx("minimum percentage of free space: (-m)             %d%%",
 	      sblock.fs_minfree);
 	warnx("optimization preference: (-o)                      %s",
Index: sys/ufs/ffs/ffs_alloc.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.64.2.1
diff -u -r1.64.2.1 ffs_alloc.c
--- sys/ufs/ffs/ffs_alloc.c	2000/03/16 08:15:53	1.64.2.1
+++ sys/ufs/ffs/ffs_alloc.c	2001/09/19 00:33:51
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)ffs_alloc.c	8.18 (Berkeley) 5/26/95
- * $FreeBSD: src/sys/ufs/ffs/ffs_alloc.c,v 1.64.2.1 2000/03/16 08:15:53 ps Exp $
+ * $FreeBSD: src/sys/ufs/ffs/ffs_alloc.c,v 1.75 2001/04/10 08:38:59 mckusick Exp $
  */
 
 #include "opt_quota.h"
@@ -68,7 +68,7 @@
 				     int));
 static ufs_daddr_t ffs_clusteralloc __P((struct inode *, int, ufs_daddr_t,
 	    int));
-static ino_t	ffs_dirpref __P((struct fs *));
+static ino_t	ffs_dirpref __P((struct inode *));
 static ufs_daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
 static void	ffs_fserr __P((struct fs *, u_int, char *));
 static u_long	ffs_hashalloc
@@ -587,12 +587,23 @@
 		goto noinodes;
 
 	if ((mode & IFMT) == IFDIR)
-		ipref = ffs_dirpref(fs);
+		ipref = ffs_dirpref(pip);
 	else
 		ipref = pip->i_number;
 	if (ipref >= fs->fs_ncg * fs->fs_ipg)
 		ipref = 0;
 	cg = ino_to_cg(fs, ipref);
+	/*
+	 * Track number of dirs created one after another
+	 * in a same cg without intervening by files.
+	 */
+	if ((mode & IFMT) == IFDIR) {
+		if (fs->fs_contigdirs[cg] < 255)
+			fs->fs_contigdirs[cg]++;
+	} else {
+		if (fs->fs_contigdirs[cg] > 0)
+			fs->fs_contigdirs[cg]--;
+	}
 	ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode,
 					(allocfcn_t *)ffs_nodealloccg);
 	if (ino == 0)
@@ -627,28 +638,112 @@
 }
 
 /*
- * Find a cylinder to place a directory.
+ * Find a cylinder group to place a directory.
+ *
+ * The policy implemented by this algorithm is to allocate a
+ * directory inode in the same cylinder group as its parent
+ * directory, but also to reserve space for its files inodes
+ * and data. Restrict the number of directories which may be
+ * allocated one after another in the same cylinder group
+ * without intervening allocation of files.
  *
- * The policy implemented by this algorithm is to select from
- * among those cylinder groups with above the average number of
- * free inodes, the one with the smallest number of directories.
+ * If we allocate a first level directory then force allocation
+ * in another cylinder group.
  */
 static ino_t
-ffs_dirpref(fs)
-	register struct fs *fs;
+ffs_dirpref(pip)
+	struct inode *pip;
 {
-	int cg, minndir, mincg, avgifree;
+	register struct fs *fs;
+	int cg, prefcg, dirsize, cgsize;
+	int avgifree, avgbfree, avgndir, curdirsize;
+	int minifree, minbfree, maxndir;
+	int mincg, minndir;
+	int maxcontigdirs;
 
+	fs = pip->i_fs;
+
 	avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
-	minndir = fs->fs_ipg;
-	mincg = 0;
-	for (cg = 0; cg < fs->fs_ncg; cg++)
-		if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
-		    fs->fs_cs(fs, cg).cs_nifree >= avgifree) {
-			mincg = cg;
-			minndir = fs->fs_cs(fs, cg).cs_ndir;
+	avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
+	avgndir = fs->fs_cstotal.cs_ndir / fs->fs_ncg;
+
+	/*
+	 * Force allocation in another cg if creating a first level dir.
+	 */
+	if (ITOV(pip)->v_flag & VROOT) {
+		prefcg = arc4random() % fs->fs_ncg;
+		mincg = prefcg;
+		minndir = fs->fs_ipg;
+		for (cg = prefcg; cg < fs->fs_ncg; cg++)
+			if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
+			    fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
+			    fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+				mincg = cg;
+				minndir = fs->fs_cs(fs, cg).cs_ndir;
+			}
+		for (cg = 0; cg < prefcg; cg++)
+			if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
+			    fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
+			    fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+				mincg = cg;
+				minndir = fs->fs_cs(fs, cg).cs_ndir;
+			}
+		return ((ino_t)(fs->fs_ipg * mincg));
+	}
+
+	/*
+	 * Count various limits which used for
+	 * optimal allocation of a directory inode.
+	 */
+	maxndir = min(avgndir + fs->fs_ipg / 16, fs->fs_ipg);
+	minifree = avgifree - fs->fs_ipg / 4;
+	if (minifree < 0)
+		minifree = 0;
+	minbfree = avgbfree - fs->fs_fpg / fs->fs_frag / 4;
+	if (minbfree < 0)
+		minbfree = 0;
+	cgsize = fs->fs_fsize * fs->fs_fpg;
+	dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir;
+	curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0;
+	if (dirsize < curdirsize)
+		dirsize = curdirsize;
+	maxcontigdirs = min(cgsize / dirsize, 255);
+	if (fs->fs_avgfpdir > 0)
+		maxcontigdirs = min(maxcontigdirs,
+				    fs->fs_ipg / fs->fs_avgfpdir);
+	if (maxcontigdirs == 0)
+		maxcontigdirs = 1;
+
+	/*
+	 * Limit number of dirs in one cg and reserve space for 
+	 * regular files, but only if we have no deficit in
+	 * inodes or space.
+	 */
+	prefcg = ino_to_cg(fs, pip->i_number);
+	for (cg = prefcg; cg < fs->fs_ncg; cg++)
+		if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
+		    fs->fs_cs(fs, cg).cs_nifree >= minifree &&
+	    	    fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
+			if (fs->fs_contigdirs[cg] < maxcontigdirs)
+				return ((ino_t)(fs->fs_ipg * cg));
 		}
-	return ((ino_t)(fs->fs_ipg * mincg));
+	for (cg = 0; cg < prefcg; cg++)
+		if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
+		    fs->fs_cs(fs, cg).cs_nifree >= minifree &&
+	    	    fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
+			if (fs->fs_contigdirs[cg] < maxcontigdirs)
+				return ((ino_t)(fs->fs_ipg * cg));
+		}
+	/*
+	 * This is a backstop when we have deficit in space.
+	 */
+	for (cg = prefcg; cg < fs->fs_ncg; cg++)
+		if (fs->fs_cs(fs, cg).cs_nifree >= avgifree)
+			return ((ino_t)(fs->fs_ipg * cg));
+	for (cg = 0; cg < prefcg; cg++)
+		if (fs->fs_cs(fs, cg).cs_nifree >= avgifree)
+			break;
+	return ((ino_t)(fs->fs_ipg * cg));
 }
 
 /*
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.117.2.3
diff -u -r1.117.2.3 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	2001/07/26 20:37:31	1.117.2.3
+++ sys/ufs/ffs/ffs_vfsops.c	2001/09/19 00:35:03
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)ffs_vfsops.c	8.31 (Berkeley) 5/20/95
- * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.3 2001/07/26 20:37:31 iedowse Exp $
+ * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.159 2001/09/09 23:48:28 iedowse Exp $
  */
 
 #include "opt_quota.h"
@@ -470,12 +470,18 @@
 	 */
 	newfs->fs_csp = fs->fs_csp;
 	newfs->fs_maxcluster = fs->fs_maxcluster;
+	newfs->fs_contigdirs = fs->fs_contigdirs;
 	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
 	if (fs->fs_sbsize < SBSIZE)
 		bp->b_flags |= B_INVAL;
 	brelse(bp);
 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
 	ffs_oldfscompat(fs);
+	/* An old fsck may have zeroed these fields, so recheck them. */
+	if (fs->fs_avgfilesize <= 0)		/* XXX */
+		fs->fs_avgfilesize = AVFILESIZ;	/* XXX */
+	if (fs->fs_avgfpdir <= 0)		/* XXX */
+		fs->fs_avgfpdir = AFPDIR;	/* XXX */
 
 	/*
 	 * Step 3: re-read summary information from disk.
@@ -674,6 +680,7 @@
 	blks = howmany(size, fs->fs_fsize);
 	if (fs->fs_contigsumsize > 0)
 		size += fs->fs_ncg * sizeof(int32_t);
+	size += fs->fs_ncg * sizeof(u_int8_t);
 	space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
 	fs->fs_csp = space;
 	for (i = 0; i < blks; i += fs->fs_frag) {
@@ -694,7 +701,16 @@
 		fs->fs_maxcluster = lp = space;
 		for (i = 0; i < fs->fs_ncg; i++)
 			*lp++ = fs->fs_contigsumsize;
+		space = lp;
 	}
+	size = fs->fs_ncg * sizeof(u_int8_t);
+	fs->fs_contigdirs = (u_int8_t *)space;
+	bzero(fs->fs_contigdirs, size);
+	/* Compatibility for old filesystems 	   XXX */
+	if (fs->fs_avgfilesize <= 0)		/* XXX */
+		fs->fs_avgfilesize = AVFILESIZ;	/* XXX */
+	if (fs->fs_avgfpdir <= 0)		/* XXX */
+		fs->fs_avgfpdir = AFPDIR;	/* XXX */
 	mp->mnt_data = (qaddr_t)ump;
 	mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
 	mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
Index: sys/ufs/ffs/fs.h
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/fs.h,v
retrieving revision 1.14.2.2
diff -u -r1.14.2.2 fs.h
--- sys/ufs/ffs/fs.h	2001/01/22 18:10:28	1.14.2.2
+++ sys/ufs/ffs/fs.h	2001/09/19 00:32:13
@@ -108,15 +108,17 @@
 /*
  * There is a 128-byte region in the superblock reserved for in-core
  * pointers to summary information. Originally this included an array
- * of pointers to blocks of struct csum; now there are just two
+ * of pointers to blocks of struct csum; now there are just three
  * pointers and the remaining space is padded with fs_ocsp[].
  *
  * NOCSPTRS determines the size of this padding. One pointer (fs_csp)
  * is taken away to point to a contiguous array of struct csum for
  * all cylinder groups; a second (fs_maxcluster) points to an array
- * of cluster sizes that is computed as cylinder groups are inspected.
+ * of cluster sizes that is computed as cylinder groups are inspected,
+ * and the third points to an array that tracks the creation of new
+ * directories.
  */
-#define	NOCSPTRS	((128 / sizeof(void *)) - 2)
+#define	NOCSPTRS	((128 / sizeof(void *)) - 3)
 
 /*
  * A summary of contiguous blocks of various sizes is maintained
@@ -142,6 +144,31 @@
 #define DEFAULTOPT	FS_OPTTIME
 
 /*
+ * Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine
+ * tune the layout preferences for directories within a filesystem.
+ * His algorithm can be tuned by adjusting the following parameters
+ * which tell the system the average file size and the average number
+ * of files per directory. These defaults are well selected for typical
+ * filesystems, but may need to be tuned for odd cases like filesystems
+ * being used for sqiud caches or news spools.
+ */
+#define AVFILESIZ      16384   /* expected average file size */
+#define AFPDIR         64      /* expected number of files per directory */
+
+/*
+ * The maximum number of snapshot nodes that can be associated
+ * with each filesystem. This limit affects only the number of
+ * snapshot files that can be recorded within the superblock so
+ * that they can be found when the filesystem is mounted. However,
+ * maintaining too many will slow the filesystem performance, so
+ * having this limit is a good idea.
+ *
+ * VALUE NOT IMPLEMENTED IN 4.x YET, RESERVED FROM -CURRENT SO SUPERBLOCKS
+ * REMAIN COMPATIBLE.
+ */
+#define FSMAXSNAP 20
+
+/*
  * Per cylinder group information; summarized in blocks allocated
  * from first cylinder group data blocks.  These blocks have to be
  * read in from fs_csaddr (size fs_cssize) in addition to the
@@ -227,11 +254,17 @@
 /* these fields retain the current block allocation info */
 	int32_t	 fs_cgrotor;		/* last cg searched */
 	void 	*fs_ocsp[NOCSPTRS];	/* padding; was list of fs_cs buffers */
+	u_int8_t *fs_contigdirs;	/* # of contiguously allocated dirs */
 	struct csum *fs_csp;		/* cg summary info buffer for fs_cs */
 	int32_t	*fs_maxcluster;		/* max cluster in each cyl group */
 	int32_t	 fs_cpc;		/* cyl per cycle in postbl */
 	int16_t	 fs_opostbl[16][8];	/* old rotation block list head */
-	int32_t	 fs_sparecon[50];	/* reserved for future constants */
+	int32_t  fs_snapinum[FSMAXSNAP];/* RESERVED FROM 5.x */
+	int32_t	 fs_avgfilesize;	/* expected average file size */
+	int32_t  fs_avgfpdir;		/* expected # of files per directory */
+	int32_t	 fs_sparecon[26];	/* reserved for future constants */
+	int32_t  fs_pendingblocks;      /* RESERVED FROM 5.x */
+	int32_t  fs_pendinginodes;      /* RESERVED FROM 5.x */
 	int32_t	 fs_contigsumsize;	/* size of cluster summary array */ 
 	int32_t	 fs_maxsymlinklen;	/* max length of an internal symlink */
 	int32_t	 fs_inodefmt;		/* format of on-disk inodes */

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200109190106.f8J16jv50999>