[PATCH v3 18/18] nvme-fc: do not reference lsrsp after failure

Daniel Wagner posted 18 patches 9 months ago
There is a newer version of this series
[PATCH v3 18/18] nvme-fc: do not reference lsrsp after failure
Posted by Daniel Wagner 9 months ago
The lsrsp object is maintained by the LLDD. The lifetime of the lsrsp
object is implicit. Because there is no explicit cleanup/free call into
the LLDD, it is not safe to assume after xml_rsp_fails, that the lsrsp
is still valid. The LLDD could have freed the object already.

With the recent changes how fcloop tracks the resources, this is the
case. Thus don't access lsrsp after xml_rsp_fails.

Signed-off-by: Daniel Wagner <wagi@kernel.org>
---
 drivers/nvme/host/fc.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index b9929a5a7f4e3f3a03953379aceb90f0c1a0b561..2c32ba9ee688d7a683bbbf8fc57a5f9b32b2ab8d 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1410,9 +1410,8 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
 }
 
 static void
-nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
+nvme_fc_xmt_ls_rsp_free(struct nvmefc_ls_rcv_op *lsop)
 {
-	struct nvmefc_ls_rcv_op *lsop = lsrsp->nvme_fc_private;
 	struct nvme_fc_rport *rport = lsop->rport;
 	struct nvme_fc_lport *lport = rport->lport;
 	unsigned long flags;
@@ -1433,6 +1432,14 @@ nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
 	nvme_fc_rport_put(rport);
 }
 
+static void
+nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
+{
+	struct nvmefc_ls_rcv_op *lsop = lsrsp->nvme_fc_private;
+
+	nvme_fc_xmt_ls_rsp_free(lsop);
+}
+
 static void
 nvme_fc_xmt_ls_rsp(struct nvmefc_ls_rcv_op *lsop)
 {
@@ -1450,7 +1457,7 @@ nvme_fc_xmt_ls_rsp(struct nvmefc_ls_rcv_op *lsop)
 		dev_warn(lport->dev,
 			"LLDD rejected LS RSP xmt: LS %d status %d\n",
 			w0->ls_cmd, ret);
-		nvme_fc_xmt_ls_rsp_done(lsop->lsrsp);
+		nvme_fc_xmt_ls_rsp_free(lsop);
 		return;
 	}
 }

-- 
2.48.1
Re: [PATCH v3 18/18] nvme-fc: do not reference lsrsp after failure
Posted by Hannes Reinecke 9 months ago
On 3/18/25 11:40, Daniel Wagner wrote:
> The lsrsp object is maintained by the LLDD. The lifetime of the lsrsp
> object is implicit. Because there is no explicit cleanup/free call into
> the LLDD, it is not safe to assume after xml_rsp_fails, that the lsrsp
> is still valid. The LLDD could have freed the object already.
> 
> With the recent changes how fcloop tracks the resources, this is the
> case. Thus don't access lsrsp after xml_rsp_fails.
> 
> Signed-off-by: Daniel Wagner <wagi@kernel.org>
> ---
>   drivers/nvme/host/fc.c | 13 ++++++++++---
>   1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
> index b9929a5a7f4e3f3a03953379aceb90f0c1a0b561..2c32ba9ee688d7a683bbbf8fc57a5f9b32b2ab8d 100644
> --- a/drivers/nvme/host/fc.c
> +++ b/drivers/nvme/host/fc.c
> @@ -1410,9 +1410,8 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
>   }
>   
>   static void
> -nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
> +nvme_fc_xmt_ls_rsp_free(struct nvmefc_ls_rcv_op *lsop)
>   {
> -	struct nvmefc_ls_rcv_op *lsop = lsrsp->nvme_fc_private;
>   	struct nvme_fc_rport *rport = lsop->rport;
>   	struct nvme_fc_lport *lport = rport->lport;
>   	unsigned long flags;
> @@ -1433,6 +1432,14 @@ nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
>   	nvme_fc_rport_put(rport);
>   }
>   
> +static void
> +nvme_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
> +{
> +	struct nvmefc_ls_rcv_op *lsop = lsrsp->nvme_fc_private;
> +
> +	nvme_fc_xmt_ls_rsp_free(lsop);
> +}
> +
>   static void
>   nvme_fc_xmt_ls_rsp(struct nvmefc_ls_rcv_op *lsop)
>   {
> @@ -1450,7 +1457,7 @@ nvme_fc_xmt_ls_rsp(struct nvmefc_ls_rcv_op *lsop)
>   		dev_warn(lport->dev,
>   			"LLDD rejected LS RSP xmt: LS %d status %d\n",
>   			w0->ls_cmd, ret);
> -		nvme_fc_xmt_ls_rsp_done(lsop->lsrsp);
> +		nvme_fc_xmt_ls_rsp_free(lsop);
>   		return;
>   	}
>   }
> 
Hmm. That is a weird change. 'lsop->lsrsp' clearly _was_ valid just before:

         ret = lport->ops->xmt_ls_rsp(&lport->localport, &rport->remoteport,
                                      lsop->lsrsp);
         if (ret) {
                 dev_warn(lport->dev,
                         "LLDD rejected LS RSP xmt: LS %d status %d\n",
                         w0->ls_cmd, ret);
                 nvme_fc_xmt_ls_rsp_done(lsop->lsrsp);
                 return;
         }

so ->xmt_ls_rsp() would have invalidated one of the arguments.
Plus 'nvme_fc_xmt_ls_rsp_done()' is now a wrapper around
'nvme_fc_xmt_ls_rsp_free()'.
So why not go the full length and kill nvme_fc_xmt_ls_rsp_done()
completely?
Hmm?

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
Re: [PATCH v3 18/18] nvme-fc: do not reference lsrsp after failure
Posted by Daniel Wagner 9 months ago
On Tue, Mar 18, 2025 at 12:33:22PM +0100, Hannes Reinecke wrote:
>         ret = lport->ops->xmt_ls_rsp(&lport->localport, &rport->remoteport,
>                                      lsop->lsrsp);
>         if (ret) {
>                 dev_warn(lport->dev,
>                         "LLDD rejected LS RSP xmt: LS %d status %d\n",
>                         w0->ls_cmd, ret);
>                 nvme_fc_xmt_ls_rsp_done(lsop->lsrsp);
>                 return;
>         }
> 
> so ->xmt_ls_rsp() would have invalidated one of the arguments.
> Plus 'nvme_fc_xmt_ls_rsp_done()' is now a wrapper around
> 'nvme_fc_xmt_ls_rsp_free()'.
> So why not go the full length and kill nvme_fc_xmt_ls_rsp_done()
> completely?

nvme_fc_xmt_ls_rsp_done will be called when the LS has been processed.
We still need it.

> Hmm?

It is very confusing with all these callbacks and the name scheme.