]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nvmet-fcloop: Check remoteport port_state before calling done callback
authorJustin Tee <justintee8345@gmail.com>
Thu, 4 Dec 2025 20:26:13 +0000 (12:26 -0800)
committerKeith Busch <kbusch@kernel.org>
Thu, 26 Feb 2026 22:35:32 +0000 (14:35 -0800)
In nvme_fc_handle_ls_rqst_work, the lsrsp->done callback is only set when
remoteport->port_state is FC_OBJSTATE_ONLINE.  Otherwise, the
nvme_fc_xmt_ls_rsp's LLDD call to lport->ops->xmt_ls_rsp is expected to
fail and the nvme-fc transport layer itself will directly call
nvme_fc_xmt_ls_rsp_free instead of relying on LLDD's done callback to free
the lsrsp resources.

Update the fcloop_t2h_xmt_ls_rsp routine to check remoteport->port_state.
If online, then lsrsp->done callback will free the lsrsp.  Else, return
-ENODEV to signal the nvme-fc transport to handle freeing lsrsp.

Cc: Ewan D. Milne <emilne@redhat.com>
Tested-by: Aristeu Rozanski <aris@redhat.com>
Acked-by: Aristeu Rozanski <aris@redhat.com>
Reviewed-by: Daniel Wagner <dwagner@suse.de>
Closes: https://lore.kernel.org/linux-nvme/21255200-a271-4fa0-b099-97755c8acd4c@work/
Fixes: 10c165af35d2 ("nvmet-fcloop: call done callback even when remote port is gone")
Signed-off-by: Justin Tee <justintee8345@gmail.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/target/fcloop.c

index c30e9a3e014fb19008c9290fc0b1b1ab685d723a..38bd2db3d6bbe7b01a00cc93386f1c5aebfda736 100644 (file)
@@ -491,6 +491,7 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
        struct fcloop_rport *rport = remoteport->private;
        struct nvmet_fc_target_port *targetport = rport->targetport;
        struct fcloop_tport *tport;
+       int ret = 0;
 
        if (!targetport) {
                /*
@@ -500,12 +501,18 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
                 * We end up here from delete association exchange:
                 * nvmet_fc_xmt_disconnect_assoc sends an async request.
                 *
-                * Return success because this is what LLDDs do; silently
-                * drop the response.
+                * Return success when remoteport is still online because this
+                * is what LLDDs do and silently drop the response.  Otherwise,
+                * return with error to signal upper layer to perform the lsrsp
+                * resource cleanup.
                 */
-               lsrsp->done(lsrsp);
+               if (remoteport->port_state == FC_OBJSTATE_ONLINE)
+                       lsrsp->done(lsrsp);
+               else
+                       ret = -ENODEV;
+
                kmem_cache_free(lsreq_cache, tls_req);
-               return 0;
+               return ret;
        }
 
        memcpy(lsreq->rspaddr, lsrsp->rspbuf,