summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Relyea <rrelyea@redhat.com>2020-04-18 17:11:20 -0700
committerRobert Relyea <rrelyea@redhat.com>2020-04-18 17:11:20 -0700
commit1341c7c22ce500a11d92350131baa5f28dc1390d (patch)
tree124265908646edde56da5f6bc37bd1646c96ebe3
parent4d1581bb5839991012507f409e02d72857591bc7 (diff)
downloadnss-hg-1341c7c22ce500a11d92350131baa5f28dc1390d.tar.gz
Bug 1603801 [patch] Avoid dcache pollution from sdb_measureAccess() r=mt
As implemented, when sdb_measureAccess() runs it creates up to 10,000 negative dcache entries (cached nonexistent filenames). There is no advantage to leaving these particular filenames in the cache; they will never be searched again. Subsequent runs will run a new test with an intentionally different set of filenames. This can have detrimental effects on some systems; a massive negative dcache can lead to memory or performance problems. Since not all platforms have a problem with negative dcache entries, this patch is limitted to those platforms that request it at compilie time (Linux is current the only patch that does.) Differential Revision: https://phabricator.services.mozilla.com/D59652
-rw-r--r--coreconf/Linux.mk2
-rw-r--r--coreconf/config.gypi1
-rw-r--r--lib/softoken/sdb.c51
3 files changed, 44 insertions, 10 deletions
diff --git a/coreconf/Linux.mk b/coreconf/Linux.mk
index 854d3ca96..956f0e4a9 100644
--- a/coreconf/Linux.mk
+++ b/coreconf/Linux.mk
@@ -21,7 +21,7 @@ ifeq ($(USE_PTHREADS),1)
endif
DEFAULT_COMPILER = gcc
-DEFINES += -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_SOURCE
+DEFINES += -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_SOURCE -DSQL_MEASURE_USE_TEMP_DIR
ifeq ($(OS_TARGET),Android)
ifndef ANDROID_NDK
diff --git a/coreconf/config.gypi b/coreconf/config.gypi
index 6459bccc9..d18875965 100644
--- a/coreconf/config.gypi
+++ b/coreconf/config.gypi
@@ -362,6 +362,7 @@
'_DEFAULT_SOURCE', # for <endian.h> functions, strdup, realpath, and getentropy
'_BSD_SOURCE', # for the above in glibc <= 2.19
'_POSIX_SOURCE', # for <signal.h>
+ 'SQL_MEASURE_USE_TEMP_DIR', # use tmpdir for the access calls
],
}],
[ 'OS=="dragonfly" or OS=="freebsd"', {
diff --git a/lib/softoken/sdb.c b/lib/softoken/sdb.c
index ac36e348c..a908d1a58 100644
--- a/lib/softoken/sdb.c
+++ b/lib/softoken/sdb.c
@@ -400,8 +400,20 @@ sdb_measureAccess(const char *directory)
PRIntervalTime duration = PR_MillisecondsToInterval(33);
const char *doesntExistName = "_dOeSnotExist_.db";
char *temp, *tempStartOfFilename;
- size_t maxTempLen, maxFileNameLen, directoryLength;
-
+ size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /*
+ * on some OS's and Filesystems, creating a bunch of files and deleting
+ * them messes up the systems's caching, but if we create the files in
+ * a temp directory which we later delete, then the cache gets cleared
+ * up. This code uses several OS dependent calls, and it's not clear
+ * that temp directory use won't mess up other filesystems and OS caching,
+ * so if you need this for your OS, you can turn on the
+ * 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf
+ */
+ const char template[] = "dbTemp.XXXXXX";
+ tmpdirLength = sizeof(template);
+#endif
/* no directory, just return one */
if (directory == NULL) {
return 1;
@@ -412,24 +424,39 @@ sdb_measureAccess(const char *directory)
directoryLength = strlen(directory);
- maxTempLen = directoryLength + strlen(doesntExistName) + 1 /* potential additional separator char */
- + 11 /* max chars for 32 bit int plus potential sign */
- + 1; /* zero terminator */
+ maxTempLen = directoryLength + 1 /* dirname + / */
+ + tmpdirLength /* tmpdirname includes / */
+ + strlen(doesntExistName) /* filename base */
+ + 11 /* max chars for 32 bit int plus potential sign */
+ + 1; /* zero terminator */
- temp = PORT_Alloc(maxTempLen);
+ temp = PORT_ZAlloc(maxTempLen);
if (!temp) {
return 1;
}
/* We'll copy directory into temp just once, then ensure it ends
- * with the directory separator, then remember the position after
- * the separator, and calculate the number of remaining bytes. */
+ * with the directory separator. */
strcpy(temp, directory);
if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
temp[directoryLength++] = PR_GetDirectorySeparator();
}
- tempStartOfFilename = temp + directoryLength;
+
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /* add the template for a temporary subdir, and create it */
+ strcat(temp, template);
+ if (!mkdtemp(temp)) {
+ PORT_Free(temp);
+ return 1;
+ }
+ /* and terminate that tmp subdir with a / */
+ strcat(temp, "/");
+#endif
+
+ /* Remember the position after the last separator, and calculate the
+ * number of remaining bytes. */
+ tempStartOfFilename = temp + directoryLength + tmpdirLength;
maxFileNameLen = maxTempLen - directoryLength;
/* measure number of Access operations that can be done in 33 milliseconds
@@ -453,6 +480,12 @@ sdb_measureAccess(const char *directory)
break;
}
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /* turn temp back into our tmpdir path by removing doesntExistName, and
+ * remove the tmp dir */
+ *tempStartOfFilename = '\0';
+ (void)rmdir(temp);
+#endif
PORT_Free(temp);
/* always return 1 or greater */