Commit 6b6df46663e7aa6f7b1d82435a3488f9b81316b3
Committed by
Pablo Neira Ayuso
1 parent
71dfa982f1
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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
include/net/ip_vs.h
... | ... | @@ -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(¶m, &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 |