ksmbd: retain connection for pending notify work

Deferred CHANGE_NOTIFY work keeps an async message ID after the original
request work is released. A durable handle can outlive its connection, so
the connection teardown can destroy its async IDA before the handle close
releases the pending notify work.

Give the synthetic deferred work a connection reference. Release it after
the async ID in ksmbd_free_work_struct(). This keeps the async IDA alive
until the deferred work is released, even when the original connection has
already left the connection list.

During server shutdown there is no client to receive a cleanup response.
Skip the write and only release the pending work.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon 2026-07-13 10:09:27 +09:00
parent 125c471ca9
commit f495154703
3 changed files with 7 additions and 1 deletions

View File

@ -86,6 +86,8 @@ void ksmbd_free_work_struct(struct ksmbd_work *work)
if (work->async_id)
ksmbd_release_id(&work->conn->async_ida, work->async_id);
if (work->owns_conn_ref)
ksmbd_conn_put(work->conn);
kmem_cache_free(work_cache, work);
}

View File

@ -90,6 +90,8 @@ struct ksmbd_work {
bool compress_response:1;
/* Is this SYNC or ASYNC ksmbd_work */
bool asynchronous:1;
/* Work owns a reference to @conn. */
bool owns_conn_ref:1;
bool need_invalidate_rkey:1;
unsigned int remote_key;

View File

@ -10510,7 +10510,9 @@ int smb2_notify(struct ksmbd_work *work)
smb2_send_interim_resp(work, STATUS_PENDING);
in_work->conn = work->conn;
/* Keep the async IDA alive until the deferred work is released. */
in_work->conn = ksmbd_conn_get(work->conn);
in_work->owns_conn_ref = true;
in_hdr = smb_get_msg(in_work->response_buf);
memcpy(in_hdr, ksmbd_resp_buf_next(work), __SMB2_HEADER_STRUCTURE_SIZE);
in_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;