2 * Implementation of the hash table type.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
6 #include <linux/kernel.h>
7 #include <linux/slab.h>
8 #include <linux/errno.h>
11 struct hashtab
*hashtab_create(u32 (*hash_value
)(struct hashtab
*h
, void *key
),
12 int (*keycmp
)(struct hashtab
*h
, void *key1
, void *key2
),
18 p
= kmalloc(sizeof(*p
), GFP_KERNEL
);
22 memset(p
, 0, sizeof(*p
));
25 p
->hash_value
= hash_value
;
27 p
->htable
= kmalloc(sizeof(*(p
->htable
)) * size
, GFP_KERNEL
);
28 if (p
->htable
== NULL
) {
33 for (i
= 0; i
< size
; i
++)
39 int hashtab_insert(struct hashtab
*h
, void *key
, void *datum
)
42 struct hashtab_node
*prev
, *cur
, *newnode
;
44 if (!h
|| h
->nel
== HASHTAB_MAX_NODES
)
47 hvalue
= h
->hash_value(h
, key
);
49 cur
= h
->htable
[hvalue
];
50 while (cur
&& h
->keycmp(h
, key
, cur
->key
) > 0) {
55 if (cur
&& (h
->keycmp(h
, key
, cur
->key
) == 0))
58 newnode
= kmalloc(sizeof(*newnode
), GFP_KERNEL
);
61 memset(newnode
, 0, sizeof(*newnode
));
63 newnode
->datum
= datum
;
65 newnode
->next
= prev
->next
;
68 newnode
->next
= h
->htable
[hvalue
];
69 h
->htable
[hvalue
] = newnode
;
76 int hashtab_remove(struct hashtab
*h
, void *key
,
77 void (*destroy
)(void *k
, void *d
, void *args
),
81 struct hashtab_node
*cur
, *last
;
86 hvalue
= h
->hash_value(h
, key
);
88 cur
= h
->htable
[hvalue
];
89 while (cur
!= NULL
&& h
->keycmp(h
, key
, cur
->key
) > 0) {
94 if (cur
== NULL
|| (h
->keycmp(h
, key
, cur
->key
) != 0))
98 h
->htable
[hvalue
] = cur
->next
;
100 last
->next
= cur
->next
;
103 destroy(cur
->key
, cur
->datum
, args
);
109 int hashtab_replace(struct hashtab
*h
, void *key
, void *datum
,
110 void (*destroy
)(void *k
, void *d
, void *args
),
114 struct hashtab_node
*prev
, *cur
, *newnode
;
119 hvalue
= h
->hash_value(h
, key
);
121 cur
= h
->htable
[hvalue
];
122 while (cur
!= NULL
&& h
->keycmp(h
, key
, cur
->key
) > 0) {
127 if (cur
&& (h
->keycmp(h
, key
, cur
->key
) == 0)) {
129 destroy(cur
->key
, cur
->datum
, args
);
133 newnode
= kmalloc(sizeof(*newnode
), GFP_KERNEL
);
136 memset(newnode
, 0, sizeof(*newnode
));
138 newnode
->datum
= datum
;
140 newnode
->next
= prev
->next
;
141 prev
->next
= newnode
;
143 newnode
->next
= h
->htable
[hvalue
];
144 h
->htable
[hvalue
] = newnode
;
151 void *hashtab_search(struct hashtab
*h
, void *key
)
154 struct hashtab_node
*cur
;
159 hvalue
= h
->hash_value(h
, key
);
160 cur
= h
->htable
[hvalue
];
161 while (cur
!= NULL
&& h
->keycmp(h
, key
, cur
->key
) > 0)
164 if (cur
== NULL
|| (h
->keycmp(h
, key
, cur
->key
) != 0))
170 void hashtab_destroy(struct hashtab
*h
)
173 struct hashtab_node
*cur
, *temp
;
178 for (i
= 0; i
< h
->size
; i
++) {
180 while (cur
!= NULL
) {
194 int hashtab_map(struct hashtab
*h
,
195 int (*apply
)(void *k
, void *d
, void *args
),
200 struct hashtab_node
*cur
;
205 for (i
= 0; i
< h
->size
; i
++) {
207 while (cur
!= NULL
) {
208 ret
= apply(cur
->key
, cur
->datum
, args
);
218 void hashtab_map_remove_on_error(struct hashtab
*h
,
219 int (*apply
)(void *k
, void *d
, void *args
),
220 void (*destroy
)(void *k
, void *d
, void *args
),
225 struct hashtab_node
*last
, *cur
, *temp
;
230 for (i
= 0; i
< h
->size
; i
++) {
233 while (cur
!= NULL
) {
234 ret
= apply(cur
->key
, cur
->datum
, args
);
237 last
->next
= cur
->next
;
239 h
->htable
[i
] = cur
->next
;
244 destroy(temp
->key
, temp
->datum
, args
);
256 void hashtab_stat(struct hashtab
*h
, struct hashtab_info
*info
)
258 u32 i
, chain_len
, slots_used
, max_chain_len
;
259 struct hashtab_node
*cur
;
263 for (slots_used
= max_chain_len
= i
= 0; i
< h
->size
; i
++) {
273 if (chain_len
> max_chain_len
)
274 max_chain_len
= chain_len
;
278 info
->slots_used
= slots_used
;
279 info
->max_chain_len
= max_chain_len
;