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