Hi!
From: Eric Dumazet edumazet@google.com
[ Upstream commit b756ad928d98e5ef0b74af7546a6a31a8dadde00 ]
KCSAN reported the following data-race [1]
Adding a couple of READ_ONCE()/WRITE_ONCE() should silence it.
Since the report hinted about multiple cpus using the history concurrently, I added a test avoiding writing on it if the victim slot already contains the desired value.
static bool fanout_flow_is_huge(struct packet_sock *po, struct sk_buff *skb) {
- u32 rxhash;
- u32 *history = po->rollover->history;
- u32 victim, rxhash; int i, count = 0;
rxhash = skb_get_hash(skb); for (i = 0; i < ROLLOVER_HLEN; i++)
if (po->rollover->history[i] == rxhash)
if (READ_ONCE(history[i]) == rxhash) count++;
- po->rollover->history[prandom_u32() % ROLLOVER_HLEN] = rxhash;
- victim = prandom_u32() % ROLLOVER_HLEN;
- /* Avoid dirtying the cache line if possible */
- if (READ_ONCE(history[victim]) != rxhash)
WRITE_ONCE(history[victim], rxhash);
Replacing simple asignment with if() is ... not nice and with all the "volatile" magic in _ONCE macros may not be win for everyone. [Actually, I don't think this is win here. This is not exactly hot path, is it? Is it likely that array aready contains required value?]
If this is going to get more common, should we get WRITE_ONCE_NONDIRTY() macro hiding the uglyness?
Best regards, Pavel