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                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 */
  48struct 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 */
  65int 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}
  93EXPORT_SYMBOL_GPL(register_ip_vs_pe);
  94
  95/* Unregister a pe from the pe list */
  96int 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}
 110EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);
 111