Whamcloud - gitweb
LU-8130 libcfs: prepare rhashtable support 02/32102/27
authorJames Simmons <uja.ornl@yahoo.com>
Sun, 19 Aug 2018 13:25:52 +0000 (09:25 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 4 Sep 2018 03:49:00 +0000 (03:49 +0000)
Linux has a resizeable hashtable implementation in lib,
so we should use that instead of having one in libcfs.
In the process we gain lockless lookup which should be
a performance boost. All modern distributions Lustre
support has rhashtable support but a few pieces are
missing for systems running a 4.4 kernel. The other
target platforms have the full implementation we need.

Test-Parameters: trivial

Change-Id: I63d5b7dae9d52eed12dbefed8ca6062af33efd30
Signed-off-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-on: https://review.whamcloud.com/32102
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
libcfs/autoconf/lustre-libcfs.m4
libcfs/include/libcfs/linux/Makefile.am
libcfs/include/libcfs/linux/linux-hash.h [new file with mode: 0644]
libcfs/libcfs/Makefile.in
libcfs/libcfs/linux/Makefile.am
libcfs/libcfs/linux/linux-hash.c [new file with mode: 0644]

index 0803c70..d437331 100644 (file)
@@ -749,6 +749,18 @@ get_user_pages_6arg, [
 ]) # LIBCFS_GET_USER_PAGES_6ARG
 
 #
 ]) # LIBCFS_GET_USER_PAGES_6ARG
 
 #
+# LIBCFS_STRINGHASH
+#
+# 4.6 kernel created stringhash.h which moved stuff out of dcache.h
+# commit f4bcbe792b8f434e32487cff9d9e30ab45a3ce02
+#
+AC_DEFUN([LIBCFS_STRINGHASH], [
+LB_CHECK_LINUX_HEADER([linux/stringhash.h], [
+       AC_DEFINE(HAVE_STRINGHASH, 1,
+               [stringhash.h is present])])
+]) # LIBCFS_STRINGHASH
+
+#
 # LIBCFS_STACKTRACE_OPS
 #
 # Kernel version 4.8 commit c8fe4609827aedc9c4b45de80e7cdc8ccfa8541b
 # LIBCFS_STACKTRACE_OPS
 #
 # Kernel version 4.8 commit c8fe4609827aedc9c4b45de80e7cdc8ccfa8541b
@@ -814,6 +826,25 @@ LB_CHECK_LINUX_HEADER([linux/sched/signal.h], [
 ]) # LIBCFS_SCHED_HEADERS
 
 #
 ]) # LIBCFS_SCHED_HEADERS
 
 #
+# Kernel version 4.11 commit f9fe1c12d126f9887441fa5bb165046f30ddd4b5
+# introduced rhashtable_lookup_get_insert_fast
+#
+AC_DEFUN([LIBCFS_RHASHTABLE_LOOKUP_GET_INSERT_FAST], [
+LB_CHECK_COMPILE([if 'rhashtable_lookup_get_insert_fast' exist],
+rhashtable_lookup_get_insert_fast, [
+       #include <linux/rhashtable.h>
+],[
+       const struct rhashtable_params params = { 0 };
+       void *ret;
+
+       ret = rhashtable_lookup_get_insert_fast(NULL, NULL, params);
+],[
+       AC_DEFINE(HAVE_RHASHTABLE_LOOKUP_GET_INSERT_FAST, 1,
+               [rhashtable_lookup_get_insert_fast() is available])
+])
+]) # LIBCFS_RHASHTABLE_LOOKUP_GET_INSERT_FAST
+
+#
 # LIBCFS_WAIT_QUEUE_ENTRY
 #
 # Kernel version 4.13 ac6424b981bce1c4bc55675c6ce11bfe1bbfa64f
 # LIBCFS_WAIT_QUEUE_ENTRY
 #
 # Kernel version 4.13 ac6424b981bce1c4bc55675c6ce11bfe1bbfa64f
@@ -966,6 +997,7 @@ LIBCFS_EXPORT_KSET_FIND_OBJ
 # 4.6
 LIBCFS_STACKTRACE_OPS_ADDRESS_RETURN_INT
 LIBCFS_GET_USER_PAGES_6ARG
 # 4.6
 LIBCFS_STACKTRACE_OPS_ADDRESS_RETURN_INT
 LIBCFS_GET_USER_PAGES_6ARG
+LIBCFS_STRINGHASH
 # 4.8
 LIBCFS_STACKTRACE_OPS
 # 4.9
 # 4.8
 LIBCFS_STACKTRACE_OPS
 # 4.9
@@ -973,6 +1005,7 @@ LIBCFS_GET_USER_PAGES_GUP_FLAGS
 # 4.10
 LIBCFS_HOTPLUG_STATE_MACHINE
 # 4.11
 # 4.10
 LIBCFS_HOTPLUG_STATE_MACHINE
 # 4.11
+LIBCFS_RHASHTABLE_LOOKUP_GET_INSERT_FAST
 LIBCFS_SCHED_HEADERS
 # 4.13
 LIBCFS_WAIT_QUEUE_ENTRY
 LIBCFS_SCHED_HEADERS
 # 4.13
 LIBCFS_WAIT_QUEUE_ENTRY
index 97930b4..031c849 100644 (file)
@@ -1,2 +1,2 @@
 EXTRA_DIST = linux-misc.h linux-fs.h linux-mem.h linux-time.h linux-cpu.h \
 EXTRA_DIST = linux-misc.h linux-fs.h linux-mem.h linux-time.h linux-cpu.h \
-            linux-list.h linux-crypto.h
+            linux-list.h linux-hash.h linux-crypto.h
diff --git a/libcfs/include/libcfs/linux/linux-hash.h b/libcfs/include/libcfs/linux/linux-hash.h
new file mode 100644 (file)
index 0000000..1227ec8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+
+#ifndef __LIBCFS_LINUX_HASH_H__
+#define __LIBCFS_LINUX_HASH_H__
+
+#include <linux/dcache.h>
+#include <linux/rhashtable.h>
+
+u64 cfs_hashlen_string(const void *salt, const char *name);
+
+#ifndef hashlen_hash
+#define hashlen_hash(hashlen) ((u32)(hashlen))
+#endif
+
+#ifndef HAVE_STRINGHASH
+#ifndef hashlen_create
+#define hashlen_create(hash, len) ((u64)(len)<<32 | (u32)(hash))
+#endif
+#endif /* !HAVE_STRINGHASH */
+
+#ifndef HAVE_RHASHTABLE_LOOKUP_GET_INSERT_FAST
+/**
+ * rhashtable_lookup_get_insert_fast - lookup and insert object into hash table
+ * @ht:         hash table
+ * @obj:        pointer to hash head inside object
+ * @params:     hash table parameters
+ *
+ * Just like rhashtable_lookup_insert_fast(), but this function returns the
+ * object if it exists, NULL if it did not and the insertion was successful,
+ * and an ERR_PTR otherwise.
+ */
+static inline void *rhashtable_lookup_get_insert_fast(
+       struct rhashtable *ht, struct rhash_head *obj,
+       const struct rhashtable_params params)
+{
+       const char *key;
+       void *ret;
+       int rc;
+
+       rc = rhashtable_lookup_insert_fast(ht, obj, params);
+       switch (rc) {
+       case -EEXIST:
+               key = rht_obj(ht, obj);
+               ret = rhashtable_lookup_fast(ht, key, params);
+               break;
+       case 0:
+               ret = NULL;
+               break;
+       default:
+               ret = ERR_PTR(rc);
+               break;
+       }
+       return ret;
+}
+#endif /* !HAVE_RHASHTABLE_LOOKUP_GET_INSERT_FAST */
+
+#endif /* __LIBCFS_LINUX_MISC_H__ */
index 8d3a244..eaf2c5f 100644 (file)
@@ -3,6 +3,7 @@ MODULES = libcfs
 libcfs-linux-objs := linux-tracefile.o linux-debug.o
 libcfs-linux-objs += linux-prim.o
 libcfs-linux-objs += linux-curproc.o
 libcfs-linux-objs := linux-tracefile.o linux-debug.o
 libcfs-linux-objs += linux-prim.o
 libcfs-linux-objs += linux-curproc.o
+libcfs-linux-objs += linux-hash.o
 libcfs-linux-objs += linux-module.o
 libcfs-linux-objs += linux-crypto.o linux-crypto-adler.o
 @HAVE_CRC32_TRUE@libcfs-linux-objs += linux-crypto-crc32.o
 libcfs-linux-objs += linux-module.o
 libcfs-linux-objs += linux-crypto.o linux-crypto-adler.o
 @HAVE_CRC32_TRUE@libcfs-linux-objs += linux-crypto-crc32.o
index 72a242c..14d84c8 100644 (file)
@@ -1,5 +1,5 @@
 EXTRA_DIST = linux-debug.c linux-prim.c linux-tracefile.c      \
 EXTRA_DIST = linux-debug.c linux-prim.c linux-tracefile.c      \
-       linux-curproc.c linux-module.c                          \
+       linux-curproc.c linux-module.c linux-hash.c             \
        linux-crypto.c linux-crypto-crc32.c linux-crypto-adler.c\
        linux-crypto-crc32pclmul.c linux-crypto-crc32c-pclmul.c \
        crc32-pclmul_asm.S crc32c-pcl-intel-asm_64.S inst.h
        linux-crypto.c linux-crypto-crc32.c linux-crypto-adler.c\
        linux-crypto-crc32pclmul.c linux-crypto-crc32c-pclmul.c \
        crc32-pclmul_asm.S crc32c-pcl-intel-asm_64.S inst.h
diff --git a/libcfs/libcfs/linux/linux-hash.c b/libcfs/libcfs/linux/linux-hash.c
new file mode 100644 (file)
index 0000000..e4e67c2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+
+#define DEBUG_SUBSYSTEM S_LNET
+
+#include <linux/module.h>
+#ifdef HAVE_STRINGHASH
+#include <linux/stringhash.h>
+#else
+#include <linux/dcache.h>
+#endif
+#include <linux/hash.h>
+
+#include <libcfs/linux/linux-hash.h>
+
+/* Return the "hash_len" (hash and length) of a null-terminated string */
+/* The kernel equivalent is in fs/namei.c but for some strange reason
+ * RHEL7.5 stuck it in dax/super.c instead. This placement never existed
+ * upstream so to make life easier we just have the equavilent
+ */
+u64 cfs_hashlen_string(const void *salt, const char *name)
+{
+#ifdef HAVE_FULL_NAME_HASH_3ARGS
+       unsigned long hash = init_name_hash(salt);
+#else
+       unsigned long hash = init_name_hash();
+#endif
+       unsigned long len = 0, c;
+
+       c = (unsigned char)*name;
+       while (c) {
+               len++;
+               hash = partial_name_hash(c, hash);
+               c = (unsigned char)name[len];
+       }
+       return hashlen_create(end_name_hash(hash), len);
+}
+EXPORT_SYMBOL(cfs_hashlen_string);