freebsd-skq/sys/cam/ctl
Alexander Motin 9a4510ac32 Implement zero-copy iSCSI target transmission/read.
Add ICL_NOCOPY flag to icl_pdu_append_data(), specifying that the method
can just reference the data buffer instead of immediately copying it.

Extend the offload KPI with optional PDU queue method, allowing to specify
completion callback, called when all the data referenced by above has been
transferred and won't be accessed any more (the buffers can be freed).

Implement the above functionality in software iSCSI driver using mbufs
with external storage and reference counter.  Note that some NICs (ixl(4))
may keep the mbuf in TX queue for a long time, so CTL has to be ready.

Add optional method to struct ctl_scsiio for buffer reference counting.
Implement it for CTL block backend, allowing to delay free of the struct
ctl_be_block_io and memory it references as needed.  In first reincarnation
of the patch I tried to delay whole I/O as it is done for FibreChannel,
that was cleaner, but due to the above callback delays I had to rewrite
it this way to not leave LUN referenced potentially for hours or more.

All together on sequential read from ZFS ARC this saves about 30% of CPU
time and memory bandwidth by avoiding one of 3 memory copies (the other
two are from ZFS ARC to DMU cache and then from DMU cache to CTL buffers).
On tests with 2x Xeon Silver 4114 this allows to reach full line rate of
100GigE NIC.  Tests with Gold CPUs and two 100GigE NICs are stil TBD,
but expectations to saturate them are pretty high. ;)

Discussed with:	Chelsio
Sponsored by:	iXsystems, Inc.
2020-06-08 20:53:57 +00:00
..
ctl_backend_block.c Implement zero-copy iSCSI target transmission/read. 2020-06-08 20:53:57 +00:00
ctl_backend_ramdisk.c Make struct ctl_be_lun first element of struct ctl_be_*_lun. 2020-05-28 21:30:29 +00:00
ctl_backend.c Cleanup LUN addition/removal. 2020-05-02 16:54:59 +00:00
ctl_backend.h Make struct ctl_be_lun first element of struct ctl_be_*_lun. 2020-05-28 21:30:29 +00:00
ctl_cmd_table.c sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_debug.h sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_error.c SPC-3 and up require some UAs to be returned as fixed. 2019-06-20 22:20:30 +00:00
ctl_error.h sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_frontend_cam_sim.c Remove unused cam ccb flags 2020-03-10 23:58:41 +00:00
ctl_frontend_ioctl.c Refactor command ordering/blocking mechanism in CTL. 2019-02-27 21:29:21 +00:00
ctl_frontend_iscsi.c Implement zero-copy iSCSI target transmission/read. 2020-06-08 20:53:57 +00:00
ctl_frontend_iscsi.h Fix iSCSI target crash on session reinstation. 2018-03-15 17:36:13 +00:00
ctl_frontend.c Rework CTL frontend & backend options to use nv(3), allow creating multiple 2018-05-10 03:50:20 +00:00
ctl_frontend.h Rework CTL frontend & backend options to use nv(3), allow creating multiple 2018-05-10 03:50:20 +00:00
ctl_ha.c Fix fallout of r319722 in CTL HA. 2020-05-26 15:08:35 +00:00
ctl_ha.h sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_io.h Implement zero-copy iSCSI target transmission/read. 2020-06-08 20:53:57 +00:00
ctl_ioctl.h Report STATUS_QUEUED/SENT in ctladm dumpooa output. 2020-05-29 13:07:52 +00:00
ctl_private.h Cleanup LUN addition/removal. 2020-05-02 16:54:59 +00:00
ctl_scsi_all.c sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_scsi_all.h sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_ser_table.c sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl_tpc_local.c SPDX: finish tagging sys/cam. 2018-01-16 23:19:57 +00:00
ctl_tpc.c Rework CTL frontend & backend options to use nv(3), allow creating multiple 2018-05-10 03:50:20 +00:00
ctl_tpc.h SPDX: finish tagging sys/cam. 2018-01-16 23:19:57 +00:00
ctl_util.c Properly check kern_sg_entries for S/G list. 2020-05-26 19:09:19 +00:00
ctl_util.h sys/cam: further adoption of SPDX licensing ID tags. 2017-11-27 15:12:43 +00:00
ctl.c Report STATUS_QUEUED/SENT in ctladm dumpooa output. 2020-05-29 13:07:52 +00:00
ctl.h Add device temperature reporting into CTL. 2019-07-26 03:49:16 +00:00
README.ctl.txt
scsi_ctl.c Return a C errno for cam_periph_acquire(). 2018-02-06 06:42:25 +00:00

/* $FreeBSD$ */

CTL - CAM Target Layer Description

Revision 1.4 (December 29th, 2011)
Ken Merry <ken@FreeBSD.org>

Table of Contents:
=================

Introduction
Features
Configuring and Running CTL
Revision 1.N Changes
To Do List
Code Roadmap
Userland Commands

Introduction:
============

CTL is a disk, processor and cdrom device emulation subsystem originally
written for Copan Systems under Linux starting in 2003.  It has been
shipping in Copan (now SGI) products since 2005.

It was ported to FreeBSD in 2008, and thanks to an agreement between SGI
(who acquired Copan's assets in 2010) and Spectra Logic in 2010, CTL is
available under a BSD-style license.  The intent behind the agreement was
that Spectra would work to get CTL into the FreeBSD tree.

Features:
========

 - Disk, processor and cdrom device emulation.
 - Tagged queueing
 - SCSI task attribute support (ordered, head of queue, simple tags)
 - SCSI implicit command ordering support.  (e.g. if a read follows a mode
   select, the read will be blocked until the mode select completes.)
 - Full task management support (abort, LUN reset, target reset, etc.)
 - Support for multiple ports
 - Support for multiple simultaneous initiators
 - Support for multiple simultaneous backing stores
 - Support for VMWare VAAI: COMPARE AND WRITE, XCOPY, WRITE SAME and
   UNMAP commands
 - Support for Microsoft ODX: POPULATE TOKEN/WRITE USING TOKEN, WRITE SAME
   and UNMAP commands
 - Persistent reservation support
 - Mode sense/select support
 - Error injection support
 - High Availability clustering support with ALUA
 - All I/O handled in-kernel, no userland context switch overhead.

Configuring and Running CTL:
===========================

 - Add 'device ctl' to your kernel configuration file or load the module.

 - If you're running with a 8Gb or 4Gb Qlogic FC board, add
   'options ISP_TARGET_MODE' to your kernel config file. 'device ispfw' or
   loading the ispfw module is also recommended.

 - Rebuild and install a new kernel.

 - Reboot with the new kernel.

 - To add a LUN with the RAM disk backend:

	ctladm create -b ramdisk -s 10485760000000000000
	ctladm port -o on

 - You should now see the CTL disk LUN through camcontrol devlist:

scbus6 on ctl2cam0 bus 0:
<FREEBSD CTLDISK 0001>             at scbus6 target 1 lun 0 (da24,pass32)
<>                                 at scbus6 target -1 lun -1 ()

   This is visible through the CTL CAM SIM.  This allows using CTL without
   any physical hardware.  You should be able to issue any normal SCSI
   commands to the device via the pass(4)/da(4) devices.

   If any target-capable HBAs are in the system (e.g. isp(4)), and have
   target mode enabled, you should now also be able to see the CTL LUNs via
   that target interface.

   Note that all CTL LUNs are presented to all frontends.  There is no
   LUN masking, or separate, per-port configuration.

 - Note that the ramdisk backend is a "fake" ramdisk.  That is, it is
   backed by a small amount of RAM that is used for all I/O requests.  This
   is useful for performance testing, but not for any data integrity tests.

 - To add a LUN with the block/file backend:

	truncate -s +1T myfile
	ctladm create -b block -o file=myfile
	ctladm port -o on

 - You can also see a list of LUNs and their backends like this:

# ctladm devlist
LUN Backend       Size (Blocks)   BS Serial Number    Device ID       
  0 block            2147483648  512 MYSERIAL   0     MYDEVID   0     
  1 block            2147483648  512 MYSERIAL   1     MYDEVID   1     
  2 block            2147483648  512 MYSERIAL   2     MYDEVID   2     
  3 block            2147483648  512 MYSERIAL   3     MYDEVID   3     
  4 block            2147483648  512 MYSERIAL   4     MYDEVID   4     
  5 block            2147483648  512 MYSERIAL   5     MYDEVID   5     
  6 block            2147483648  512 MYSERIAL   6     MYDEVID   6     
  7 block            2147483648  512 MYSERIAL   7     MYDEVID   7     
  8 block            2147483648  512 MYSERIAL   8     MYDEVID   8     
  9 block            2147483648  512 MYSERIAL   9     MYDEVID   9     
 10 block            2147483648  512 MYSERIAL  10     MYDEVID  10     
 11 block            2147483648  512 MYSERIAL  11     MYDEVID  11    

 - You can see the LUN type and backing store for block/file backend LUNs
   like this:

# ctladm devlist -v
LUN Backend       Size (Blocks)   BS Serial Number    Device ID       
  0 block            2147483648  512 MYSERIAL   0     MYDEVID   0     
      lun_type=0
      num_threads=14
      file=testdisk0
  1 block            2147483648  512 MYSERIAL   1     MYDEVID   1     
      lun_type=0
      num_threads=14
      file=testdisk1
  2 block            2147483648  512 MYSERIAL   2     MYDEVID   2     
      lun_type=0
      num_threads=14
      file=testdisk2
  3 block            2147483648  512 MYSERIAL   3     MYDEVID   3     
      lun_type=0
      num_threads=14
      file=testdisk3
  4 block            2147483648  512 MYSERIAL   4     MYDEVID   4     
      lun_type=0
      num_threads=14
      file=testdisk4
  5 block            2147483648  512 MYSERIAL   5     MYDEVID   5     
      lun_type=0
      num_threads=14
      file=testdisk5
  6 block            2147483648  512 MYSERIAL   6     MYDEVID   6     
      lun_type=0
      num_threads=14
      file=testdisk6
  7 block            2147483648  512 MYSERIAL   7     MYDEVID   7     
      lun_type=0
      num_threads=14
      file=testdisk7
  8 block            2147483648  512 MYSERIAL   8     MYDEVID   8     
      lun_type=0
      num_threads=14
      file=testdisk8
  9 block            2147483648  512 MYSERIAL   9     MYDEVID   9     
      lun_type=0
      num_threads=14
      file=testdisk9
 10 ramdisk                   0    0 MYSERIAL   0     MYDEVID   0     
      lun_type=3
 11 ramdisk     204800000000000  512 MYSERIAL   1     MYDEVID   1     
      lun_type=0


Revision 1.4 Changes
====================
 - Added in the second HA mode (where CTL does the data transfers instead
   of having data transfers done below CTL), and abstracted out the Copan
   HA API.

 - Fixed the phantom device problem in the CTL CAM SIM and improved the
   CAM SIM to automatically trigger a rescan when the port is enabled and
   disabled.
 
 - Made the number of threads in the block backend configurable via sysctl,
   loader tunable and the ctladm command line.  (You can now specify
   -o num_threads=4 when creating a LUN with ctladm create.)

 - Fixed some LUN selection issues in ctlstat(8) and allowed for selection
   of LUN numbers up to 1023.

 - General cleanup.

 - This version intended for public release.

Revision 1.3 Changes
====================
 - Added descriptor sense support to CTL.  It can be enabled through the
   control mode page (10), but is disabled by default.

 - Improved error injection support.  The number of errors that can be
   injected with 'ctladm inject' has been increased, and any arbitrary
   sense data may now be injected as well.

 - The port infrastructure has been revamped.  Individual ports and types
   of ports may now be enabled and disabled from the command line.  ctladm
   now has the ability to set the WWNN and WWPN for each port.

 - The block backend can now send multiple I/Os to backing files.  Multiple
   writes are only allowed for ZFS, but multiple readers are allowed for
   any filesystem.

 - The block and ramdisk backends now support setting the LUN blocksize.
   There are some restrictions when the backing device is a block device,
   but otherwise the blocksize may be set to anything.

Revision 1.2 Changes
====================

 - CTL initialization process has been revamped.  Instead of using an
   ad-hoc method, it is now sequenced through SYSINIT() calls.

 - A block/file backend has been added.  This allows using arbitrary files
   or block devices as a backing store.

 - The userland LUN configuration interface has been completely rewritten.
   Configuration is now done out of band.

 - The ctladm(8) command line interface has been revamped, and is now
   similar to camcontrol(8).

To Do List:
==========

 - Use devstat(9) for CTL's statistics collection.  CTL uses a home-grown
   statistics collection system that is similar to devstat(9).  ctlstat
   should be retired in favor of iostat, etc., once aggregation modes are
   available in iostat to match the behavior of ctlstat -t and dump modes
   are available to match the behavior of ctlstat -d/ctlstat -J.

 - ZFS ARC backend for CTL.  Since ZFS copies all I/O into the ARC
   (Adaptive Replacement Cache), running the block/file backend on top of a
   ZFS-backed zdev or file will involve an extra set of copies.  The
   optimal solution for backing targets served by CTL with ZFS would be to
   allocate buffers out of the ARC directly, and DMA to/from them directly.
   That would eliminate an extra data buffer allocation and copy.

 - Switch CTL over to using CAM CCBs instead of its own union ctl_io.  This
   will likely require a significant amount of work, but will eliminate
   another data structure in the stack, more memory allocations, etc.  This
   will also require changes to the CAM CCB structure to support CTL.

Code Roadmap:
============

CTL has the concept of pluggable frontend ports and backends.  All
frontends and backends can be active at the same time.  You can have a
ramdisk-backed LUN present along side a file backed LUN.

ctl.c:
-----

This is the core of CTL, where all of the command handlers and a lot of
other things live.  Yes, it is large.  It started off small and grew to its
current size over time.  Perhaps it can be split into more files at some
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
			in.

ctl_queue_sense()	This is only used for non-packetized SCSI.  i.e.
			parallel SCSI prior to U320 and perhaps U160.

ctl_work_thread() 	This is the primary work thread, and everything gets
			executed from there.

ctl_scsiio_precheck() 	This where all of the initial checks are done, and I/O
			is either queued for execution or blocked.

ctl_scsiio() 		This is where the command handler is actually
			executed.  (See ctl_cmd_table.c for the mapping of
			SCSI opcode to command handler function.)

ctl_done()		This is the routine called (or ctl_done_lock()) to
			initiate the command completion process.

ctl_process_done()	This is where command completion actually happens.

ctl.h:
-----

Basic function declarations and data structures.

ctl_backend.c,
ctl_backend.h:
-------------

These files define the basic CTL backend API.  The comments in the header
explain the API.

ctl_backend_block.c
-------------------

The block and file backend.  This allows for using a disk or a file as the
backing store for a LUN.  Multiple threads are started to do I/O to the
backing device, primarily because the VFS API requires that to get any
concurrency.

ctl_backend_ramdisk.c:
---------------------

A "fake" ramdisk backend.  It only allocates a small amount of memory to
act as a source and sink for reads and writes from an initiator.  Therefore
it cannot be used for any real data, but it can be used to test for
throughput.  It can also be used to test initiators' support for extremely
large LUNs.

ctl_cmd_table.c:
---------------

This is a table with all 256 possible SCSI opcodes, and command handler
functions defined for supported opcodes.  It is included in ctl.c.

ctl_debug.h:
-----------

Simplistic debugging support.

ctl_error.c,
ctl_error.h:
-----------

CTL-specific wrappers around the CAM sense building functions.

ctl_frontend.c,
ctl_frontend.h:
--------------

These files define the basic CTL frontend port API.  The comments in the
header explain the API.

ctl_frontend_cam_sim.c:
----------------------

This is a CTL frontend port that is also a CAM SIM.  The idea is that this
frontend allows for using CTL without any target-capable hardware.  So any
LUNs you create in CTL are visible via this port.

ctl_ha.c:
ctl_ha.h:
--------

This is a High Availability API and TCP-based interlink implementation.

ctl_io.h:
--------

This defines most of the core CTL I/O structures.  union ctl_io is
conceptually very similar to CAM's union ccb.  

ctl_ioctl.h:
-----------

This defines all ioctls available through the CTL character device, and
the data structures needed for those ioctls.

ctl_private.h:
-------------

Private data structres (e.g. CTL softc) and function prototypes.  This also
includes the SCSI vendor and product names used by CTL.

ctl_scsi_all.c
ctl_scsi_all.h:
--------------

CTL wrappers around CAM sense printing functions.

ctl_ser_table.c:
---------------

Command serialization table.  This defines what happens when one type of
command is followed by another type of command.  e.g., what do you do when
you have a mode select followed by a write?  You block the write until the
mode select is complete.  That is defined in this table.

ctl_util.c
ctl_util.h:
----------

CTL utility functions, primarily designed to be used from userland.  See
ctladm for the primary consumer of these functions.  These include CDB
building functions.

scsi_ctl.c:
----------

CAM target peripheral driver and CTL frontend port.  This is the path into
CTL for commands from target-capable hardware/SIMs.

Userland Commands:
=================

ctladm(8) fills a role similar to camcontrol(8).  It allow configuring LUNs,
issuing commands, injecting errors and various other control functions.

ctlstat(8) fills a role similar to iostat(8).  It reports I/O statistics
for CTL.