net: shaper: annotate the data races

As previously discussed we don't care about making the shaper
state fully RCU-compliant because the hierarchy itself can't
be dumped in one go over Netlink. Let's annotate the reads
and writes to make that clear.

The field-by-field assignments will also be useful for the
next commit which adds explicit "valid" field (which we don't
want to override with the current full struct assignment).

Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260515221325.1685455-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-05-15 15:13:24 -07:00
parent abe003b332
commit a3442936dd

View File

@ -138,35 +138,58 @@ static int net_shaper_fill_handle(struct sk_buff *msg,
return -EMSGSIZE;
}
static void net_shaper_copy(struct net_shaper *dst,
const struct net_shaper *src)
{
WRITE_ONCE(dst->parent.scope, READ_ONCE(src->parent.scope));
WRITE_ONCE(dst->parent.id, READ_ONCE(src->parent.id));
WRITE_ONCE(dst->handle.scope, READ_ONCE(src->handle.scope));
WRITE_ONCE(dst->handle.id, READ_ONCE(src->handle.id));
WRITE_ONCE(dst->metric, READ_ONCE(src->metric));
WRITE_ONCE(dst->bw_min, READ_ONCE(src->bw_min));
WRITE_ONCE(dst->bw_max, READ_ONCE(src->bw_max));
WRITE_ONCE(dst->burst, READ_ONCE(src->burst));
WRITE_ONCE(dst->priority, READ_ONCE(src->priority));
WRITE_ONCE(dst->weight, READ_ONCE(src->weight));
/* private fields are only used on the write path under the lock */
data_race(dst->leaves = src->leaves);
}
static int
net_shaper_fill_one(struct sk_buff *msg,
const struct net_shaper_binding *binding,
const struct net_shaper *shaper,
const struct genl_info *info)
{
struct net_shaper cur;
void *hdr;
hdr = genlmsg_iput(msg, info);
if (!hdr)
return -EMSGSIZE;
/* Make a copy to avoid data races */
net_shaper_copy(&cur, shaper);
if (net_shaper_fill_binding(msg, binding, NET_SHAPER_A_IFINDEX) ||
net_shaper_fill_handle(msg, &shaper->parent,
net_shaper_fill_handle(msg, &cur.parent,
NET_SHAPER_A_PARENT) ||
net_shaper_fill_handle(msg, &shaper->handle,
net_shaper_fill_handle(msg, &cur.handle,
NET_SHAPER_A_HANDLE) ||
((shaper->bw_min || shaper->bw_max || shaper->burst) &&
nla_put_u32(msg, NET_SHAPER_A_METRIC, shaper->metric)) ||
(shaper->bw_min &&
nla_put_uint(msg, NET_SHAPER_A_BW_MIN, shaper->bw_min)) ||
(shaper->bw_max &&
nla_put_uint(msg, NET_SHAPER_A_BW_MAX, shaper->bw_max)) ||
(shaper->burst &&
nla_put_uint(msg, NET_SHAPER_A_BURST, shaper->burst)) ||
(shaper->priority &&
nla_put_u32(msg, NET_SHAPER_A_PRIORITY, shaper->priority)) ||
(shaper->weight &&
nla_put_u32(msg, NET_SHAPER_A_WEIGHT, shaper->weight)))
((cur.bw_min || cur.bw_max || cur.burst) &&
nla_put_u32(msg, NET_SHAPER_A_METRIC, cur.metric)) ||
(cur.bw_min &&
nla_put_uint(msg, NET_SHAPER_A_BW_MIN, cur.bw_min)) ||
(cur.bw_max &&
nla_put_uint(msg, NET_SHAPER_A_BW_MAX, cur.bw_max)) ||
(cur.burst &&
nla_put_uint(msg, NET_SHAPER_A_BURST, cur.burst)) ||
(cur.priority &&
nla_put_u32(msg, NET_SHAPER_A_PRIORITY, cur.priority)) ||
(cur.weight &&
nla_put_u32(msg, NET_SHAPER_A_WEIGHT, cur.weight)))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@ -424,7 +447,7 @@ static void net_shaper_commit(struct net_shaper_binding *binding,
/* Successful update: drop the tentative mark
* and update the hierarchy container.
*/
*cur = shapers[i];
net_shaper_copy(cur, &shapers[i]);
smp_wmb();
__xa_set_mark(&hierarchy->shapers, index, NET_SHAPER_VALID);
}