]> git.sesse.net Git - bcachefs-tools-debian/blob - include/linux/rhashtable.h
Delete more unused shim code, update bcache code
[bcachefs-tools-debian] / include / linux / rhashtable.h
1 /*
2  * Resizable, Scalable, Concurrent Hash Table
3  *
4  * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
5  * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
6  * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
7  *
8  * Code partially derived from nft_hash
9  * Rewritten with rehash code from br_multicast plus single list
10  * pointer as suggested by Josh Triplett
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16
17 #ifndef _LINUX_RHASHTABLE_H
18 #define _LINUX_RHASHTABLE_H
19
20 #include <linux/atomic.h>
21 #include <linux/cache.h>
22 #include <linux/compiler.h>
23 #include <linux/cpumask.h>
24 #include <linux/err.h>
25 #include <linux/errno.h>
26 #include <linux/jhash.h>
27 #include <linux/list_nulls.h>
28 #include <linux/workqueue.h>
29 #include <linux/mutex.h>
30 #include <linux/spinlock.h>
31 #include <linux/rcupdate.h>
32
33 #define RHT_BASE_BITS           4
34 #define RHT_HASH_BITS           27
35 #define RHT_BASE_SHIFT          RHT_HASH_BITS
36 #define RHT_HASH_RESERVED_SPACE (RHT_BASE_BITS + 1)
37
38 struct rhash_head {
39         struct rhash_head __rcu         *next;
40 };
41
42 struct bucket_table {
43         unsigned int            size;
44         unsigned int            rehash;
45         u32                     hash_rnd;
46         unsigned int            locks_mask;
47         spinlock_t              *locks;
48         struct list_head        walkers;
49         struct rcu_head         rcu;
50
51         struct bucket_table __rcu *future_tbl;
52
53         struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp;
54 };
55
56 struct rhashtable_compare_arg {
57         struct rhashtable *ht;
58         const void *key;
59 };
60
61 typedef u32 (*rht_hashfn_t)(const void *data, u32 len, u32 seed);
62 typedef u32 (*rht_obj_hashfn_t)(const void *data, u32 len, u32 seed);
63 typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg,
64                                const void *obj);
65
66 struct rhashtable_params {
67         size_t                  nelem_hint;
68         size_t                  key_len;
69         size_t                  key_offset;
70         size_t                  head_offset;
71         unsigned int            insecure_max_entries;
72         unsigned int            max_size;
73         unsigned int            min_size;
74         u32                     nulls_base;
75         bool                    insecure_elasticity;
76         bool                    automatic_shrinking;
77         size_t                  locks_mul;
78         rht_hashfn_t            hashfn;
79         rht_obj_hashfn_t        obj_hashfn;
80         rht_obj_cmpfn_t         obj_cmpfn;
81 };
82
83 struct rhashtable {
84         struct bucket_table __rcu       *tbl;
85         atomic_t                        nelems;
86         unsigned int                    key_len;
87         unsigned int                    elasticity;
88         struct rhashtable_params        p;
89         struct work_struct              run_work;
90         struct mutex                    mutex;
91         spinlock_t                      lock;
92 };
93
94 struct rhashtable_walker {
95         struct list_head list;
96         struct bucket_table *tbl;
97 };
98
99 static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
100 {
101         return NULLS_MARKER(ht->p.nulls_base + hash);
102 }
103
104 #define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \
105         ((ptr) = (typeof(ptr)) rht_marker(ht, hash))
106
107 static inline bool rht_is_a_nulls(const struct rhash_head *ptr)
108 {
109         return ((unsigned long) ptr & 1);
110 }
111
112 static inline unsigned long rht_get_nulls_value(const struct rhash_head *ptr)
113 {
114         return ((unsigned long) ptr) >> 1;
115 }
116
117 static inline void *rht_obj(const struct rhashtable *ht,
118                             const struct rhash_head *he)
119 {
120         return (char *)he - ht->p.head_offset;
121 }
122
123 static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
124                                             unsigned int hash)
125 {
126         return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1);
127 }
128
129 static inline unsigned int rht_key_hashfn(
130         struct rhashtable *ht, const struct bucket_table *tbl,
131         const void *key, const struct rhashtable_params params)
132 {
133         unsigned int hash;
134
135         /* params must be equal to ht->p if it isn't constant. */
136         if (!__builtin_constant_p(params.key_len))
137                 hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd);
138         else if (params.key_len) {
139                 unsigned int key_len = params.key_len;
140
141                 if (params.hashfn)
142                         hash = params.hashfn(key, key_len, tbl->hash_rnd);
143                 else if (key_len & (sizeof(u32) - 1))
144                         hash = jhash(key, key_len, tbl->hash_rnd);
145                 else
146                         hash = jhash2(key, key_len / sizeof(u32),
147                                       tbl->hash_rnd);
148         } else {
149                 unsigned int key_len = ht->p.key_len;
150
151                 if (params.hashfn)
152                         hash = params.hashfn(key, key_len, tbl->hash_rnd);
153                 else
154                         hash = jhash(key, key_len, tbl->hash_rnd);
155         }
156
157         return rht_bucket_index(tbl, hash);
158 }
159
160 static inline unsigned int rht_head_hashfn(
161         struct rhashtable *ht, const struct bucket_table *tbl,
162         const struct rhash_head *he, const struct rhashtable_params params)
163 {
164         const char *ptr = rht_obj(ht, he);
165
166         return likely(params.obj_hashfn) ?
167                rht_bucket_index(tbl, params.obj_hashfn(ptr, params.key_len ?:
168                                                             ht->p.key_len,
169                                                        tbl->hash_rnd)) :
170                rht_key_hashfn(ht, tbl, ptr + params.key_offset, params);
171 }
172
173 static inline bool rht_grow_above_75(const struct rhashtable *ht,
174                                      const struct bucket_table *tbl)
175 {
176         /* Expand table when exceeding 75% load */
177         return atomic_read(&ht->nelems) > (tbl->size / 4 * 3) &&
178                (!ht->p.max_size || tbl->size < ht->p.max_size);
179 }
180
181 static inline bool rht_shrink_below_30(const struct rhashtable *ht,
182                                        const struct bucket_table *tbl)
183 {
184         /* Shrink table beneath 30% load */
185         return atomic_read(&ht->nelems) < (tbl->size * 3 / 10) &&
186                tbl->size > ht->p.min_size;
187 }
188
189 static inline bool rht_grow_above_100(const struct rhashtable *ht,
190                                       const struct bucket_table *tbl)
191 {
192         return atomic_read(&ht->nelems) > tbl->size &&
193                 (!ht->p.max_size || tbl->size < ht->p.max_size);
194 }
195
196 static inline bool rht_grow_above_max(const struct rhashtable *ht,
197                                       const struct bucket_table *tbl)
198 {
199         return ht->p.insecure_max_entries &&
200                atomic_read(&ht->nelems) >= ht->p.insecure_max_entries;
201 }
202
203 static inline spinlock_t *rht_bucket_lock(const struct bucket_table *tbl,
204                                           unsigned int hash)
205 {
206         return &tbl->locks[hash & tbl->locks_mask];
207 }
208
209 int rhashtable_insert_rehash(struct rhashtable *, struct bucket_table *);
210 struct bucket_table *rhashtable_insert_slow(struct rhashtable *,
211                                             const void *,
212                                             struct rhash_head *,
213                                             struct bucket_table *);
214
215 int rhashtable_init(struct rhashtable *, const struct rhashtable_params *);
216 void rhashtable_destroy(struct rhashtable *);
217
218 #define rht_dereference(p, ht)                  rcu_dereference(p)
219 #define rht_dereference_rcu(p, ht)              rcu_dereference(p)
220 #define rht_dereference_bucket(p, tbl, hash)    rcu_dereference(p)
221 #define rht_dereference_bucket_rcu(p, tbl, hash) rcu_dereference(p)
222
223 #define rht_entry(tpos, pos, member) \
224         ({ tpos = container_of(pos, typeof(*tpos), member); 1; })
225
226 #define rht_for_each_continue(pos, head, tbl, hash) \
227         for (pos = rht_dereference_bucket(head, tbl, hash); \
228              !rht_is_a_nulls(pos); \
229              pos = rht_dereference_bucket((pos)->next, tbl, hash))
230
231 #define rht_for_each(pos, tbl, hash) \
232         rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash)
233
234 #define rht_for_each_rcu_continue(pos, head, tbl, hash)                 \
235         for (({barrier(); }),                                           \
236              pos = rht_dereference_bucket_rcu(head, tbl, hash);         \
237              !rht_is_a_nulls(pos);                                      \
238              pos = rcu_dereference_raw(pos->next))
239
240 #define rht_for_each_rcu(pos, tbl, hash)                                \
241         rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash)
242
243 #define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \
244         for (({barrier(); }),                                               \
245              pos = rht_dereference_bucket_rcu(head, tbl, hash);             \
246              (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member);        \
247              pos = rht_dereference_bucket_rcu(pos->next, tbl, hash))
248
249 #define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member)            \
250         rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\
251                                         tbl, hash, member)
252
253 static inline int rhashtable_compare(struct rhashtable_compare_arg *arg,
254                                      const void *obj)
255 {
256         struct rhashtable *ht = arg->ht;
257         const char *ptr = obj;
258
259         return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len);
260 }
261
262 static inline void *rhashtable_lookup_fast(
263         struct rhashtable *ht, const void *key,
264         const struct rhashtable_params params)
265 {
266         struct rhashtable_compare_arg arg = {
267                 .ht = ht,
268                 .key = key,
269         };
270         const struct bucket_table *tbl;
271         struct rhash_head *he;
272         unsigned int hash;
273
274         rcu_read_lock();
275
276         tbl = rht_dereference_rcu(ht->tbl, ht);
277 restart:
278         hash = rht_key_hashfn(ht, tbl, key, params);
279         rht_for_each_rcu(he, tbl, hash) {
280                 if (params.obj_cmpfn ?
281                     params.obj_cmpfn(&arg, rht_obj(ht, he)) :
282                     rhashtable_compare(&arg, rht_obj(ht, he)))
283                         continue;
284                 rcu_read_unlock();
285                 return rht_obj(ht, he);
286         }
287
288         /* Ensure we see any new tables. */
289         smp_rmb();
290
291         tbl = rht_dereference_rcu(tbl->future_tbl, ht);
292         if (unlikely(tbl))
293                 goto restart;
294         rcu_read_unlock();
295
296         return NULL;
297 }
298
299 static inline int __rhashtable_insert_fast(
300         struct rhashtable *ht, const void *key, struct rhash_head *obj,
301         const struct rhashtable_params params)
302 {
303         struct rhashtable_compare_arg arg = {
304                 .ht = ht,
305                 .key = key,
306         };
307         struct bucket_table *tbl, *new_tbl;
308         struct rhash_head *head;
309         spinlock_t *lock;
310         unsigned int elasticity;
311         unsigned int hash;
312         int err;
313
314 restart:
315         rcu_read_lock();
316
317         tbl = rht_dereference_rcu(ht->tbl, ht);
318
319         /* All insertions must grab the oldest table containing
320          * the hashed bucket that is yet to be rehashed.
321          */
322         for (;;) {
323                 hash = rht_head_hashfn(ht, tbl, obj, params);
324                 lock = rht_bucket_lock(tbl, hash);
325                 spin_lock_bh(lock);
326
327                 if (tbl->rehash <= hash)
328                         break;
329
330                 spin_unlock_bh(lock);
331                 tbl = rht_dereference_rcu(tbl->future_tbl, ht);
332         }
333
334         new_tbl = rht_dereference_rcu(tbl->future_tbl, ht);
335         if (unlikely(new_tbl)) {
336                 tbl = rhashtable_insert_slow(ht, key, obj, new_tbl);
337                 if (!IS_ERR_OR_NULL(tbl))
338                         goto slow_path;
339
340                 err = PTR_ERR(tbl);
341                 goto out;
342         }
343
344         err = -E2BIG;
345         if (unlikely(rht_grow_above_max(ht, tbl)))
346                 goto out;
347
348         if (unlikely(rht_grow_above_100(ht, tbl))) {
349 slow_path:
350                 spin_unlock_bh(lock);
351                 err = rhashtable_insert_rehash(ht, tbl);
352                 rcu_read_unlock();
353                 if (err)
354                         return err;
355
356                 goto restart;
357         }
358
359         err = -EEXIST;
360         elasticity = ht->elasticity;
361         rht_for_each(head, tbl, hash) {
362                 if (key &&
363                     unlikely(!(params.obj_cmpfn ?
364                                params.obj_cmpfn(&arg, rht_obj(ht, head)) :
365                                rhashtable_compare(&arg, rht_obj(ht, head)))))
366                         goto out;
367                 if (!--elasticity)
368                         goto slow_path;
369         }
370
371         err = 0;
372
373         head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash);
374
375         RCU_INIT_POINTER(obj->next, head);
376
377         rcu_assign_pointer(tbl->buckets[hash], obj);
378
379         atomic_inc(&ht->nelems);
380         if (rht_grow_above_75(ht, tbl))
381                 schedule_work(&ht->run_work);
382
383 out:
384         spin_unlock_bh(lock);
385         rcu_read_unlock();
386
387         return err;
388 }
389
390 static inline int rhashtable_lookup_insert_fast(
391         struct rhashtable *ht, struct rhash_head *obj,
392         const struct rhashtable_params params)
393 {
394         const char *key = rht_obj(ht, obj);
395
396         BUG_ON(ht->p.obj_hashfn);
397
398         return __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj,
399                                         params);
400 }
401
402 static inline int __rhashtable_remove_fast(
403         struct rhashtable *ht, struct bucket_table *tbl,
404         struct rhash_head *obj, const struct rhashtable_params params)
405 {
406         struct rhash_head __rcu **pprev;
407         struct rhash_head *he;
408         spinlock_t * lock;
409         unsigned int hash;
410         int err = -ENOENT;
411
412         hash = rht_head_hashfn(ht, tbl, obj, params);
413         lock = rht_bucket_lock(tbl, hash);
414
415         spin_lock_bh(lock);
416
417         pprev = &tbl->buckets[hash];
418         rht_for_each(he, tbl, hash) {
419                 if (he != obj) {
420                         pprev = &he->next;
421                         continue;
422                 }
423
424                 rcu_assign_pointer(*pprev, obj->next);
425                 err = 0;
426                 break;
427         }
428
429         spin_unlock_bh(lock);
430
431         return err;
432 }
433
434 static inline int rhashtable_remove_fast(
435         struct rhashtable *ht, struct rhash_head *obj,
436         const struct rhashtable_params params)
437 {
438         struct bucket_table *tbl;
439         int err;
440
441         rcu_read_lock();
442
443         tbl = rht_dereference_rcu(ht->tbl, ht);
444
445         /* Because we have already taken (and released) the bucket
446          * lock in old_tbl, if we find that future_tbl is not yet
447          * visible then that guarantees the entry to still be in
448          * the old tbl if it exists.
449          */
450         while ((err = __rhashtable_remove_fast(ht, tbl, obj, params)) &&
451                (tbl = rht_dereference_rcu(tbl->future_tbl, ht)))
452                 ;
453
454         if (err)
455                 goto out;
456
457         atomic_dec(&ht->nelems);
458         if (unlikely(ht->p.automatic_shrinking &&
459                      rht_shrink_below_30(ht, tbl)))
460                 schedule_work(&ht->run_work);
461
462 out:
463         rcu_read_unlock();
464
465         return err;
466 }
467
468 #endif /* _LINUX_RHASHTABLE_H */