From owner-dev-commits-src-branches@freebsd.org Mon Mar 15 02:39:44 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 01EFA56B18C; Mon, 15 Mar 2021 02:39:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DzLH36gh8z3MF7; Mon, 15 Mar 2021 02:39:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D7F7286C; Mon, 15 Mar 2021 02:39:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 12F2dhbN061546; Mon, 15 Mar 2021 02:39:43 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12F2dhgh061545; Mon, 15 Mar 2021 02:39:43 GMT (envelope-from git) Date: Mon, 15 Mar 2021 02:39:43 GMT Message-Id: <202103150239.12F2dhgh061545@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alexander Motin Subject: git: 6fb753b9fa19 - stable/13 - Save context switch per I/O for iSCSI and IOCTL frontends. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mav X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 6fb753b9fa19838208d0bada1de87afe1f0dd887 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Mar 2021 02:39:44 -0000 The branch stable/13 has been updated by mav: URL: https://cgit.FreeBSD.org/src/commit/?id=6fb753b9fa19838208d0bada1de87afe1f0dd887 commit 6fb753b9fa19838208d0bada1de87afe1f0dd887 Author: Alexander Motin AuthorDate: 2021-02-19 03:07:32 +0000 Commit: Alexander Motin 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