~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/ipvs/ip_vs_sched.c

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * IPVS         An implementation of the IP virtual server support for the
  3  *              LINUX operating system.  IPVS is now implemented as a module
  4  *              over the Netfilter framework. IPVS can be used to build a
  5  *              high-performance and highly available server based on a
  6  *              cluster of servers.
  7  *
  8  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  9  *              Peter Kese <peter.kese@ijs.si>
 10  *
 11  *              This program is free software; you can redistribute it and/or
 12  *              modify it under the terms of the GNU General Public License
 13  *              as published by the Free Software Foundation; either version
 14  *              2 of the License, or (at your option) any later version.
 15  *
 16  * Changes:
 17  *
 18  */
 19 
 20 #define KMSG_COMPONENT "IPVS"
 21 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 22 
 23 #include <linux/module.h>
 24 #include <linux/spinlock.h>
 25 #include <linux/interrupt.h>
 26 #include <asm/string.h>
 27 #include <linux/kmod.h>
 28 #include <linux/sysctl.h>
 29 
 30 #include <net/ip_vs.h>
 31 
 32 EXPORT_SYMBOL(ip_vs_scheduler_err);
 33 /*
 34  *  IPVS scheduler list
 35  */
 36 static LIST_HEAD(ip_vs_schedulers);
 37 
 38 /* lock for service table */
 39 static DEFINE_SPINLOCK(ip_vs_sched_lock);
 40 
 41 
 42 /*
 43  *  Bind a service with a scheduler
 44  */
 45 int ip_vs_bind_scheduler(struct ip_vs_service *svc,
 46                          struct ip_vs_scheduler *scheduler)
 47 {
 48         int ret;
 49 
 50         svc->scheduler = scheduler;
 51 
 52         if (scheduler->init_service) {
 53                 ret = scheduler->init_service(svc);
 54                 if (ret) {
 55                         pr_err("%s(): init error\n", __func__);
 56                         return ret;
 57                 }
 58         }
 59 
 60         return 0;
 61 }
 62 
 63 
 64 /*
 65  *  Unbind a service with its scheduler
 66  */
 67 int ip_vs_unbind_scheduler(struct ip_vs_service *svc)
 68 {
 69         struct ip_vs_scheduler *sched = svc->scheduler;
 70 
 71         if (!sched)
 72                 return 0;
 73 
 74         if (sched->done_service) {
 75                 if (sched->done_service(svc) != 0) {
 76                         pr_err("%s(): done error\n", __func__);
 77                         return -EINVAL;
 78                 }
 79         }
 80 
 81         svc->scheduler = NULL;
 82         return 0;
 83 }
 84 
 85 
 86 /*
 87  *  Get scheduler in the scheduler list by name
 88  */
 89 static struct ip_vs_scheduler *ip_vs_sched_getbyname(const char *sched_name)
 90 {
 91         struct ip_vs_scheduler *sched;
 92 
 93         IP_VS_DBG(2, "%s(): sched_name \"%s\"\n", __func__, sched_name);
 94 
 95         spin_lock_bh(&ip_vs_sched_lock);
 96 
 97         list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
 98                 /*
 99                  * Test and get the modules atomically
100                  */
101                 if (sched->module && !try_module_get(sched->module)) {
102                         /*
103                          * This scheduler is just deleted
104                          */
105                         continue;
106                 }
107                 if (strcmp(sched_name, sched->name)==0) {
108                         /* HIT */
109                         spin_unlock_bh(&ip_vs_sched_lock);
110                         return sched;
111                 }
112                 if (sched->module)
113                         module_put(sched->module);
114         }
115 
116         spin_unlock_bh(&ip_vs_sched_lock);
117         return NULL;
118 }
119 
120 
121 /*
122  *  Lookup scheduler and try to load it if it doesn't exist
123  */
124 struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name)
125 {
126         struct ip_vs_scheduler *sched;
127 
128         /*
129          *  Search for the scheduler by sched_name
130          */
131         sched = ip_vs_sched_getbyname(sched_name);
132 
133         /*
134          *  If scheduler not found, load the module and search again
135          */
136         if (sched == NULL) {
137                 request_module("ip_vs_%s", sched_name);
138                 sched = ip_vs_sched_getbyname(sched_name);
139         }
140 
141         return sched;
142 }
143 
144 void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
145 {
146         if (scheduler && scheduler->module)
147                 module_put(scheduler->module);
148 }
149 
150 /*
151  * Common error output helper for schedulers
152  */
153 
154 void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
155 {
156         if (svc->fwmark) {
157                 IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
158                              svc->scheduler->name, svc->fwmark,
159                              svc->fwmark, msg);
160 #ifdef CONFIG_IP_VS_IPV6
161         } else if (svc->af == AF_INET6) {
162                 IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
163                              svc->scheduler->name,
164                              ip_vs_proto_name(svc->protocol),
165                              &svc->addr.in6, ntohs(svc->port), msg);
166 #endif
167         } else {
168                 IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
169                              svc->scheduler->name,
170                              ip_vs_proto_name(svc->protocol),
171                              &svc->addr.ip, ntohs(svc->port), msg);
172         }
173 }
174 
175 /*
176  *  Register a scheduler in the scheduler list
177  */
178 int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
179 {
180         struct ip_vs_scheduler *sched;
181 
182         if (!scheduler) {
183                 pr_err("%s(): NULL arg\n", __func__);
184                 return -EINVAL;
185         }
186 
187         if (!scheduler->name) {
188                 pr_err("%s(): NULL scheduler_name\n", __func__);
189                 return -EINVAL;
190         }
191 
192         /* increase the module use count */
193         ip_vs_use_count_inc();
194 
195         spin_lock_bh(&ip_vs_sched_lock);
196 
197         if (!list_empty(&scheduler->n_list)) {
198                 spin_unlock_bh(&ip_vs_sched_lock);
199                 ip_vs_use_count_dec();
200                 pr_err("%s(): [%s] scheduler already linked\n",
201                        __func__, scheduler->name);
202                 return -EINVAL;
203         }
204 
205         /*
206          *  Make sure that the scheduler with this name doesn't exist
207          *  in the scheduler list.
208          */
209         list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
210                 if (strcmp(scheduler->name, sched->name) == 0) {
211                         spin_unlock_bh(&ip_vs_sched_lock);
212                         ip_vs_use_count_dec();
213                         pr_err("%s(): [%s] scheduler already existed "
214                                "in the system\n", __func__, scheduler->name);
215                         return -EINVAL;
216                 }
217         }
218         /*
219          *      Add it into the d-linked scheduler list
220          */
221         list_add(&scheduler->n_list, &ip_vs_schedulers);
222         spin_unlock_bh(&ip_vs_sched_lock);
223 
224         pr_info("[%s] scheduler registered.\n", scheduler->name);
225 
226         return 0;
227 }
228 
229 
230 /*
231  *  Unregister a scheduler from the scheduler list
232  */
233 int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
234 {
235         if (!scheduler) {
236                 pr_err("%s(): NULL arg\n", __func__);
237                 return -EINVAL;
238         }
239 
240         spin_lock_bh(&ip_vs_sched_lock);
241         if (list_empty(&scheduler->n_list)) {
242                 spin_unlock_bh(&ip_vs_sched_lock);
243                 pr_err("%s(): [%s] scheduler is not in the list. failed\n",
244                        __func__, scheduler->name);
245                 return -EINVAL;
246         }
247 
248         /*
249          *      Remove it from the d-linked scheduler list
250          */
251         list_del(&scheduler->n_list);
252         spin_unlock_bh(&ip_vs_sched_lock);
253 
254         /* decrease the module use count */
255         ip_vs_use_count_dec();
256 
257         pr_info("[%s] scheduler unregistered.\n", scheduler->name);
258 
259         return 0;
260 }
261 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp