ip_vs_pe.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #define KMSG_COMPONENT "IPVS"
  2. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  3. #include <linux/module.h>
  4. #include <linux/spinlock.h>
  5. #include <linux/interrupt.h>
  6. #include <asm/string.h>
  7. #include <linux/kmod.h>
  8. #include <linux/sysctl.h>
  9. #include <net/ip_vs.h>
  10. /* IPVS pe list */
  11. static LIST_HEAD(ip_vs_pe);
  12. /* semaphore for IPVS PEs. */
  13. static DEFINE_MUTEX(ip_vs_pe_mutex);
  14. /* Get pe in the pe list by name */
  15. struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
  16. {
  17. struct ip_vs_pe *pe;
  18. IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__,
  19. pe_name);
  20. rcu_read_lock();
  21. list_for_each_entry_rcu(pe, &ip_vs_pe, n_list) {
  22. /* Test and get the modules atomically */
  23. if (pe->module &&
  24. !try_module_get(pe->module)) {
  25. /* This pe is just deleted */
  26. continue;
  27. }
  28. if (strcmp(pe_name, pe->name)==0) {
  29. /* HIT */
  30. rcu_read_unlock();
  31. return pe;
  32. }
  33. module_put(pe->module);
  34. }
  35. rcu_read_unlock();
  36. return NULL;
  37. }
  38. /* Lookup pe and try to load it if it doesn't exist */
  39. struct ip_vs_pe *ip_vs_pe_getbyname(const char *name)
  40. {
  41. struct ip_vs_pe *pe;
  42. /* Search for the pe by name */
  43. pe = __ip_vs_pe_getbyname(name);
  44. /* If pe not found, load the module and search again */
  45. if (!pe) {
  46. request_module("ip_vs_pe_%s", name);
  47. pe = __ip_vs_pe_getbyname(name);
  48. }
  49. return pe;
  50. }
  51. /* Register a pe in the pe list */
  52. int register_ip_vs_pe(struct ip_vs_pe *pe)
  53. {
  54. struct ip_vs_pe *tmp;
  55. /* increase the module use count */
  56. ip_vs_use_count_inc();
  57. mutex_lock(&ip_vs_pe_mutex);
  58. /* Make sure that the pe with this name doesn't exist
  59. * in the pe list.
  60. */
  61. list_for_each_entry(tmp, &ip_vs_pe, n_list) {
  62. if (strcmp(tmp->name, pe->name) == 0) {
  63. mutex_unlock(&ip_vs_pe_mutex);
  64. ip_vs_use_count_dec();
  65. pr_err("%s(): [%s] pe already existed "
  66. "in the system\n", __func__, pe->name);
  67. return -EINVAL;
  68. }
  69. }
  70. /* Add it into the d-linked pe list */
  71. list_add_rcu(&pe->n_list, &ip_vs_pe);
  72. mutex_unlock(&ip_vs_pe_mutex);
  73. pr_info("[%s] pe registered.\n", pe->name);
  74. return 0;
  75. }
  76. EXPORT_SYMBOL_GPL(register_ip_vs_pe);
  77. /* Unregister a pe from the pe list */
  78. int unregister_ip_vs_pe(struct ip_vs_pe *pe)
  79. {
  80. mutex_lock(&ip_vs_pe_mutex);
  81. /* Remove it from the d-linked pe list */
  82. list_del_rcu(&pe->n_list);
  83. mutex_unlock(&ip_vs_pe_mutex);
  84. /* decrease the module use count */
  85. ip_vs_use_count_dec();
  86. pr_info("[%s] pe unregistered.\n", pe->name);
  87. return 0;
  88. }
  89. EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);