Skip to content

Commit 74d6a5d

Browse files
Wang Haimartinetd
authored andcommitted
9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
p9_read_work and p9_fd_cancelled may be called concurrently. In some cases, req->req_list may be deleted by both p9_read_work and p9_fd_cancelled. We can fix it by ignoring replies associated with a cancelled request and ignoring cancelled request if message has been received before lock. Link: http://lkml.kernel.org/r/[email protected] Fixes: 60ff779 ("9p: client: remove unused code and any reference to "cancelled" function") Cc: <[email protected]> # v3.12+ Reported-by: [email protected] Signed-off-by: Wang Hai <[email protected]> Signed-off-by: Dominique Martinet <[email protected]>
1 parent a39c460 commit 74d6a5d

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

net/9p/trans_fd.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ static void p9_read_work(struct work_struct *work)
362362
if (m->rreq->status == REQ_STATUS_SENT) {
363363
list_del(&m->rreq->req_list);
364364
p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD);
365+
} else if (m->rreq->status == REQ_STATUS_FLSHD) {
366+
/* Ignore replies associated with a cancelled request. */
367+
p9_debug(P9_DEBUG_TRANS,
368+
"Ignore replies associated with a cancelled request\n");
365369
} else {
366370
spin_unlock(&m->client->lock);
367371
p9_debug(P9_DEBUG_ERROR,
@@ -703,11 +707,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
703707
{
704708
p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
705709

710+
spin_lock(&client->lock);
711+
/* Ignore cancelled request if message has been received
712+
* before lock.
713+
*/
714+
if (req->status == REQ_STATUS_RCVD) {
715+
spin_unlock(&client->lock);
716+
return 0;
717+
}
718+
706719
/* we haven't received a response for oldreq,
707720
* remove it from the list.
708721
*/
709-
spin_lock(&client->lock);
710722
list_del(&req->req_list);
723+
req->status = REQ_STATUS_FLSHD;
711724
spin_unlock(&client->lock);
712725
p9_req_put(req);
713726

0 commit comments

Comments
 (0)