Skip to content

Commit 31934da

Browse files
jiangyiwen123Dominique Martinet
authored andcommitted
net/9p/virtio: Fix hard lockup in req_done
When client has multiple threads that issue io requests all the time, and the server has a very good performance, it may cause cpu is running in the irq context for a long time because it can check virtqueue has buf in the *while* loop. So we should keep chan->lock in the whole loop. [ Dominique: reworded subject line ] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Yiwen Jiang <[email protected]> To: Andrew Morton <[email protected]> To: Eric Van Hensbergen <[email protected]> To: Ron Minnich <[email protected]> To: Latchesar Ionkov <[email protected]> Signed-off-by: Dominique Martinet <[email protected]>
1 parent c7ebbae commit 31934da

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

net/9p/trans_virtio.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,24 +144,25 @@ static void req_done(struct virtqueue *vq)
144144
struct virtio_chan *chan = vq->vdev->priv;
145145
unsigned int len;
146146
struct p9_req_t *req;
147+
bool need_wakeup = false;
147148
unsigned long flags;
148149

149150
p9_debug(P9_DEBUG_TRANS, ": request done\n");
150151

151-
while (1) {
152-
spin_lock_irqsave(&chan->lock, flags);
153-
req = virtqueue_get_buf(chan->vq, &len);
154-
if (req == NULL) {
155-
spin_unlock_irqrestore(&chan->lock, flags);
156-
break;
152+
spin_lock_irqsave(&chan->lock, flags);
153+
while ((req = virtqueue_get_buf(chan->vq, &len)) != NULL) {
154+
if (!chan->ring_bufs_avail) {
155+
chan->ring_bufs_avail = 1;
156+
need_wakeup = true;
157157
}
158-
chan->ring_bufs_avail = 1;
159-
spin_unlock_irqrestore(&chan->lock, flags);
160-
/* Wakeup if anyone waiting for VirtIO ring space. */
161-
wake_up(chan->vc_wq);
158+
162159
if (len)
163160
p9_client_cb(chan->client, req, REQ_STATUS_RCVD);
164161
}
162+
spin_unlock_irqrestore(&chan->lock, flags);
163+
/* Wakeup if anyone waiting for VirtIO ring space. */
164+
if (need_wakeup)
165+
wake_up(chan->vc_wq);
165166
}
166167

167168
/**

0 commit comments

Comments
 (0)