From 4818df5aaac04f83c7fc196384783033275c8041 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 14 Aug 2026 13:51:00 +0900 Subject: [PATCH] ksmbd: wait for deferred notify cancellation A cancelled SMB2 CHANGE_NOTIFY request is completed from system_wq. The deferred work keeps a reference to the connection, but it is not included in the connection's r_count. During connection teardown, ksmbd_conn_transport_destroy() can therefore finish the connection handler and destroy session proc entries before the deferred response runs. Account for the deferred cancellation work in r_count. The connection handler now waits for the deferred response to finish before it deregisters sessions and removes their proc entries. Signed-off-by: Namjae Jeon --- fs/smb/server/smb2pdu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 37cf1deed6d0..365439abbebe 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -11058,9 +11058,15 @@ static void smb2_notify_cancel_deferred(struct work_struct *w) { struct notify_cancel_ctx *ctx = container_of(w, struct notify_cancel_ctx, work); + struct ksmbd_conn *conn = ctx->in_work->conn; smb2_complete_notify_cancel(ctx->in_work); kfree(ctx); + /* + * The connection teardown waits for r_count before destroying + * connection sessions and their proc entries. + */ + ksmbd_conn_r_count_dec(conn); } static struct ksmbd_work *smb2_notify_cancel_claim(void **argv) @@ -11119,6 +11125,12 @@ static void smb2_notify_cancel_fn(void **argv) } ctx->in_work = in_work; INIT_WORK(&ctx->work, smb2_notify_cancel_deferred); + /* + * This deferred work can outlive the connection handler's receive loop. + * Keep teardown from destroying the connection's sessions until the + * deferred response has finished using them. + */ + ksmbd_conn_r_count_inc(conn); schedule_work(&ctx->work); }