inet_hashtables.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * INET An implementation of the TCP/IP protocol suite for the LINUX
  3. * operating system. INET is implemented using the BSD Socket
  4. * interface as the means of communication with the user level.
  5. *
  6. * Generic INET transport hashtables
  7. *
  8. * Authors: Lotsa people, from code originally in tcp
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version
  13. * 2 of the License, or (at your option) any later version.
  14. */
  15. #include <linux/config.h>
  16. #include <linux/module.h>
  17. #include <linux/slab.h>
  18. #include <net/inet_hashtables.h>
  19. /*
  20. * Allocate and initialize a new local port bind bucket.
  21. * The bindhash mutex for snum's hash chain must be held here.
  22. */
  23. struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
  24. struct inet_bind_hashbucket *head,
  25. const unsigned short snum)
  26. {
  27. struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, SLAB_ATOMIC);
  28. if (tb != NULL) {
  29. tb->port = snum;
  30. tb->fastreuse = 0;
  31. INIT_HLIST_HEAD(&tb->owners);
  32. hlist_add_head(&tb->node, &head->chain);
  33. }
  34. return tb;
  35. }
  36. EXPORT_SYMBOL(inet_bind_bucket_create);
  37. /*
  38. * Caller must hold hashbucket lock for this tb with local BH disabled
  39. */
  40. void inet_bind_bucket_destroy(kmem_cache_t *cachep, struct inet_bind_bucket *tb)
  41. {
  42. if (hlist_empty(&tb->owners)) {
  43. __hlist_del(&tb->node);
  44. kmem_cache_free(cachep, tb);
  45. }
  46. }
  47. void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
  48. const unsigned short snum)
  49. {
  50. struct inet_sock *inet = inet_sk(sk);
  51. inet->num = snum;
  52. sk_add_bind_node(sk, &tb->owners);
  53. inet->bind_hash = tb;
  54. }
  55. EXPORT_SYMBOL(inet_bind_hash);
  56. /*
  57. * Get rid of any references to a local port held by the given sock.
  58. */
  59. static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
  60. {
  61. struct inet_sock *inet = inet_sk(sk);
  62. const int bhash = inet_bhashfn(inet->num, hashinfo->bhash_size);
  63. struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
  64. struct inet_bind_bucket *tb;
  65. spin_lock(&head->lock);
  66. tb = inet->bind_hash;
  67. __sk_del_bind_node(sk);
  68. inet->bind_hash = NULL;
  69. inet->num = 0;
  70. inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
  71. spin_unlock(&head->lock);
  72. }
  73. void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
  74. {
  75. local_bh_disable();
  76. __inet_put_port(hashinfo, sk);
  77. local_bh_enable();
  78. }
  79. EXPORT_SYMBOL(inet_put_port);