Module Name:    src
Committed By:   simonb
Date:           Sun Aug  7 02:33:47 UTC 2022

Modified Files:
        src/sys/ufs/lfs: ulfs_dirhash.c
        src/sys/ufs/ufs: ufs_dirhash.c

Log Message:
If UFS or LFS dirhash is enabled in the kernel, set the dirhash cache
size dependant on memory size.  If less than 128MB of memory, default
to no cache.  With 128MB of memory or more, use a maximum cache size of
1/64th of memory; cap maximum default cache size to 32MB (for systems
with 2GB of memory or more).

The dirhash cache sizes are still explicityly setable by sysctl(8) or
by adding relevant entry(s) to sysctl.conf(5).


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/ufs/lfs/ulfs_dirhash.c
cvs rdiff -u -r1.40 -r1.41 src/sys/ufs/ufs/ufs_dirhash.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/lfs/ulfs_dirhash.c
diff -u src/sys/ufs/lfs/ulfs_dirhash.c:1.18 src/sys/ufs/lfs/ulfs_dirhash.c:1.19
--- src/sys/ufs/lfs/ulfs_dirhash.c:1.18	Sat Mar 14 18:08:40 2020
+++ src/sys/ufs/lfs/ulfs_dirhash.c	Sun Aug  7 02:33:47 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ulfs_dirhash.c,v 1.18 2020/03/14 18:08:40 ad Exp $	*/
+/*	$NetBSD: ulfs_dirhash.c,v 1.19 2022/08/07 02:33:47 simonb Exp $	*/
 /*  from NetBSD: ufs_dirhash.c,v 1.37 2014/12/20 00:28:05 christos Exp  */
 
 /*
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash.c,v 1.18 2020/03/14 18:08:40 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash.c,v 1.19 2022/08/07 02:33:47 simonb Exp $");
 
 /*
  * This implements a hash-based lookup scheme for ULFS directories.
@@ -57,13 +57,25 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash
 #include <ufs/lfs/ulfs_bswap.h>
 #include <ufs/lfs/ulfs_extern.h>
 
+/*
+ * Defaults for dirhash cache sizes:
+ *  - use up to 1/64th of system memory.
+ *  - disable dirhash (set the cache size to 0 bytes) if the
+ *    calculated value of hash is less than 2MB.
+ *  - cap maximum size of the dirhash cache at 32MB.
+ */
+#define	DIRHASH_DEFAULT_DIVIDER	64
+#define	MIN_DEFAULT_DIRHASH_MEM	(2 * 1024 * 1024)
+#define	MAX_DEFAULT_DIRHASH_MEM	(32 * 1024 * 1024)
+
+
 #define WRAPINCR(val, limit)	(((val) + 1 == (limit)) ? 0 : ((val) + 1))
 #define WRAPDECR(val, limit)	(((val) == 0) ? ((limit) - 1) : ((val) - 1))
 #define OFSFMT(ip)		((ip)->i_lfs->um_maxsymlinklen <= 0)
 #define BLKFREE2IDX(n)		((n) > DH_NFSTATS ? DH_NFSTATS : (n))
 
 static u_int ulfs_dirhashminblks = 5;
-static u_int ulfs_dirhashmaxmem = 2 * 1024 * 1024;
+static u_int ulfs_dirhashmaxmem = 0;
 static u_int ulfs_dirhashmem;
 static u_int ulfs_dirhashcheck = 0;
 
@@ -125,7 +137,9 @@ ulfsdirhash_build(struct inode *ip)
 
 	/* Check if we can/should use dirhash. */
 	if (ip->i_dirhash == NULL) {
-		if (ip->i_size < (ulfs_dirhashminblks * dirblksiz) || OFSFMT(ip))
+		if (ulfs_dirhashmaxmem == 0 ||
+		    ip->i_size < (ulfs_dirhashminblks * dirblksiz) ||
+		    OFSFMT(ip))
 			return (-1);
 	} else {
 		/* Hash exists, but sysctls could have changed. */
@@ -1155,6 +1169,26 @@ void
 ulfsdirhash_init(void)
 {
 
+	/*
+	 * Only initialise defaults for the dirhash size if it hasn't
+	 * hasn't been set.
+	 */
+	if (ulfs_dirhashmaxmem == 0) {
+		/* Use 64-bit math to avoid overflows. */
+		uint64_t physmem_bytes, hash_bytes;
+
+		physmem_bytes = ctob((uint64_t)physmem);
+		hash_bytes = physmem_bytes / DIRHASH_DEFAULT_DIVIDER;
+
+		if (hash_bytes < MIN_DEFAULT_DIRHASH_MEM)
+			hash_bytes = 0;
+
+		if (hash_bytes > MAX_DEFAULT_DIRHASH_MEM)
+			hash_bytes = MAX_DEFAULT_DIRHASH_MEM;
+
+		ulfs_dirhashmaxmem = (u_int)hash_bytes;
+	}
+
 	mutex_init(&ulfsdirhash_lock, MUTEX_DEFAULT, IPL_NONE);
 	ulfsdirhashblk_cache = pool_cache_init(DH_NBLKOFF * sizeof(daddr_t), 0,
 	    0, 0, "dirhashblk", NULL, IPL_NONE, NULL, NULL, NULL);

Index: src/sys/ufs/ufs/ufs_dirhash.c
diff -u src/sys/ufs/ufs/ufs_dirhash.c:1.40 src/sys/ufs/ufs/ufs_dirhash.c:1.41
--- src/sys/ufs/ufs/ufs_dirhash.c:1.40	Mon Mar 16 21:20:13 2020
+++ src/sys/ufs/ufs/ufs_dirhash.c	Sun Aug  7 02:33:47 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_dirhash.c,v 1.40 2020/03/16 21:20:13 pgoyette Exp $	*/
+/*	$NetBSD: ufs_dirhash.c,v 1.41 2022/08/07 02:33:47 simonb Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002 Ian Dowse.  All rights reserved.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_dirhash.c,v 1.40 2020/03/16 21:20:13 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_dirhash.c,v 1.41 2022/08/07 02:33:47 simonb Exp $");
 
 /*
  * This implements a hash-based lookup scheme for UFS directories.
@@ -55,13 +55,26 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_dirhash.
 #include <ufs/ufs/ufs_bswap.h>
 #include <ufs/ufs/ufs_extern.h>
 
+
+/*
+ * Defaults for dirhash cache sizes:
+ *  - use up to 1/64th of system memory.
+ *  - disable dirhash (set the cache size to 0 bytes) if the
+ *    calculated value of hash is less than 2MB.
+ *  - cap maximum size of the dirhash cache at 32MB.
+ */
+#define	DIRHASH_DEFAULT_DIVIDER	64
+#define	MIN_DEFAULT_DIRHASH_MEM	(2 * 1024 * 1024)
+#define	MAX_DEFAULT_DIRHASH_MEM	(32 * 1024 * 1024)
+
+
 #define WRAPINCR(val, limit)	(((val) + 1 == (limit)) ? 0 : ((val) + 1))
 #define WRAPDECR(val, limit)	(((val) == 0) ? ((limit) - 1) : ((val) - 1))
 #define OFSFMT(ip)		((ip)->i_ump->um_maxsymlinklen <= 0)
 #define BLKFREE2IDX(n)		((n) > DH_NFSTATS ? DH_NFSTATS : (n))
 
 static u_int ufs_dirhashminblks = 5;
-static u_int ufs_dirhashmaxmem = 2 * 1024 * 1024;
+static u_int ufs_dirhashmaxmem = 0;
 static u_int ufs_dirhashmem;
 static u_int ufs_dirhashcheck = 0;
 
@@ -121,7 +134,9 @@ ufsdirhash_build(struct inode *ip)
 
 	/* Check if we can/should use dirhash. */
 	if (ip->i_dirhash == NULL) {
-		if (ip->i_size < (ufs_dirhashminblks * dirblksiz) || OFSFMT(ip))
+		if (ufs_dirhashmaxmem == 0 ||
+		    ip->i_size < (ufs_dirhashminblks * dirblksiz) ||
+		    OFSFMT(ip))
 			return (-1);
 	} else {
 		/* Hash exists, but sysctls could have changed. */
@@ -1138,6 +1153,26 @@ void
 ufsdirhash_init(void)
 {
 
+	/*
+	 * Only initialise defaults for the dirhash size if it hasn't
+	 * hasn't been set.
+	 */
+	if (ufs_dirhashmaxmem == 0) {
+		/* Use 64-bit math to avoid overflows. */
+		uint64_t physmem_bytes, hash_bytes;
+
+		physmem_bytes = ctob((uint64_t)physmem);
+		hash_bytes = physmem_bytes / DIRHASH_DEFAULT_DIVIDER;
+
+		if (hash_bytes < MIN_DEFAULT_DIRHASH_MEM)
+			hash_bytes = 0;
+
+		if (hash_bytes > MAX_DEFAULT_DIRHASH_MEM)
+			hash_bytes = MAX_DEFAULT_DIRHASH_MEM;
+
+		ufs_dirhashmaxmem = (u_int)hash_bytes;
+	}
+
 	mutex_init(&ufsdirhash_lock, MUTEX_DEFAULT, IPL_NONE);
 	ufsdirhashblk_cache = pool_cache_init(DH_NBLKOFF * sizeof(daddr_t), 0,
 	    0, 0, "dirhashblk", NULL, IPL_NONE, NULL, NULL, NULL);

Reply via email to