Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Jun 2018 17:09:33 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r335155 - stable/11/sys/dev/nvme
Message-ID:  <201806141709.w5EH9Xk3087721@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Jun 14 17:09:33 2018
New Revision: 335155
URL: https://svnweb.freebsd.org/changeset/base/335155

Log:
  MFC r333180: 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.

Modified:
  stable/11/sys/dev/nvme/nvme_ctrlr.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- stable/11/sys/dev/nvme/nvme_ctrlr.c	Thu Jun 14 17:08:44 2018	(r335154)
+++ stable/11/sys/dev/nvme/nvme_ctrlr.c	Thu Jun 14 17:09:33 2018	(r335155)
@@ -228,11 +228,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);
 }
@@ -933,15 +934,17 @@ static void
 nvme_pt_done(void *arg, const struct nvme_completion *cpl)
 {
 	struct nvme_pt_command *pt = arg;
+	struct mtx *mtx = pt->driver_lock;
 
 	bzero(&pt->cpl, sizeof(pt->cpl));
 	pt->cpl.cdw0 = cpl->cdw0;
 	pt->cpl.status = cpl->status;
 	pt->cpl.status.p = 0;
 
-	mtx_lock(pt->driver_lock);
+	mtx_lock(mtx);
+	pt->driver_lock = NULL;
 	wakeup(pt);
-	mtx_unlock(pt->driver_lock);
+	mtx_unlock(mtx);
 }
 
 int
@@ -1009,12 +1012,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctr
 
 	req->cmd.nsid = nsid;
 
-	if (is_admin_cmd)
-		mtx = &ctrlr->lock;
-	else
-		mtx = &ctrlr->ns[nsid-1].lock;
-
-	mtx_lock(mtx);
+	mtx = mtx_pool_find(mtxpool_sleep, pt);
 	pt->driver_lock = mtx;
 
 	if (is_admin_cmd)
@@ -1022,10 +1020,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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806141709.w5EH9Xk3087721>