linux/net/netfilter/ipvs/ip_vs_pe.c
<<
>>
Prefs
   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 */
  14static LIST_HEAD(ip_vs_pe);
  15
  16/* semaphore for IPVS PEs. */
  17static DEFINE_MUTEX(ip_vs_pe_mutex);
  18
  19/* Get pe in the pe list by name */
  20struct 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                if (pe->module)
  41                        module_put(pe->module);
  42        }
  43        rcu_read_unlock();
  44
  45        return NULL;
  46}
  47
  48/* Lookup pe and try to load it if it doesn't exist */
  49struct ip_vs_pe *ip_vs_pe_getbyname(const char *name)
  50{
  51        struct ip_vs_pe *pe;
  52
  53        /* Search for the pe by name */
  54        pe = __ip_vs_pe_getbyname(name);
  55
  56        /* If pe not found, load the module and search again */
  57        if (!pe) {
  58                request_module("ip_vs_pe_%s", name);
  59                pe = __ip_vs_pe_getbyname(name);
  60        }
  61
  62        return pe;
  63}
  64
  65/* Register a pe in the pe list */
  66int register_ip_vs_pe(struct ip_vs_pe *pe)
  67{
  68        struct ip_vs_pe *tmp;
  69
  70        /* increase the module use count */
  71        ip_vs_use_count_inc();
  72
  73        mutex_lock(&ip_vs_pe_mutex);
  74        /* Make sure that the pe with this name doesn't exist
  75         * in the pe list.
  76         */
  77        list_for_each_entry(tmp, &ip_vs_pe, n_list) {
  78                if (strcmp(tmp->name, pe->name) == 0) {
  79                        mutex_unlock(&ip_vs_pe_mutex);
  80                        ip_vs_use_count_dec();
  81                        pr_err("%s(): [%s] pe already existed "
  82                               "in the system\n", __func__, pe->name);
  83                        return -EINVAL;
  84                }
  85        }
  86        /* Add it into the d-linked pe list */
  87        list_add_rcu(&pe->n_list, &ip_vs_pe);
  88        mutex_unlock(&ip_vs_pe_mutex);
  89
  90        pr_info("[%s] pe registered.\n", pe->name);
  91
  92        return 0;
  93}
  94EXPORT_SYMBOL_GPL(register_ip_vs_pe);
  95
  96/* Unregister a pe from the pe list */
  97int unregister_ip_vs_pe(struct ip_vs_pe *pe)
  98{
  99        mutex_lock(&ip_vs_pe_mutex);
 100        /* Remove it from the d-linked pe list */
 101        list_del_rcu(&pe->n_list);
 102        mutex_unlock(&ip_vs_pe_mutex);
 103
 104        /* decrease the module use count */
 105        ip_vs_use_count_dec();
 106
 107        pr_info("[%s] pe unregistered.\n", pe->name);
 108
 109        return 0;
 110}
 111EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);
 112