[PATCH 3/3] smb/server: stop new async work when closing connection
ChenXiaoSong <[email protected]>
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
From: ChenXiaoSong <[email protected]> A new async request may be added while a connection is closing. The close code may miss this request and wait forever. Check the connection state before adding the request. Return an error and release the async ID if the connection is closing. Signed-off-by: ChenXiaoSong <[email protected]> --- fs/smb/server/smb2pdu.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 72e1b2b0a6fe..4203771891fd 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -799,21 +799,27 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) pr_err("Failed to alloc async message id\n"); return id; } - work->asynchronous = true; - work->async_id = id; - ksmbd_debug(SMB, - "Send interim Response to inform async request id : %d\n", - work->async_id); + spin_lock(&conn->request_lock); + if (ksmbd_conn_exiting(conn) || ksmbd_conn_releasing(conn)) { + spin_unlock(&conn->request_lock); + pr_err("Failed to setup async work: connection is exiting\n"); + ksmbd_release_id(&conn->async_ida, id); + return -ESHUTDOWN; + } + work->asynchronous = true; + work->async_id = id; work->cancel_fn = fn; work->cancel_argv = arg; - if (list_empty(&work->async_request_entry)) { - spin_lock(&conn->request_lock); + if (list_empty(&work->async_request_entry)) list_add_tail(&work->async_request_entry, &conn->async_requests); - spin_unlock(&conn->request_lock); - } + spin_unlock(&conn->request_lock); + + ksmbd_debug(SMB, + "Send interim Response to inform async request id : %d\n", + work->async_id); return 0; } -- 2.54.0