Skip to content

Commit 9707bc9

Browse files
Annotate lockless reads in homa_qdisc_deferred_offset
homa_qdisc_deferred_offset reads the length of an RPC's deferred packet queue and its tx_left without holding qdev->defer_lock, while the pacer modifies both under that lock. The race is intentional, but the reads were plain loads, which KCSAN reports as a data race. Use skb_queue_len_lockless and READ_ONCE/WRITE_ONCE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 4bd0275 commit 9707bc9

2 files changed

Lines changed: 6 additions & 5 deletions

File tree

‎homa_qdisc.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ void homa_qdisc_defer_homa(struct homa_qdisc_dev *qdev, struct sk_buff *skb)
753753
h = (struct homa_data_hdr *)skb_transport_header(skb);
754754
bytes_left = rpc->msgout.length - ntohl(h->seg.offset);
755755
if (bytes_left < rpc->qrpc.tx_left)
756-
rpc->qrpc.tx_left = bytes_left;
756+
WRITE_ONCE(rpc->qrpc.tx_left, bytes_left);
757757
rpc->qrpc.qdev = qdev;
758758
homa_qdisc_insert_rb(qdev, rpc);
759759
}
@@ -950,7 +950,7 @@ struct sk_buff *homa_qdisc_get_deferred_homa(struct homa_qdisc_dev *qdev)
950950
bytes_left = rpc->msgout.length - (ntohl(h->seg.offset) +
951951
info->data_bytes);
952952
if (bytes_left < qrpc->tx_left)
953-
qrpc->tx_left = bytes_left;
953+
WRITE_ONCE(qrpc->tx_left, bytes_left);
954954
if (fifo) {
955955
if (skb_queue_len(&qrpc->packets) > 0) {
956956
rb_erase_cached(node, &qdev->deferred_rpcs);

‎homa_qdisc.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,11 @@ static inline bool homa_qdisc_precedes(struct homa_rpc *rpc1,
484484
static inline int homa_qdisc_deferred_offset(struct homa_rpc *rpc)
485485
{
486486
/* This doesn't synchronize, but the worst that can happen is
487-
* to return a slightly out-of-date result.
487+
* to return a slightly out-of-date result. The pacer modifies
488+
* these fields concurrently, under qdev->defer_lock.
488489
*/
489-
if (skb_queue_len(&rpc->qrpc.packets) > 0)
490-
return rpc->msgout.length - rpc->qrpc.tx_left;
490+
if (skb_queue_len_lockless(&rpc->qrpc.packets) > 0)
491+
return rpc->msgout.length - READ_ONCE(rpc->qrpc.tx_left);
491492
return -1;
492493
}
493494

0 commit comments

Comments
 (0)