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