• Julian Anastasov's avatar
    ipvs: make the service replacement more robust · bcbde4c0
    Julian Anastasov authored
    commit 578bc3ef ("ipvs: reorganize dest trash") added
    IP_VS_DEST_STATE_REMOVING flag and RCU callback named
    ip_vs_dest_wait_readers() to keep dests and services after
    removal for at least a RCU grace period. But we have the
    following corner cases:
    
    - we can not reuse the same dest if its service is removed
    while IP_VS_DEST_STATE_REMOVING is still set because another dest
    removal in the first grace period can not extend this period.
    It can happen when ipvsadm -C && ipvsadm -R is used.
    
    - dest->svc can be replaced but ip_vs_in_stats() and
    ip_vs_out_stats() have no explicit read memory barriers
    when accessing dest->svc. It can happen that dest->svc
    was just freed (replaced) while we use it to update
    the stats.
    
    We solve the problems as follows:
    
    - IP_VS_DEST_STATE_REMOVING is removed and we ensure a fixed
    idle period for the dest (IP_VS_DEST_TRASH_PERIOD). idle_start
    will remember when for first time after deletion we noticed
    dest->refcnt=0. Later, the connections can grab a reference
    while in RCU grace period but if refcnt becomes 0 we can
    safely free the dest and its svc.
    
    - dest->svc becomes RCU pointer. As result, we add explicit
    RCU locking in ip_vs_in_stats() and ip_vs_out_stats().
    
    - __ip_vs_unbind_svc is renamed to __ip_vs_svc_put(), it
    now can free the service immediately or after a RCU grace
    period. dest->svc is not set to NULL anymore.
    
    	As result, unlinked dests and their services are
    freed always after IP_VS_DEST_TRASH_PERIOD period, unused
    services are freed after a RCU grace period.
    Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
    Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
    bcbde4c0
ip_vs.h 46.4 KB