Re: [PATCH nf v2] ipvs: make destination flags atomic

Vadim Fedorenko <[email protected]> Wed, 8 Jul 2026 09:53:28 +0100
Newsgroups org.kernel.vger.lvs-devel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev,org.kernel.vger.netfilter-devel,org.kernel.vger.stable
Message-ID <[email protected]>
On 08/07/2026 07:04, Yizhou Zhao wrote:
> IPVS destination schedulers read dest->flags from packet processing paths
> while holding only the RCU read lock.  The same word is updated by plain
> read-modify-write operations from connection accounting and destination
> update paths, for example ip_vs_bind_dest(), ip_vs_unbind_dest(), and
> __ip_vs_update_dest().
> 
> The RCU read lock protects the destination lifetime, but it does not
> serialize accesses to dest->flags.  A plain load can therefore race with a
> plain write, and concurrent plain read-modify-write updates can lose an
> AVAILABLE or OVERLOAD bit update.
> 
> KCSAN reports the race with a standard IPVS configuration using the SH
> scheduler and a destination with u_threshold set:
> 
>    BUG: KCSAN: data-race in __ip_vs_update_dest / ip_vs_sh_schedule
>    write to ... of 4 bytes by task ipvs_cfg:
>      __ip_vs_update_dest
>      ip_vs_edit_dest
>      do_ip_vs_set_ctl
>      __x64_sys_setsockopt
>    read to ... of 4 bytes by task ipvs_churn:
>      ip_vs_sh_schedule
>      ip_vs_schedule
>      tcp_conn_schedule
>      ip_vs_in_hook
>      tcp_connect
>      __x64_sys_connect
>    value changed: 0x00000003 -> 0x00000001
> 
> Convert dest->flags to atomic_t and use atomic_read(), atomic_or(), and
> atomic_and() for all destination flag tests and updates.  This preserves
> the existing 32-bit field size while making the flag updates atomic RMW
> operations and making readers use atomic accesses.  Valid minimum-sized
> IPVS configuration and scheduling paths are unchanged; only the
> synchronization of the destination status flags changes.
> 
> This is limited to synchronizing the flags word itself.  It does not add
> ordering for readers, and it does not make scheduler decisions operate on a
> fresh snapshot of all destination state; readers may still observe stale
> state in the usual IPVS fast path. This keeps the packet fast path free
> of additional barriers or locks.
> 
> Fixes: eba3b5a78799d ("ipvs: SH fallback and L4 hashing")
> Cc: [email protected]
> Reported-by: Yizhou Zhao <[email protected]>
> Reported-by: Yuxiang Yang <[email protected]>
> Reported-by: Ao Wang <[email protected]>
> Reported-by: Xuewei Feng <[email protected]>
> Reported-by: Qi Li <[email protected]>
> Reported-by: Ke Xu <[email protected]>
> Assisted-by: Claude-Code:GLM-5.2
> Signed-off-by: Yizhou Zhao <[email protected]>
> ---
> Changes in v2:
> - Clarify that the patch fixes the flags data race and RMW lost updates,
>    but does not prevent readers from observing stale scheduling state.
> - Fix checkpatch logical-continuation warnings.
> - Suggested by Julian Anastasov.
> - Link to v1: https://lore.kernel.org/netfilter-devel/[email protected]/
> ---
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index 49297fec448a..bb969738ed73 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -972,7 +972,7 @@ struct ip_vs_dest {
>   	u16			af;		/* address family */
>   	__be16			port;		/* port number of the server */
>   	union nf_inet_addr	addr;		/* IP address of the server */
> -	volatile unsigned int	flags;		/* dest status flags */
> +	atomic_t		flags;		/* dest status flags */
>   	atomic_t		conn_flags;	/* flags to copy to conn */
>   	atomic_t		weight;		/* server weight */
>   	atomic_t		last_weight;	/* server latest weight */

It would be quite interesting to look at pahole output of ip_vs_dest
structure after the modification, it may have some "areas to improve"
for the performance