Blame SOURCES/autofs-5.1.6-add-hashtable-implementation.patch

9a499a
autofs-5.1.6 - add hashtable implementation
9a499a
9a499a
From: Ian Kent <raven@themaw.net>
9a499a
9a499a
Include the (slightly modified) Linux kernel hashtable implementation.
9a499a
9a499a
Signed-off-by: Ian Kent <raven@themaw.net>
9a499a
---
9a499a
 CHANGELOG           |    1 
9a499a
 include/automount.h |   19 -----
9a499a
 include/hash.h      |  101 +++++++++++++++++++++++++++++++
9a499a
 include/hashtable.h |  166 ++++++++++++++++++++++++++++++++++++++++++++++++++++
9a499a
 4 files changed, 269 insertions(+), 18 deletions(-)
9a499a
 create mode 100644 include/hash.h
9a499a
 create mode 100644 include/hashtable.h
9a499a
9a499a
--- autofs-5.1.4.orig/CHANGELOG
9a499a
+++ autofs-5.1.4/CHANGELOG
9a499a
@@ -117,6 +117,7 @@ xx/xx/2018 autofs-5.1.5
9a499a
 - make bind mounts propagation slave by default.
9a499a
 - fix browse dir not re-created on symlink expire.
9a499a
 - update list.h.
9a499a
+- add hashtable implementation.
9a499a
 
9a499a
 19/12/2017 autofs-5.1.4
9a499a
 - fix spec file url.
9a499a
--- autofs-5.1.4.orig/include/automount.h
9a499a
+++ autofs-5.1.4/include/automount.h
9a499a
@@ -22,6 +22,7 @@
9a499a
 #include <mntent.h>
9a499a
 #include "config.h"
9a499a
 #include "list.h"
9a499a
+#include "hash.h"
9a499a
 
9a499a
 #include <linux/auto_fs4.h>
9a499a
 
9a499a
@@ -143,24 +144,6 @@ struct autofs_point;
9a499a
 #define UMOUNT_RETRIES		8
9a499a
 #define EXPIRE_RETRIES		3
9a499a
 
9a499a
-static u_int32_t inline hash(const char *key, unsigned int size)
9a499a
-{
9a499a
-	u_int32_t hashval;
9a499a
-	char *s = (char *) key;
9a499a
-
9a499a
-	for (hashval = 0; *s != '\0';) {
9a499a
-		hashval += (unsigned char) *s++;
9a499a
-		hashval += (hashval << 10);
9a499a
-		hashval ^= (hashval >> 6);
9a499a
-	}
9a499a
-
9a499a
-	hashval += (hashval << 3);
9a499a
-	hashval ^= (hashval >> 11);
9a499a
-	hashval += (hashval << 15);
9a499a
-
9a499a
-	return hashval % size;
9a499a
-}
9a499a
-
9a499a
 struct mapent_cache {
9a499a
 	pthread_rwlock_t rwlock;
9a499a
 	unsigned int size;
9a499a
--- /dev/null
9a499a
+++ autofs-5.1.4/include/hash.h
9a499a
@@ -0,0 +1,101 @@
9a499a
+#ifndef _LINUX_HASH_H
9a499a
+#define _LINUX_HASH_H
9a499a
+/* Fast hashing routine for ints,  longs and pointers.
9a499a
+   (C) 2002 Nadia Yvette Chambers, IBM */
9a499a
+
9a499a
+#include <sys/types.h>
9a499a
+#include <stdint.h>
9a499a
+
9a499a
+/*
9a499a
+ * The "GOLDEN_RATIO_PRIME" is used in ifs/btrfs/brtfs_inode.h and
9a499a
+ * fs/inode.c.  It's not actually prime any more (the previous primes
9a499a
+ * were actively bad for hashing), but the name remains.
9a499a
+ */
9a499a
+#if __WORDSIZE == 32
9a499a
+#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
9a499a
+#define hash_long(val, bits) hash_32(val, bits)
9a499a
+#elif __WORDSIZE == 64
9a499a
+#define hash_long(val, bits) hash_64(val, bits)
9a499a
+#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
9a499a
+#else
9a499a
+#error Wordsize not 32 or 64
9a499a
+#endif
9a499a
+
9a499a
+/* String based hash function */
9a499a
+static uint32_t inline hash(const char *key, unsigned int size)
9a499a
+{
9a499a
+	u_int32_t hashval;
9a499a
+	char *s = (char *) key;
9a499a
+
9a499a
+	for (hashval = 0; *s != '\0';) {
9a499a
+		hashval += (unsigned char) *s++;
9a499a
+		hashval += (hashval << 10);
9a499a
+		hashval ^= (hashval >> 6);
9a499a
+	}
9a499a
+
9a499a
+	hashval += (hashval << 3);
9a499a
+	hashval ^= (hashval >> 11);
9a499a
+	hashval += (hashval << 15);
9a499a
+
9a499a
+	return hashval % size;
9a499a
+}
9a499a
+
9a499a
+/*
9a499a
+ * This hash multiplies the input by a large odd number and takes the
9a499a
+ * high bits.  Since multiplication propagates changes to the most
9a499a
+ * significant end only, it is essential that the high bits of the
9a499a
+ * product be used for the hash value.
9a499a
+ *
9a499a
+ * Chuck Lever verified the effectiveness of this technique:
9a499a
+ * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
9a499a
+ *
9a499a
+ * Although a random odd number will do, it turns out that the golden
9a499a
+ * ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
9a499a
+ * properties.  (See Knuth vol 3, section 6.4, exercise 9.)
9a499a
+ *
9a499a
+ * These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
9a499a
+ * which is very slightly easier to multiply by and makes no
9a499a
+ * difference to the hash distribution.
9a499a
+ */
9a499a
+#define GOLDEN_RATIO_32 0x61C88647
9a499a
+#define GOLDEN_RATIO_64 0x61C8864680B583EBull
9a499a
+
9a499a
+static inline uint32_t __hash_32(uint32_t val)
9a499a
+{
9a499a
+	return val * GOLDEN_RATIO_32;
9a499a
+}
9a499a
+
9a499a
+static inline uint32_t hash_32(uint32_t val, unsigned int bits)
9a499a
+{
9a499a
+	/* High bits are more random, so use them. */
9a499a
+	return __hash_32(val) >> (32 - bits);
9a499a
+}
9a499a
+
9a499a
+static __always_inline uint32_t hash_64(uint64_t val, unsigned int bits)
9a499a
+{
9a499a
+#if __WORDSIZE == 64
9a499a
+	/* 64x64-bit multiply is efficient on all 64-bit processors */
9a499a
+	return val * GOLDEN_RATIO_64 >> (64 - bits);
9a499a
+#else
9a499a
+	/* Hash 64 bits using only 32x32-bit multiply. */
9a499a
+	return hash_32((uint32_t) val ^ __hash_32(val >> 32), bits);
9a499a
+#endif
9a499a
+}
9a499a
+
9a499a
+static inline uint32_t hash_ptr(const void *ptr, unsigned int bits)
9a499a
+{
9a499a
+	return hash_long((unsigned long) ptr, bits);
9a499a
+}
9a499a
+
9a499a
+/* This really should be called fold32_ptr; it does no hashing to speak of. */
9a499a
+static inline uint32_t hash32_ptr(const void *ptr)
9a499a
+{
9a499a
+	unsigned long val = (unsigned long) ptr;
9a499a
+
9a499a
+#if __WORDSIZE == 64
9a499a
+	val ^= (val >> 32);
9a499a
+#endif
9a499a
+	return (uint32_t) val;
9a499a
+}
9a499a
+
9a499a
+#endif /* _LINUX_HASH_H */
9a499a
--- /dev/null
9a499a
+++ autofs-5.1.4/include/hashtable.h
9a499a
@@ -0,0 +1,166 @@
9a499a
+/*
9a499a
+ * Statically sized hash table implementation
9a499a
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
9a499a
+ */
9a499a
+
9a499a
+#ifndef _LINUX_HASHTABLE_H
9a499a
+#define _LINUX_HASHTABLE_H
9a499a
+
9a499a
+#include "list.h"
9a499a
+#include "hash.h"
9a499a
+
9a499a
+#ifndef ARRAY_SIZE
9a499a
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
9a499a
+#endif
9a499a
+
9a499a
+static inline unsigned int ilog2(unsigned long val) {
9a499a
+	unsigned int ret = -1;
9a499a
+
9a499a
+	while (val != 0) {
9a499a
+		val >>= 1;
9a499a
+		ret++;
9a499a
+	}
9a499a
+	return ret;
9a499a
+}
9a499a
+
9a499a
+#define DEFINE_HASHTABLE(name, bits)						\
9a499a
+	struct hlist_head name[1 << (bits)] =					\
9a499a
+			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
9a499a
+
9a499a
+#define DECLARE_HASHTABLE(name, bits)                                   	\
9a499a
+	struct hlist_head name[1 << (bits)]
9a499a
+
9a499a
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
9a499a
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
9a499a
+
9a499a
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
9a499a
+#define hash_min(val, bits)							\
9a499a
+	(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
9a499a
+
9a499a
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
9a499a
+{
9a499a
+	unsigned int i;
9a499a
+
9a499a
+	for (i = 0; i < sz; i++)
9a499a
+		INIT_HLIST_HEAD(&ht[i]);
9a499a
+}
9a499a
+
9a499a
+/**
9a499a
+ * hash_init - initialize a hash table
9a499a
+ * @hashtable: hashtable to be initialized
9a499a
+ *
9a499a
+ * Calculates the size of the hashtable from the given parameter, otherwise
9a499a
+ * same as hash_init_size.
9a499a
+ *
9a499a
+ * This has to be a macro since HASH_BITS() will not work on pointers since
9a499a
+ * it calculates the size during preprocessing.
9a499a
+ */
9a499a
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
9a499a
+
9a499a
+/**
9a499a
+ * hash_add - add an object to a hashtable
9a499a
+ * @hashtable: hashtable to add to
9a499a
+ * @node: the &struct hlist_node of the object to be added
9a499a
+ * @key: the key of the object to be added
9a499a
+ */
9a499a
+#define hash_add(hashtable, node, key)						\
9a499a
+	hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
9a499a
+
9a499a
+/**
9a499a
+ * hash_add_str - add a string object to a hashtable
9a499a
+ * @hashtable: hashtable to add to
9a499a
+ * @node: the &struct hlist_node of the object to be added
9a499a
+ * @key: the string key of the object to be added
9a499a
+ */
9a499a
+#define hash_add_str(hashtable, node, key)						\
9a499a
+	hlist_add_head(node, &hashtable[hash(key, HASH_SIZE(hashtable))])
9a499a
+
9a499a
+/**
9a499a
+ * hash_hashed - check whether an object is in any hashtable
9a499a
+ * @node: the &struct hlist_node of the object to be checked
9a499a
+ */
9a499a
+static inline int hash_hashed(struct hlist_node *node)
9a499a
+{
9a499a
+	return !hlist_unhashed(node);
9a499a
+}
9a499a
+
9a499a
+static inline int __hash_empty(struct hlist_head *ht, unsigned int sz)
9a499a
+{
9a499a
+	unsigned int i;
9a499a
+
9a499a
+	for (i = 0; i < sz; i++)
9a499a
+		if (!hlist_empty(&ht[i]))
9a499a
+			return 0;
9a499a
+
9a499a
+	return 1;
9a499a
+}
9a499a
+
9a499a
+/**
9a499a
+ * hash_empty - check whether a hashtable is empty
9a499a
+ * @hashtable: hashtable to check
9a499a
+ *
9a499a
+ * This has to be a macro since HASH_BITS() will not work on pointers since
9a499a
+ * it calculates the size during preprocessing.
9a499a
+ */
9a499a
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
9a499a
+
9a499a
+/**
9a499a
+ * hash_del - remove an object from a hashtable
9a499a
+ * @node: &struct hlist_node of the object to remove
9a499a
+ */
9a499a
+static inline void hash_del(struct hlist_node *node)
9a499a
+{
9a499a
+	hlist_del_init(node);
9a499a
+}
9a499a
+
9a499a
+/**
9a499a
+ * hash_for_each - iterate over a hashtable
9a499a
+ * @name: hashtable to iterate
9a499a
+ * @bkt: integer to use as bucket loop cursor
9a499a
+ * @obj: the type * to use as a loop cursor for each entry
9a499a
+ * @member: the name of the hlist_node within the struct
9a499a
+ */
9a499a
+#define hash_for_each(name, bkt, obj, member)				\
9a499a
+	for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
9a499a
+			(bkt)++)\
9a499a
+		hlist_for_each_entry(obj, &name[bkt], member)
9a499a
+
9a499a
+/**
9a499a
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
9a499a
+ * hash entry
9a499a
+ * @name: hashtable to iterate
9a499a
+ * @bkt: integer to use as bucket loop cursor
9a499a
+ * @tmp: a &struct used for temporary storage
9a499a
+ * @obj: the type * to use as a loop cursor for each entry
9a499a
+ * @member: the name of the hlist_node within the struct
9a499a
+ */
9a499a
+#define hash_for_each_safe(name, bkt, tmp, obj, member)			\
9a499a
+	for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
9a499a
+			(bkt)++)\
9a499a
+		hlist_for_each_entry_safe(obj, tmp, &name[bkt], member)
9a499a
+
9a499a
+/**
9a499a
+ * hash_for_each_possible - iterate over all possible objects hashing to the
9a499a
+ * same bucket
9a499a
+ * @name: hashtable to iterate
9a499a
+ * @obj: the type * to use as a loop cursor for each entry
9a499a
+ * @member: the name of the hlist_node within the struct
9a499a
+ * @key: the key of the objects to iterate over
9a499a
+ */
9a499a
+#define hash_for_each_possible(name, obj, member, key)			\
9a499a
+	hlist_for_each_entry(obj, &name[hash_min(key, HASH_BITS(name))], member)
9a499a
+
9a499a
+/**
9a499a
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
9a499a
+ * same bucket safe against removals
9a499a
+ * @name: hashtable to iterate
9a499a
+ * @obj: the type * to use as a loop cursor for each entry
9a499a
+ * @tmp: a &struct used for temporary storage
9a499a
+ * @member: the name of the hlist_node within the struct
9a499a
+ * @key: the key of the objects to iterate over
9a499a
+ */
9a499a
+#define hash_for_each_possible_safe(name, obj, tmp, member, key)	\
9a499a
+	hlist_for_each_entry_safe(obj, tmp,\
9a499a
+		&name[hash_min(key, HASH_BITS(name))], member)
9a499a
+
9a499a
+#endif