Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Mar 2021 02:39:43 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 6fb753b9fa19 - stable/13 - Save context switch per I/O for iSCSI and IOCTL frontends.
Message-ID:  <202103150239.12F2dhgh061545@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=6fb753b9fa19838208d0bada1de87afe1f0dd887

commit 6fb753b9fa19838208d0bada1de87afe1f0dd887
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2021-02-19 03:07:32 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2021-03-15 02:33:10 +0000

    Save context switch per I/O for iSCSI and IOCTL frontends.
    
    Introduce new CTL core KPI ctl_run(), preprocessing I/Os in the caller
    context instead of scheduling another thread just for that.  This call
    may sleep, that is not acceptable for some frontends like the original
    CAM/FC one, but iSCSI already has separate sleepable per-connection RX
    threads, and another thread scheduling is mostly just a waste of time.
    IOCTL frontend actually waits for the I/O completion in the caller
    thread, so the use of another thread for this has even less sense.
    
    With this change I can measure ~5% IOPS improvement on 4KB iSCSI I/Os
    to ZFS.
    
    MFC after:      1 month
    
    (cherry picked from commit 812c9f48a2b7bccc31b2a6077b299822357832e4)
---
 sys/cam/ctl/README.ctl.txt       |  2 +-
 sys/cam/ctl/ctl.c                | 65 ++++++++++++++++++++++++++++++----------
 sys/cam/ctl/ctl_frontend.h       |  7 +++++
 sys/cam/ctl/ctl_frontend_ioctl.c |  2 +-
 sys/cam/ctl/ctl_frontend_iscsi.c | 12 ++++----
 sys/cam/ctl/ctl_tpc.c            |  2 +-
 6 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/sys/cam/ctl/README.ctl.txt b/sys/cam/ctl/README.ctl.txt
index 27ebe49aec56..db8666ea99db 100644
--- a/sys/cam/ctl/README.ctl.txt
+++ b/sys/cam/ctl/README.ctl.txt
@@ -258,7 +258,7 @@ point.
 Here is a roadmap of some of the primary functions in ctl.c.  Starting here
 and following the various leaf functions will show the command flow.
 
-ctl_queue() 		This is where commands from the frontend ports come
+ctl_queue() / ctl_run()	This is where commands from the frontend ports come
 			in.
 
 ctl_queue_sense()	This is only used for non-packetized SCSI.  i.e.
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index bb8fbf910857..ee36e6b01f52 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -513,8 +513,7 @@ static int ctl_scsiio_lun_check(struct ctl_lun *lun,
 				const struct ctl_cmd_entry *entry,
 				struct ctl_scsiio *ctsio);
 static void ctl_failover_lun(union ctl_io *io);
-static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc,
-			       struct ctl_scsiio *ctsio);
+static void ctl_scsiio_precheck(struct ctl_scsiio *ctsio);
 static int ctl_scsiio(struct ctl_scsiio *ctsio);
 
 static int ctl_target_reset(union ctl_io *io);
@@ -11435,14 +11434,14 @@ ctl_failover_lun(union ctl_io *rio)
 	mtx_unlock(&lun->lun_lock);
 }
 
-static int
-ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
+static void
+ctl_scsiio_precheck(struct ctl_scsiio *ctsio)
 {
+	struct ctl_softc *softc = CTL_SOFTC(ctsio);
 	struct ctl_lun *lun;
 	const struct ctl_cmd_entry *entry;
 	union ctl_io *bio;
 	uint32_t initidx, targ_lun;
-	int retval = 0;
 
 	lun = NULL;
 	targ_lun = ctsio->io_hdr.nexus.targ_mapped_lun;
@@ -11480,7 +11479,7 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 	if (entry == NULL) {
 		if (lun)
 			mtx_unlock(&lun->lun_lock);
-		return (retval);
+		return;
 	}
 
 	ctsio->io_hdr.flags &= ~CTL_FLAG_DATA_MASK;
@@ -11497,13 +11496,13 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 		if (entry->flags & CTL_CMD_FLAG_OK_ON_NO_LUN) {
 			ctsio->io_hdr.flags |= CTL_FLAG_IS_WAS_ON_RTR;
 			ctl_enqueue_rtr((union ctl_io *)ctsio);
-			return (retval);
+			return;
 		}
 
 		ctl_set_unsupported_lun(ctsio);
 		ctl_done((union ctl_io *)ctsio);
 		CTL_DEBUG_PRINT(("ctl_scsiio_precheck: bailing out due to invalid LUN\n"));
-		return (retval);
+		return;
 	} else {
 		/*
 		 * Make sure we support this particular command on this LUN.
@@ -11513,7 +11512,7 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 			mtx_unlock(&lun->lun_lock);
 			ctl_set_invalid_opcode(ctsio);
 			ctl_done((union ctl_io *)ctsio);
-			return (retval);
+			return;
 		}
 	}
 
@@ -11567,14 +11566,14 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 			ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE;
 			ctsio->sense_len = sense_len;
 			ctl_done((union ctl_io *)ctsio);
-			return (retval);
+			return;
 		}
 	}
 
 	if (ctl_scsiio_lun_check(lun, entry, ctsio) != 0) {
 		mtx_unlock(&lun->lun_lock);
 		ctl_done((union ctl_io *)ctsio);
-		return (retval);
+		return;
 	}
 
 	/*
@@ -11611,9 +11610,9 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 		    M_WAITOK)) > CTL_HA_STATUS_SUCCESS) {
 			ctl_set_busy(ctsio);
 			ctl_done((union ctl_io *)ctsio);
-			return (retval);
+			return;
 		}
-		return (retval);
+		return;
 	}
 
 	bio = (union ctl_io *)TAILQ_PREV(&ctsio->io_hdr, ctl_ooaq, ooa_links);
@@ -11623,7 +11622,7 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 		TAILQ_INSERT_TAIL(&bio->io_hdr.blocked_queue, &ctsio->io_hdr,
 				  blocked_links);
 		mtx_unlock(&lun->lun_lock);
-		return (retval);
+		break;
 	case CTL_ACTION_PASS:
 	case CTL_ACTION_SKIP:
 		ctsio->io_hdr.flags |= CTL_FLAG_IS_WAS_ON_RTR;
@@ -11649,7 +11648,6 @@ ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
 		ctl_done((union ctl_io *)ctsio);
 		break;
 	}
-	return (retval);
 }
 
 const struct ctl_cmd_entry *
@@ -13251,6 +13249,41 @@ ctl_queue(union ctl_io *io)
 	return (CTL_RETVAL_COMPLETE);
 }
 
+int
+ctl_run(union ctl_io *io)
+{
+	struct ctl_port *port = CTL_PORT(io);
+
+	CTL_DEBUG_PRINT(("ctl_run cdb[0]=%02X\n", io->scsiio.cdb[0]));
+
+#ifdef CTL_TIME_IO
+	io->io_hdr.start_time = time_uptime;
+	getbinuptime(&io->io_hdr.start_bt);
+#endif /* CTL_TIME_IO */
+
+	/* Map FE-specific LUN ID into global one. */
+	io->io_hdr.nexus.targ_mapped_lun =
+	    ctl_lun_map_from_port(port, io->io_hdr.nexus.targ_lun);
+
+	switch (io->io_hdr.io_type) {
+	case CTL_IO_SCSI:
+		if (ctl_debug & CTL_DEBUG_CDB)
+			ctl_io_print(io);
+		ctl_scsiio_precheck(&io->scsiio);
+		break;
+	case CTL_IO_TASK:
+		if (ctl_debug & CTL_DEBUG_CDB)
+			ctl_io_print(io);
+		ctl_run_task(io);
+		break;
+	default:
+		printf("ctl_run: unknown I/O type %d\n", io->io_hdr.io_type);
+		return (EINVAL);
+	}
+
+	return (CTL_RETVAL_COMPLETE);
+}
+
 #ifdef CTL_IO_DELAY
 static void
 ctl_done_timer_wakeup(void *arg)
@@ -13381,7 +13414,7 @@ ctl_work_thread(void *arg)
 			if (io->io_hdr.io_type == CTL_IO_TASK)
 				ctl_run_task(io);
 			else
-				ctl_scsiio_precheck(softc, &io->scsiio);
+				ctl_scsiio_precheck(&io->scsiio);
 			continue;
 		}
 		io = (union ctl_io *)STAILQ_FIRST(&thr->rtr_queue);
diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h
index bdcb7a2e1abd..c9ab255cdde4 100644
--- a/sys/cam/ctl/ctl_frontend.h
+++ b/sys/cam/ctl/ctl_frontend.h
@@ -310,6 +310,13 @@ void ctl_port_offline(struct ctl_port *fe);
  */
 int ctl_queue(union ctl_io *io);
 
+/*
+ * This routine starts execution of I/O and task management requests from
+ * the FETD to the CTL layer.  May sleep.  Returns 0 for success, non-zero
+ * for failure.
+ */
+int ctl_run(union ctl_io *io);
+
 /*
  * This routine is used if the front end interface doesn't support
  * autosense (e.g. non-packetized parallel SCSI).  This will queue the
diff --git a/sys/cam/ctl/ctl_frontend_ioctl.c b/sys/cam/ctl/ctl_frontend_ioctl.c
index 370e553042c5..ef5e2bd22a86 100644
--- a/sys/cam/ctl/ctl_frontend_ioctl.c
+++ b/sys/cam/ctl/ctl_frontend_ioctl.c
@@ -524,7 +524,7 @@ cfi_submit_wait(union ctl_io *io)
 	CTL_DEBUG_PRINT(("cfi_submit_wait\n"));
 
 	/* This shouldn't happen */
-	if ((retval = ctl_queue(io)) != CTL_RETVAL_COMPLETE)
+	if ((retval = ctl_run(io)) != CTL_RETVAL_COMPLETE)
 		return (retval);
 
 	done = 0;
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 8b0effcaf393..73483fb155cc 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -557,9 +557,9 @@ cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
 	io->scsiio.cdb_len = sizeof(bhssc->bhssc_cdb); /* Which is 16. */
 	memcpy(io->scsiio.cdb, bhssc->bhssc_cdb, sizeof(bhssc->bhssc_cdb));
 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
-	error = ctl_queue(io);
+	error = ctl_run(io);
 	if (error != CTL_RETVAL_COMPLETE) {
-		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
+		CFISCSI_SESSION_WARN(cs, "ctl_run() failed; error %d; "
 		    "dropping connection", error);
 		ctl_free_io(io);
 		refcount_release(&cs->cs_outstanding_ctl_pdus);
@@ -679,9 +679,9 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
 	}
 
 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
-	error = ctl_queue(io);
+	error = ctl_run(io);
 	if (error != CTL_RETVAL_COMPLETE) {
-		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
+		CFISCSI_SESSION_WARN(cs, "ctl_run() failed; error %d; "
 		    "dropping connection", error);
 		ctl_free_io(io);
 		refcount_release(&cs->cs_outstanding_ctl_pdus);
@@ -1128,9 +1128,9 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
 	io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET;
 	wait = cs->cs_outstanding_ctl_pdus;
 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
-	error = ctl_queue(io);
+	error = ctl_run(io);
 	if (error != CTL_RETVAL_COMPLETE) {
-		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
+		CFISCSI_SESSION_WARN(cs, "ctl_run() failed; error %d", error);
 		refcount_release(&cs->cs_outstanding_ctl_pdus);
 		ctl_free_io(io);
 	}
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index d63435b38762..de9e97b87a3e 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -1628,7 +1628,7 @@ tpc_done(union ctl_io *io)
 			io->io_hdr.flags &= ~CTL_FLAG_ABORT;
 			io->io_hdr.flags &= ~CTL_FLAG_SENT_2OTHER_SC;
 			if (tpcl_queue(io, tio->lun) != CTL_RETVAL_COMPLETE) {
-				printf("%s: error returned from ctl_queue()!\n",
+				printf("%s: error returned from tpcl_queue()!\n",
 				       __func__);
 				io->io_hdr.status = old_status;
 			} else



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