nvme_fc: Add ls aborts on remote port teardown
authorJames Smart <jsmart2021@gmail.com>
Tue, 11 Apr 2017 18:35:09 +0000 (11:35 -0700)
committerChristoph Hellwig <hch@lst.de>
Fri, 21 Apr 2017 14:41:53 +0000 (16:41 +0200)
remoteport teardown never aborted the LS opertions. Add support.

Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
drivers/nvme/host/fc.c

index a0c5e5420c41b547d593d2792fcd2d03ec9c8420..596b3a453b545173b27eb4e899556b2e7aaef915 100644 (file)
@@ -61,12 +61,19 @@ struct nvme_fc_queue {
        unsigned long           flags;
 } __aligned(sizeof(u64));      /* alignment for other things alloc'd with */
 
+enum nvme_fcop_flags {
+       FCOP_FLAGS_TERMIO       = (1 << 0),
+       FCOP_FLAGS_RELEASED     = (1 << 1),
+       FCOP_FLAGS_COMPLETE     = (1 << 2),
+};
+
 struct nvmefc_ls_req_op {
        struct nvmefc_ls_req    ls_req;
 
        struct nvme_fc_rport    *rport;
        struct nvme_fc_queue    *queue;
        struct request          *rq;
+       u32                     flags;
 
        int                     ls_error;
        struct completion       ls_done;
@@ -491,6 +498,30 @@ nvme_fc_rport_get(struct nvme_fc_rport *rport)
        return kref_get_unless_zero(&rport->ref);
 }
 
+static int
+nvme_fc_abort_lsops(struct nvme_fc_rport *rport)
+{
+       struct nvmefc_ls_req_op *lsop;
+       unsigned long flags;
+
+restart:
+       spin_lock_irqsave(&rport->lock, flags);
+
+       list_for_each_entry(lsop, &rport->ls_req_list, lsreq_list) {
+               if (!(lsop->flags & FCOP_FLAGS_TERMIO)) {
+                       lsop->flags |= FCOP_FLAGS_TERMIO;
+                       spin_unlock_irqrestore(&rport->lock, flags);
+                       rport->lport->ops->ls_abort(&rport->lport->localport,
+                                               &rport->remoteport,
+                                               &lsop->ls_req);
+                       goto restart;
+               }
+       }
+       spin_unlock_irqrestore(&rport->lock, flags);
+
+       return 0;
+}
+
 /**
  * nvme_fc_unregister_remoteport - transport entry point called by an
  *                              LLDD to deregister/remove a previously
@@ -526,6 +557,8 @@ nvme_fc_unregister_remoteport(struct nvme_fc_remote_port *portptr)
 
        spin_unlock_irqrestore(&rport->lock, flags);
 
+       nvme_fc_abort_lsops(rport);
+
        nvme_fc_rport_put(rport);
        return 0;
 }