1 // SPDX-License-Identifier: GPL-2.0
3 * Implementation of the hash table type.
5 * Author : Stephen Smalley, <sds@tycho.nsa.gov>
7 #include <linux/kernel.h>
8 #include <linux/slab.h>
9 #include <linux/errno.h>
10 #include <linux/sched.h>
13 static struct kmem_cache
*hashtab_node_cachep
;
15 struct hashtab
*hashtab_create(u32 (*hash_value
)(struct hashtab
*h
, const void *key
),
16 int (*keycmp
)(struct hashtab
*h
, const void *key1
, const void *key2
),
22 p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
28 p
->hash_value
= hash_value
;
30 p
->htable
= kmalloc_array(size
, sizeof(*p
->htable
), GFP_KERNEL
);
36 for (i
= 0; i
< size
; i
++)
42 int hashtab_insert(struct hashtab
*h
, void *key
, void *datum
)
45 struct hashtab_node
*prev
, *cur
, *newnode
;
49 if (!h
|| h
->nel
== HASHTAB_MAX_NODES
)
52 hvalue
= h
->hash_value(h
, key
);
54 cur
= h
->htable
[hvalue
];
55 while (cur
&& h
->keycmp(h
, key
, cur
->key
) > 0) {
60 if (cur
&& (h
->keycmp(h
, key
, cur
->key
) == 0))
63 newnode
= kmem_cache_zalloc(hashtab_node_cachep
, GFP_KERNEL
);
67 newnode
->datum
= datum
;
69 newnode
->next
= prev
->next
;
72 newnode
->next
= h
->htable
[hvalue
];
73 h
->htable
[hvalue
] = newnode
;
80 void *hashtab_search(struct hashtab
*h
, const void *key
)
83 struct hashtab_node
*cur
;
88 hvalue
= h
->hash_value(h
, key
);
89 cur
= h
->htable
[hvalue
];
90 while (cur
&& h
->keycmp(h
, key
, cur
->key
) > 0)
93 if (!cur
|| (h
->keycmp(h
, key
, cur
->key
) != 0))
99 void hashtab_destroy(struct hashtab
*h
)
102 struct hashtab_node
*cur
, *temp
;
107 for (i
= 0; i
< h
->size
; i
++) {
112 kmem_cache_free(hashtab_node_cachep
, temp
);
123 int hashtab_map(struct hashtab
*h
,
124 int (*apply
)(void *k
, void *d
, void *args
),
129 struct hashtab_node
*cur
;
134 for (i
= 0; i
< h
->size
; i
++) {
137 ret
= apply(cur
->key
, cur
->datum
, args
);
147 void hashtab_stat(struct hashtab
*h
, struct hashtab_info
*info
)
149 u32 i
, chain_len
, slots_used
, max_chain_len
;
150 struct hashtab_node
*cur
;
154 for (i
= 0; i
< h
->size
; i
++) {
164 if (chain_len
> max_chain_len
)
165 max_chain_len
= chain_len
;
169 info
->slots_used
= slots_used
;
170 info
->max_chain_len
= max_chain_len
;
172 void hashtab_cache_init(void)
174 hashtab_node_cachep
= kmem_cache_create("hashtab_node",
175 sizeof(struct hashtab_node
),
176 0, SLAB_PANIC
, NULL
);
179 void hashtab_cache_destroy(void)
181 kmem_cache_destroy(hashtab_node_cachep
);