Author: mav
Date: Wed May  2 20:13:03 2018
New Revision: 333180
URL: https://svnweb.freebsd.org/changeset/base/333180

Log:
  Fix LOR between controller and queue locks.
  
  Admin pass-through requests took controller lock before the queue lock,
  but in case of request submission to a failed controller controller lock
  was taken after the queue lock.  Fix that by reducing the lock scopes and
  switching to mtx_pool locks to track pass-through request completion.
  
  Sponsored by: iXsystems, Inc.

Modified:
  head/sys/dev/nvme/nvme_ctrlr.c

Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c      Wed May  2 20:10:27 2018        
(r333179)
+++ head/sys/dev/nvme/nvme_ctrlr.c      Wed May  2 20:13:03 2018        
(r333180)
@@ -233,11 +233,12 @@ nvme_ctrlr_fail_req_task(void *arg, int pending)
        struct nvme_request     *req;
 
        mtx_lock(&ctrlr->lock);
-       while (!STAILQ_EMPTY(&ctrlr->fail_req)) {
-               req = STAILQ_FIRST(&ctrlr->fail_req);
+       while ((req = STAILQ_FIRST(&ctrlr->fail_req)) != NULL) {
                STAILQ_REMOVE_HEAD(&ctrlr->fail_req, stailq);
+               mtx_unlock(&ctrlr->lock);
                nvme_qpair_manual_complete_request(req->qpair, req,
                    NVME_SCT_GENERIC, NVME_SC_ABORTED_BY_REQUEST, TRUE);
+               mtx_lock(&ctrlr->lock);
        }
        mtx_unlock(&ctrlr->lock);
 }
@@ -978,6 +979,7 @@ static void
 nvme_pt_done(void *arg, const struct nvme_completion *cpl)
 {
        struct nvme_pt_command *pt = arg;
+       struct mtx *mtx = pt->driver_lock;
        uint16_t status;
 
        bzero(&pt->cpl, sizeof(pt->cpl));
@@ -987,9 +989,10 @@ nvme_pt_done(void *arg, const struct nvme_completion *
        status &= ~NVME_STATUS_P_MASK;
        pt->cpl.status = status;
 
-       mtx_lock(pt->driver_lock);
+       mtx_lock(mtx);
+       pt->driver_lock = NULL;
        wakeup(pt);
-       mtx_unlock(pt->driver_lock);
+       mtx_unlock(mtx);
 }
 
 int
@@ -1058,15 +1061,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctr
 
        req->cmd.nsid = htole32(nsid);
 
-       if (is_admin_cmd)
-               mtx = &ctrlr->lock;
-       else {
-               KASSERT((nsid-1) >= 0 && (nsid-1) < NVME_MAX_NAMESPACES,
-                   ("%s: invalid namespace ID %d\n", __func__, nsid));
-               mtx = &ctrlr->ns[nsid-1].lock;
-       }
-
-       mtx_lock(mtx);
+       mtx = mtx_pool_find(mtxpool_sleep, pt);
        pt->driver_lock = mtx;
 
        if (is_admin_cmd)
@@ -1074,10 +1069,10 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctr
        else
                nvme_ctrlr_submit_io_request(ctrlr, req);
 
-       mtx_sleep(pt, mtx, PRIBIO, "nvme_pt", 0);
+       mtx_lock(mtx);
+       while (pt->driver_lock != NULL)
+               mtx_sleep(pt, mtx, PRIBIO, "nvme_pt", 0);
        mtx_unlock(mtx);
-
-       pt->driver_lock = NULL;
 
 err:
        if (buf != NULL) {
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to