Bug 1456888, Use Linux filesystem type to decide about NSS SQL DB caching and speed measuring, r=rrelyea
authorKai Engert <kaie@kuix.de>
Wed, 02 May 2018 15:44:22 +0200
changeset 14343 5a210945d2486d6443556ec578b22c05949e1049
parent 14342 4189fcdd9b7580e206f04d0f775006524d02b0d1
child 14344 2f1ee2b8f7a65ecae1a84c02dcf0167ce3b57ab4
push id3076
push userkaie@kuix.de
push dateWed, 02 May 2018 13:43:10 +0000
reviewersrrelyea
bugs1456888
Bug 1456888, Use Linux filesystem type to decide about NSS SQL DB caching and speed measuring, r=rrelyea
lib/softoken/sdb.c
--- a/lib/softoken/sdb.c
+++ b/lib/softoken/sdb.c
@@ -32,16 +32,20 @@
 #include "prsystem.h" /* for PR_GetDirectorySeparator() */
 #include <sys/stat.h>
 #if defined(_WIN32)
 #include <io.h>
 #include <windows.h>
 #elif defined(XP_UNIX)
 #include <unistd.h>
 #endif
+#if defined(LINUX) && !defined(ANDROID)
+#include <linux/magic.h>
+#include <sys/vfs.h>
+#endif
 #include "utilpars.h"
 
 #ifdef SQLITE_UNSAFE_THREADS
 #include "prlock.h"
 /*
  * SQLite can be compiled to be thread safe or not.
  * turn on SQLITE_UNSAFE_THREADS if the OS does not support
  * a thread safe version of sqlite.
@@ -1758,16 +1762,18 @@ sdb_init(char *dbname, char *table, sdbD
     SDBPrivate *sdb_p = NULL;
     sqlite3 *sqlDB = NULL;
     int sqlerr = SQLITE_OK;
     CK_RV error = CKR_OK;
     char *cacheTable = NULL;
     PRIntervalTime now = 0;
     char *env;
     PRBool enableCache = PR_FALSE;
+    PRBool checkFSType = PR_FALSE;
+    PRBool measureSpeed = PR_FALSE;
     PRBool create;
     int flags = inFlags & 0x7;
 
     *pSdb = NULL;
     *inUpdate = 0;
 
     /* sqlite3 doesn't have a flag to specify that we want to
      * open the database read only. If the db doesn't exist,
@@ -1918,21 +1924,58 @@ sdb_init(char *dbname, char *table, sdbD
      *   always be used.
      *
      * It is expected that most applications will not need this feature, and
      * thus it is disabled by default.
      */
 
     env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
 
-    if (!env || PORT_Strcasecmp(env, "no") == 0) {
-        enableCache = PR_FALSE;
+    /* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default,
+     * which is the expected behavior for NSS_SDB_USE_CACHE="no".
+     * We don't need to check for "no" here. */
+    if (!env) {
+        /* By default, with no variable set, we avoid expensive measuring for
+         * most FS types. We start with inexpensive FS type checking, and
+         * might perform measuring for some types. */
+        checkFSType = PR_TRUE;
     } else if (PORT_Strcasecmp(env, "yes") == 0) {
         enableCache = PR_TRUE;
-    } else {
+    } else if (PORT_Strcasecmp(env, "no") != 0) { /* not "no" => "auto" */
+        measureSpeed = PR_TRUE;
+    }
+
+    if (checkFSType) {
+#if defined(LINUX) && !defined(ANDROID)
+        struct statfs statfs_s;
+        if (statfs(dbname, &statfs_s) == 0) {
+            switch (statfs_s.f_type) {
+                case SMB_SUPER_MAGIC:
+                case 0xff534d42: /* CIFS_MAGIC_NUMBER */
+                case NFS_SUPER_MAGIC:
+                    /* We assume these are slow. */
+                    enableCache = PR_TRUE;
+                    break;
+                case CODA_SUPER_MAGIC:
+                case 0x65735546: /* FUSE_SUPER_MAGIC */
+                case NCP_SUPER_MAGIC:
+                    /* It's uncertain if this FS is fast or slow.
+                     * It seems reasonable to perform slow measuring for users
+                     * with questionable FS speed. */
+                    measureSpeed = PR_TRUE;
+                    break;
+                case AFS_SUPER_MAGIC: /* Already implements caching. */
+                default:
+                    break;
+            }
+        }
+#endif
+    }
+
+    if (measureSpeed) {
         char *tempDir = NULL;
         PRUint32 tempOps = 0;
         /*
          *  Use PR_Access to determine how expensive it
          * is to check for the existance of a local file compared to the same
          * check in the temp directory. If the temp directory is faster, cache
          * the database there. */
         tempDir = sdb_getTempDir(sqlDB);