hashtab.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Implementation of the hash table type.
  3. *
  4. * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/slab.h>
  8. #include <linux/errno.h>
  9. #include <linux/sched.h>
  10. #include "hashtab.h"
  11. struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
  12. int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
  13. u32 size)
  14. {
  15. struct hashtab *p;
  16. u32 i;
  17. p = kzalloc(sizeof(*p), GFP_KERNEL);
  18. if (p == NULL)
  19. return p;
  20. p->size = size;
  21. p->nel = 0;
  22. p->hash_value = hash_value;
  23. p->keycmp = keycmp;
  24. p->htable = kmalloc(sizeof(*(p->htable)) * size, GFP_KERNEL);
  25. if (p->htable == NULL) {
  26. kfree(p);
  27. return NULL;
  28. }
  29. for (i = 0; i < size; i++)
  30. p->htable[i] = NULL;
  31. return p;
  32. }
  33. int hashtab_insert(struct hashtab *h, void *key, void *datum)
  34. {
  35. u32 hvalue;
  36. struct hashtab_node *prev, *cur, *newnode;
  37. cond_resched();
  38. if (!h || h->nel == HASHTAB_MAX_NODES)
  39. return -EINVAL;
  40. hvalue = h->hash_value(h, key);
  41. prev = NULL;
  42. cur = h->htable[hvalue];
  43. while (cur && h->keycmp(h, key, cur->key) > 0) {
  44. prev = cur;
  45. cur = cur->next;
  46. }
  47. if (cur && (h->keycmp(h, key, cur->key) == 0))
  48. return -EEXIST;
  49. newnode = kzalloc(sizeof(*newnode), GFP_KERNEL);
  50. if (newnode == NULL)
  51. return -ENOMEM;
  52. newnode->key = key;
  53. newnode->datum = datum;
  54. if (prev) {
  55. newnode->next = prev->next;
  56. prev->next = newnode;
  57. } else {
  58. newnode->next = h->htable[hvalue];
  59. h->htable[hvalue] = newnode;
  60. }
  61. h->nel++;
  62. return 0;
  63. }
  64. void *hashtab_search(struct hashtab *h, const void *key)
  65. {
  66. u32 hvalue;
  67. struct hashtab_node *cur;
  68. if (!h)
  69. return NULL;
  70. hvalue = h->hash_value(h, key);
  71. cur = h->htable[hvalue];
  72. while (cur && h->keycmp(h, key, cur->key) > 0)
  73. cur = cur->next;
  74. if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
  75. return NULL;
  76. return cur->datum;
  77. }
  78. void hashtab_destroy(struct hashtab *h)
  79. {
  80. u32 i;
  81. struct hashtab_node *cur, *temp;
  82. if (!h)
  83. return;
  84. for (i = 0; i < h->size; i++) {
  85. cur = h->htable[i];
  86. while (cur) {
  87. temp = cur;
  88. cur = cur->next;
  89. kfree(temp);
  90. }
  91. h->htable[i] = NULL;
  92. }
  93. kfree(h->htable);
  94. h->htable = NULL;
  95. kfree(h);
  96. }
  97. int hashtab_map(struct hashtab *h,
  98. int (*apply)(void *k, void *d, void *args),
  99. void *args)
  100. {
  101. u32 i;
  102. int ret;
  103. struct hashtab_node *cur;
  104. if (!h)
  105. return 0;
  106. for (i = 0; i < h->size; i++) {
  107. cur = h->htable[i];
  108. while (cur) {
  109. ret = apply(cur->key, cur->datum, args);
  110. if (ret)
  111. return ret;
  112. cur = cur->next;
  113. }
  114. }
  115. return 0;
  116. }
  117. void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
  118. {
  119. u32 i, chain_len, slots_used, max_chain_len;
  120. struct hashtab_node *cur;
  121. slots_used = 0;
  122. max_chain_len = 0;
  123. for (slots_used = max_chain_len = i = 0; i < h->size; i++) {
  124. cur = h->htable[i];
  125. if (cur) {
  126. slots_used++;
  127. chain_len = 0;
  128. while (cur) {
  129. chain_len++;
  130. cur = cur->next;
  131. }
  132. if (chain_len > max_chain_len)
  133. max_chain_len = chain_len;
  134. }
  135. }
  136. info->slots_used = slots_used;
  137. info->max_chain_len = max_chain_len;
  138. }