Commit 6b6df46663e7aa6f7b1d82435a3488f9b81316b3

Authored by Julian Anastasov
Committed by Pablo Neira Ayuso
1 parent 71dfa982f1

ipvs: preparations for using rcu in schedulers

Allow schedulers to use rcu_dereference when
returning destination on lookup. The RCU read-side critical
section will allow ip_vs_bind_dest to get dest refcnt as
preparation for the step where destinations will be
deleted without an IP_VS_WAIT_WHILE guard that holds the
packet processing during update.

	Add new optional scheduler methods add_dest,
del_dest and upd_dest. For now the methods are called
together with update_service but update_service will be
removed in a following change.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>

Showing 3 changed files with 20 additions and 0 deletions Side-by-side Diff

... ... @@ -805,6 +805,12 @@
805 805 int (*done_service)(struct ip_vs_service *svc);
806 806 /* scheduler updating service */
807 807 int (*update_service)(struct ip_vs_service *svc);
  808 + /* dest is linked */
  809 + int (*add_dest)(struct ip_vs_service *svc, struct ip_vs_dest *dest);
  810 + /* dest is unlinked */
  811 + int (*del_dest)(struct ip_vs_service *svc, struct ip_vs_dest *dest);
  812 + /* dest is updated */
  813 + int (*upd_dest)(struct ip_vs_service *svc, struct ip_vs_dest *dest);
808 814  
809 815 /* selecting a server from the given service */
810 816 struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,
net/netfilter/ipvs/ip_vs_core.c
... ... @@ -301,8 +301,10 @@
301 301 * template is not available.
302 302 * return *ignored=0 i.e. ICMP and NF_DROP
303 303 */
  304 + rcu_read_lock();
304 305 dest = svc->scheduler->schedule(svc, skb);
305 306 if (!dest) {
  307 + rcu_read_unlock();
306 308 IP_VS_DBG(1, "p-schedule: no dest found.\n");
307 309 kfree(param.pe_data);
308 310 *ignored = 0;
... ... @@ -318,6 +320,7 @@
318 320 * when the template expires */
319 321 ct = ip_vs_conn_new(&param, &dest->addr, dport,
320 322 IP_VS_CONN_F_TEMPLATE, dest, skb->mark);
  323 + rcu_read_unlock();
321 324 if (ct == NULL) {
322 325 kfree(param.pe_data);
323 326 *ignored = -1;
324 327  
... ... @@ -446,8 +449,10 @@
446 449 return NULL;
447 450 }
448 451  
  452 + rcu_read_lock();
449 453 dest = svc->scheduler->schedule(svc, skb);
450 454 if (dest == NULL) {
  455 + rcu_read_unlock();
451 456 IP_VS_DBG(1, "Schedule: no dest found.\n");
452 457 return NULL;
453 458 }
... ... @@ -468,6 +473,7 @@
468 473 cp = ip_vs_conn_new(&p, &dest->addr,
469 474 dest->port ? dest->port : pptr[1],
470 475 flags, dest, skb->mark);
  476 + rcu_read_unlock();
471 477 if (!cp) {
472 478 *ignored = -1;
473 479 return NULL;
net/netfilter/ipvs/ip_vs_ctl.c
... ... @@ -825,6 +825,11 @@
825 825 if (add) {
826 826 list_add(&dest->n_list, &svc->destinations);
827 827 svc->num_dests++;
  828 + if (svc->scheduler->add_dest)
  829 + svc->scheduler->add_dest(svc, dest);
  830 + } else {
  831 + if (svc->scheduler->upd_dest)
  832 + svc->scheduler->upd_dest(svc, dest);
828 833 }
829 834  
830 835 /* call the update_service, because server weight may be changed */
... ... @@ -1070,6 +1075,9 @@
1070 1075 */
1071 1076 list_del(&dest->n_list);
1072 1077 svc->num_dests--;
  1078 +
  1079 + if (svcupd && svc->scheduler->del_dest)
  1080 + svc->scheduler->del_dest(svc, dest);
1073 1081  
1074 1082 /*
1075 1083 * Call the update_service function of its scheduler