]> git.pld-linux.org Git - packages/autofs.git/blame - autofs-5.0.4-make-hash-table-scale-to-thousands-of-entries.patch
- updated to 5.0.5, nfy.
[packages/autofs.git] / autofs-5.0.4-make-hash-table-scale-to-thousands-of-entries.patch
CommitLineData
e5fd101c
PS
1autofs-5.0.4 - make hash table scale to thousands of entries
2
3From: Valerie Aurora Henson <vaurora@redhat.com>
4
5Originally written by Paul Wankadia <junyer@google.com>.
6
7The autofs cache lookup performs poorly for large maps.
8
9The additive hashing algorithm used by autofs results in a clustering
10of hash values around the average hash chain size. It is biased toward
11a small range of hash indexes which becomes worse as the hash table size
12increases.
13
14Simple testing shows that the "One-at-a-time" hash function (implemented
15by this patch) gives a much better distribution of hash indexes as table
16size increases.
17
18The only change made to the original patch is to make the hash table size
19configurable with a default somewhat larger than it is currently.
20---
21
22 CHANGELOG | 2 ++
23 include/automount.h | 2 +-
24 include/defaults.h | 3 +++
25 lib/cache.c | 47 +++++++++++++++++++++++-----------------
26 lib/defaults.c | 16 +++++++++++++-
27 redhat/autofs.sysconfig.in | 6 +++++
28 samples/autofs.conf.default.in | 6 +++++
29 7 files changed, 60 insertions(+), 22 deletions(-)
30
31
32diff --git a/CHANGELOG b/CHANGELOG
33index 0fb7db5..912c088 100644
34--- a/CHANGELOG
35+++ b/CHANGELOG
36@@ -5,6 +5,8 @@
37 - fix negative caching for non-existent map keys.
38 - use CLOEXEC flag.
39 - fix select(2) fd limit.
40+- make hash table scale to thousands of entries (Paul Wankadia,
41+ Valerie Aurora Henson).
42
43 4/11/2008 autofs-5.0.4
44 -----------------------
45diff --git a/include/automount.h b/include/automount.h
46index a55ddbc..fa24885 100644
47--- a/include/automount.h
48+++ b/include/automount.h
49@@ -128,7 +128,7 @@ struct autofs_point;
50 #define CHE_DUPLICATE 0x0020
51 #define CHE_UNAVAIL 0x0040
52
53-#define HASHSIZE 77
54+#define NULL_MAP_HASHSIZE 64
55 #define NEGATIVE_TIMEOUT 10
56 #define UMOUNT_RETRIES 8
57 #define EXPIRE_RETRIES 3
58diff --git a/include/defaults.h b/include/defaults.h
59index 12534ec..9a2430f 100644
60--- a/include/defaults.h
61+++ b/include/defaults.h
62@@ -40,6 +40,8 @@
63 #define DEFAULT_APPEND_OPTIONS 1
64 #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf"
65
66+#define DEFAULT_MAP_HASH_TABLE_SIZE 1024
67+
68 struct ldap_schema;
69 struct ldap_searchdn;
70
71@@ -62,6 +64,7 @@ void defaults_free_searchdns(struct ldap_searchdn *);
72 unsigned int defaults_get_append_options(void);
73 unsigned int defaults_get_umount_wait(void);
74 const char *defaults_get_auth_conf_file(void);
75+unsigned int defaults_get_map_hash_table_size(void);
76
77 #endif
78
79diff --git a/lib/cache.c b/lib/cache.c
80index 4a00367..edb3192 100644
81--- a/lib/cache.c
82+++ b/lib/cache.c
83@@ -190,7 +190,7 @@ struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
84 if (!mc)
85 return NULL;
86
87- mc->size = HASHSIZE;
88+ mc->size = defaults_get_map_hash_table_size();
89
90 mc->hash = malloc(mc->size * sizeof(struct entry *));
91 if (!mc->hash) {
92@@ -241,7 +241,7 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
93 if (!mc)
94 return NULL;
95
96- mc->size = HASHSIZE;
97+ mc->size = NULL_MAP_HASHSIZE;
98
99 mc->hash = malloc(mc->size * sizeof(struct entry *));
100 if (!mc->hash) {
101@@ -279,29 +279,36 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
102 return mc;
103 }
104
105-static unsigned int hash(const char *key)
106+static u_int32_t hash(const char *key, unsigned int size)
107 {
108- unsigned long hashval;
109+ u_int32_t hashval;
110 char *s = (char *) key;
111
112- for (hashval = 0; *s != '\0';)
113- hashval += *s++;
114+ for (hashval = 0; *s != '\0';) {
115+ hashval += (unsigned char) *s++;
116+ hashval += (hashval << 10);
117+ hashval ^= (hashval >> 6);
118+ }
119+
120+ hashval += (hashval << 3);
121+ hashval ^= (hashval >> 11);
122+ hashval += (hashval << 15);
123
124- return hashval % HASHSIZE;
125+ return hashval % size;
126 }
127
128-static unsigned int ino_hash(dev_t dev, ino_t ino)
129+static u_int32_t ino_hash(dev_t dev, ino_t ino, unsigned int size)
130 {
131- unsigned long hashval;
132+ u_int32_t hashval;
133
134 hashval = dev + ino;
135
136- return hashval % HASHSIZE;
137+ return hashval % size;
138 }
139
140 int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
141 {
142- unsigned int ino_index = ino_hash(dev, ino);
143+ u_int32_t ino_index = ino_hash(dev, ino, mc->size);
144 struct mapent *me;
145
146 me = cache_lookup_distinct(mc, key);
147@@ -323,10 +330,10 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
148 {
149 struct mapent *me = NULL;
150 struct list_head *head, *p;
151- unsigned int ino_index;
152+ u_int32_t ino_index;
153
154 ino_index_lock(mc);
155- ino_index = ino_hash(dev, ino);
156+ ino_index = ino_hash(dev, ino, mc->size);
157 head = &mc->ino_index[ino_index];
158
159 list_for_each(p, head) {
160@@ -369,7 +376,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
161 struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
162 {
163 struct mapent *this;
164- unsigned long hashval;
165+ u_int32_t hashval;
166 unsigned int i;
167
168 if (!me)
169@@ -385,7 +392,7 @@ struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
170 return this;
171 }
172
173- hashval = hash(me->key) + 1;
174+ hashval = hash(me->key, mc->size) + 1;
175 if (hashval < mc->size) {
176 for (i = (unsigned int) hashval; i < mc->size; i++) {
177 this = mc->hash[i];
178@@ -433,7 +440,7 @@ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key)
179 if (!key)
180 return NULL;
181
182- for (me = mc->hash[hash(key)]; me != NULL; me = me->next) {
183+ for (me = mc->hash[hash(key, mc->size)]; me != NULL; me = me->next) {
184 if (strcmp(key, me->key) == 0)
185 goto done;
186 }
187@@ -446,7 +453,7 @@ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key)
188 goto done;
189 }
190
191- for (me = mc->hash[hash("*")]; me != NULL; me = me->next)
192+ for (me = mc->hash[hash("*", mc->size)]; me != NULL; me = me->next)
193 if (strcmp("*", me->key) == 0)
194 goto done;
195 }
196@@ -462,7 +469,7 @@ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key)
197 if (!key)
198 return NULL;
199
200- for (me = mc->hash[hash(key)]; me != NULL; me = me->next) {
201+ for (me = mc->hash[hash(key, mc->size)]; me != NULL; me = me->next) {
202 if (strcmp(key, me->key) == 0)
203 return me;
204 }
205@@ -530,7 +537,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
206 {
207 struct mapent *me, *existing = NULL;
208 char *pkey, *pent;
209- unsigned int hashval = hash(key);
210+ u_int32_t hashval = hash(key, mc->size);
211 int status;
212
213 me = (struct mapent *) malloc(sizeof(struct mapent));
214@@ -750,7 +757,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
215 int cache_delete(struct mapent_cache *mc, const char *key)
216 {
217 struct mapent *me = NULL, *pred;
218- unsigned int hashval = hash(key);
219+ u_int32_t hashval = hash(key, mc->size);
220 int status, ret = CHE_OK;
221 char *this;
222
223diff --git a/lib/defaults.c b/lib/defaults.c
224index ff653e3..0d39716 100644
225--- a/lib/defaults.c
226+++ b/lib/defaults.c
227@@ -49,6 +49,8 @@
228 #define ENV_UMOUNT_WAIT "UMOUNT_WAIT"
229 #define ENV_AUTH_CONF_FILE "AUTH_CONF_FILE"
230
231+#define ENV_MAP_HASH_TABLE_SIZE "MAP_HASH_TABLE_SIZE"
232+
233 static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME;
234 static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE;
235
236@@ -323,7 +325,8 @@ unsigned int defaults_read_config(unsigned int to_syslog)
237 check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) ||
238 check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) ||
239 check_set_config_value(key, ENV_UMOUNT_WAIT, value, to_syslog) ||
240- check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog))
241+ check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog) ||
242+ check_set_config_value(key, ENV_MAP_HASH_TABLE_SIZE, value, to_syslog))
243 ;
244 }
245
246@@ -672,3 +675,14 @@ const char *defaults_get_auth_conf_file(void)
247 return (const char *) cf;
248 }
249
250+unsigned int defaults_get_map_hash_table_size(void)
251+{
252+ long size;
253+
254+ size = get_env_number(ENV_MAP_HASH_TABLE_SIZE);
255+ if (size < 0)
256+ size = DEFAULT_MAP_HASH_TABLE_SIZE;
257+
258+ return (unsigned int) size;
259+}
260+
261diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
262index 8256888..fe36f45 100644
263--- a/redhat/autofs.sysconfig.in
264+++ b/redhat/autofs.sysconfig.in
265@@ -89,6 +89,12 @@ BROWSE_MODE="no"
266 #
267 #AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf"
268 #
269+# MAP_HASH_TABLE_SIZE - set the map cache hash table size.
270+# Should be a power of 2 with a ratio roughly
271+# between 1:10 and 1:20 for each map.
272+#
273+#MAP_HASH_TABLE_SIZE=1024
274+#
275 # General global options
276 #
277 # If the kernel supports using the autofs miscellanous device
278diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
279index 844a6f3..4496738 100644
280--- a/samples/autofs.conf.default.in
281+++ b/samples/autofs.conf.default.in
282@@ -89,6 +89,12 @@ BROWSE_MODE="no"
283 #
284 #AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf"
285 #
286+# MAP_HASH_TABLE_SIZE - set the map cache hash table size.
287+# Should be a power of 2 with a ratio roughly
288+# between 1:10 and 1:20 for each map.
289+#
290+#MAP_HASH_TABLE_SIZE=1024
291+#
292 # General global options
293 #
294 # If the kernel supports using the autofs miscellanous device
This page took 0.052683 seconds and 4 git commands to generate.