summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChenXiaoSong <chenxiaosong@kylinos.cn>2026-07-23 04:11:30 +0000
committerNamjae Jeon <linkinjeon@kernel.org>2026-08-17 15:00:52 +0900
commit4fd5bad647bfa45eb86bfd2f03ba1bef3fcd5851 (patch)
treeb136ccbaecc66654ed86f2ccbd79cc4390637027
parentdf3e2150f3ea44256688ad1be9cbd7453fcf0ca2 (diff)
smb/server: cancel async requests when closing connection
An async request may still be waiting when a connection is closed. This can stop the connection from closing. Cancel active async requests before waiting for them to finish. Suggested-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r--fs/smb/server/connection.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index b08ef8e49a24..99ffb00e87bf 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -371,6 +371,26 @@ void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
wake_up_all(&conn->req_running_q);
}
+static void ksmbd_conn_cancel_async_requests(struct ksmbd_conn *conn)
+{
+ struct ksmbd_work *work, *tmp;
+
+ ksmbd_debug(CONN, "Cancel pending async requests on releasing connection\n");
+ spin_lock(&conn->request_lock);
+ list_for_each_entry_safe(work, tmp, &conn->async_requests,
+ async_request_entry) {
+ if (work->state != KSMBD_WORK_ACTIVE)
+ continue;
+
+ ksmbd_debug(CONN, "Cancel async request id %d\n",
+ work->async_id);
+ work->state = KSMBD_WORK_CANCELLED;
+ if (work->cancel_fn)
+ work->cancel_fn(work->cancel_argv);
+ }
+ spin_unlock(&conn->request_lock);
+}
+
void ksmbd_conn_lock(struct ksmbd_conn *conn)
{
mutex_lock(&conn->srv_mutex);
@@ -665,6 +685,7 @@ recheck:
}
ksmbd_conn_set_releasing(conn);
+ ksmbd_conn_cancel_async_requests(conn);
/* Wait till all reference dropped to the Server object*/
ksmbd_debug(CONN, "Wait for all pending requests(%d)\n", atomic_read(&conn->r_count));
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);