Files
scst/doc/scst_pg.sgml
Vladislav Bolkhovitin 8b77aa8ad2 Minor cleanups and docs updates
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@422 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2008-06-26 16:35:10 +00:00

2280 lines
65 KiB
Plaintext

<!doctype linuxdoc system>
<article>
<title>Generic SCSI Target Middle Level for Linux</title>
<author>
<name>Vladislav Bolkhovitin</name>
</author>
<date>Version 0.9.5 2006/12/01, actual for SCST 0.9.5 and later</date>
<abstract>
This document describes SCSI target mid-level for Linux (SCST), its
architecture and drivers from the driver writer's point of view.
</abstract>
<toc>
<sect>Introduction
<p>
SCST is a SCSI target mid-level subsystem for Linux. It is designed to
provide unified, consistent interface between SCSI target drivers and
Linux kernel and simplify target drivers development as much as
possible. It has the following features:
<itemize>
<item> Very low overhead, fine-grained locks and simplest commands
processing path, which allow to reach maximum possible performance and
scalability that close to theoretical limit.
<item> Incoming requests can be processed in the caller's context or in
one of the internal SCST's tasklets, therefore no extra context switches
required.
<item> Complete SMP support.
<item> Undertakes most problems, related to execution contexts, thus
practically eliminating one of the most complicated problem in the
kernel drivers development. For example, a target driver for QLogic
22xx/23xx cards, which has all necessary features, is about 2000
lines of code long, that is at least in several times less, than the
initiator one.
<item> Performs all required pre- and post- processing of incoming
requests and all necessary error recovery functionality.
<item> Emulates necessary functionality of SCSI host adapter, because
from a remote initiator's point of view SCST acts as a SCSI host with
its own devices. Some of the emulated functions are the following:
<itemize>
<item> Generation of necessary UNIT ATTENTIONs, their storage and
delivery to all connected remote initiators (sessions).
<item> RESERVE/RELEASE functionality.
<item> CA/ACA conditions.
<item> All types of RESETs and other task management functions.
<item> REPORT LUNS command as well as SCSI address space management
in order to have consistent address space on all remote initiators,
since local SCSI devices could not know about each other to report
via REPORT LUNS command. Additionally, SCST responds with error on
all commands to non-existing devices and provides access control
(not implemented yet), so different remote initiators could see
different set of devices.
<item> Other necessary functionality (task attributes, etc.) as
specified in SAM-2, SPC-2, SAM-3, SPC-3 and other SCSI standards.
</itemize>
<item> Device handlers architecture provides extra reliability and
security via verifying all incoming requests and allows to make any
additional requests processing, which is completely independent from
target drivers, for example, data caching or device dependent
exceptional conditions treatment.
</itemize>
Interoperability between SCST and local SCSI initiators (like sd, st) is
the additional issue that SCST is going to address (it is not
implemented yet). It is necessary, because local SCSI initiators can
change the state of the device, for example RESERVE the device, or some
of its parameters and that would be done behind SCST, which could lead
to various problems. Thus, RESERVE/RELEASE commands, locally generated
UNIT ATTENTIONs, etc. should be intercepted and processed as if local
SCSI initiators act as remote SCSI initiators connected to SCST. This
feature requires some the kernel modification. Since in the current
version it is not implemented, SCST and the target drivers are able to
work with any unpatched 2.4 kernel version.
Interface between SCST and the target drivers is based on work, done by
University of New Hampshire Interoperability Labs (UNH IOL).
All described below data structures and function could be found in
<bf/scst.h/. The SCST's Internet page is
<url url="http://scst.sourceforge.net">.
<sect>Terms and Definitions
<p><bf/SCSI initiator device/
A SCSI device that originates service and task management requests to be
processed by a SCSI target device and receives device service and task
management responses from SCSI target devices.
<bf/SCSI target device/
A SCSI device that receives device service and task management requests
for processing and sends device service and task management responses
to SCSI initiator devices or drivers.
<bf/SCST session/
SCST session is the object that describes relationship between a remote
initiator and SCST via a target driver. All the commands from the remote
initiator is passed to SCST in the session. For example, for connection
oriented protocols, like iSCSI, SCST session could be mapped to the TCP
connection (as well as iSCSI session). SCST session is the close
equivalent of I_T nexus object.
<bf/Local SCSI initiator/
A SCSI initiator that is located on the same host as SCST subsystem.
Examples are sg and st drivers.
<bf/Remote SCSI initiator/
A SCSI initiator that is located on the remote host for SCST subsystem
and makes client connections to SCST via SCSI target drivers.
<bf/SCSI target driver/
A Linux hardware or logical driver that acts as a SCSI target for remote
SCSI initiators, i.e. accepts remote connections, passes incoming SCSI
requests to SCST and sends SCSI responses from SCST back to their
originators.
<bf/Device handler driver/
Also known as "device type specific driver" or "dev handler", is plugin
for SCST, which helps SCST to analyze incoming requests and determine
parameters, specific to various types of devices as well as perform some
processing. See appropriate section for details.
<sect>SCST Architecture
<p>
SCST accepts commands and passes them to SCSI mid-level at the same
way as SCSI high-level drivers (sg, sd, st) do. Figure 1 shows
interaction between SCST, its drivers and Linux SCSI subsystem.
<figure>
<eps file="fig1.png">
<img src="fig1.png">
<caption>
<newline> Interaction between SCST, its drivers and Linux SCSI subsystem.
</caption>
</figure>
<sect>Target driver registration
<p>
To work with SCST a target driver must register its template in SCST by
calling scst_register_target_template(). The template lets SCST know the
target driver's entry points. It is defined as the following:
<sect1>Structure scst_tgt_template
<p>
<verb>
struct scst_tgt_template
{
int sg_tablesize;
const char name[15];
unsigned unchecked_isa_dma:1;
unsigned use_clustering:1;
unsigned xmit_response_atomic:1;
unsigned rdy_to_xfer_atomic:1;
unsigned report_aen_atomic:1;
int (* detect) (struct scst_tgt_template *tgt_template);
int (* release)(struct scst_tgt *tgt);
int (* xmit_response)(struct scst_cmd *cmd);
int (* rdy_to_xfer)(struct scst_cmd *cmd);
void (*on_free_cmd) (struct scst_cmd *cmd);
void (* task_mgmt_fn_done)(struct scst_mgmt_cmd *mgmt_cmd);
void (* report_aen)(int mgmt_fn, const uint8_t *lun, int lun_len);
int (*proc_info) (char *buffer, char **start, off_t offset,
int length, int *eof, struct scst_tgt *tgt, int inout);
}
</verb>
Where:
<itemize>
<item><bf/sg_tablesize/ - allows checking whether scatter/gather can be
used or not and, if yes, sets the maximum supported count of
scatter/gather entries
<item><bf/name/ - the name of the template. Must be unique to identify
the template. Must be defined.
<item><bf/unchecked_isa_dma/ - true, if this target adapter uses
unchecked DMA onto an ISA bus.
<item><bf/use_clustering/ - true, if this target adapter wants to use
clustering (i.e. smaller number of segments).
<item><bf/xmit_response_atomic/, <bf/rdy_to_xfer_atomic/ - true, if the
corresponding function supports execution in the atomic (non-sleeping)
context.
<item><bf/int (* detect) (struct scst_tgt_template *tgt_template)/ - this
function is intended to detect the target adapters that are present in
the system. Each found adapter should be registered by calling
<bf/scst_register()/. The function should return a value >= 0 to signify
the number of detected target adapters. A negative value should be
returned whenever there is an error. Must be defined.
<item><bf/int (* release)(struct scst_tgt *tgt)/ - this function is
intended to free up the resources allocated to the device. The function
should return 0 to indicate successful release or a negative value if
there are some issues with the release. In the current version of SCST
the return value is ignored. Must be defined.
<item><bf/int (* xmit_response)(struct scst_cmd *cmd)/ - this
function is equivalent to the SCSI queuecommand(). The target should
transmit the response data and the status in the struct scst_cmd. See
below for details. Must be defined.
<item><bf/int (* rdy_to_xfer)(struct scst_cmd *cmd)/ - this function
informs the driver that data buffer corresponding to the said command
have now been allocated and it is OK to receive data for this command.
This function is necessary because a SCSI target does not have any
control over the commands it receives. Most lower-level protocols have a
corresponding function which informs the initiator that buffers have
been allocated e.g., XFER_RDY in Fibre Channel. After the data is
actually received the low-level driver should call <bf/scst_rx_data()/
in order to continue processing this command. Returns one of the
<bf/SCST_TGT_RES_*/ constants, described below. Pay attention to
"atomic" attribute of the command, which can be get via
<bf/scst_cmd_atomic()/: it is true if the function called in the atomic
(non-sleeping) context. Must be defined.
<item><bf/void (*on_free_cmd)(struct scst_cmd *cmd)/ - this function
called to notify the driver that the command is about to be freed.
Necessary, because for aborted commands <bf/xmit_response()/ could not be
called. Could be used on IRQ context. Must be defined.
<item><bf/void (* task_mgmt_fn_done)(struct scst_mgmt_cmd *mgmt_cmd)/ -
this function informs the driver that a received task management
function has been completed. Completion status could be get via
<bf/scst_mgmt_cmd_get_status()/. No return value expected. Must be
defined, if the target supports task management functionality.
<item><bf/int (* report_aen)(int mgmt_fn, const uint8_t *lun, int
lun_len)/ - this function is used for Asynchronous Event Notification.
It is the responsibility of the driver to notify any/all initiators
about the Asynchronous Event reported. Returns one of the
<bf/SCST_TGT_RES_*/ constants, described below. Must be defined, if
low-level protocol supports AEN. This feature is not implemented yet.
<item><bf/int (*proc_info) (char *buffer, char **start, off_t offset,
int length, int *eof, struct scst_tgt *tgt, int inout)/ - this function
can be used to export the driver's statistics and other information to
the world outside the kernel. Parameters:
<enum>
<item> <bf/buffer, start, offset, length, eof/ - have the same
meaning as for <bf/read_proc_t/ function of the kernel
<item> <bf/tgt/ - pointer to the target, for which the function
is called
<item> <bf/inout/ - read/write direction flag, 0 - for reads, other
value - for writes
</enum>
If the driver needs to create additional files in its /proc
subdirectory, it can use <bf/scst_proc_get_tgt_root()/ function to get
the root proc_dir_entry.
</itemize>
Functions <bf/xmit_response()/, <bf/rdy_to_xfer()/ are expected to be
non-blocking, i.e. return immediately and don't wait for actual data
transfer to finish. Blocking in such command could negatively impact on
overall system performance. If blocking is necessary, it is worth to
consider creating dedicated thread(s) in target driver, to which the
commands would be passed and which would perform blocking operations
instead of SCST. If the function allowed to sleep or not is defined by
"atomic" attribute of the cmd that can be get via
<bf/scst_cmd_atomic()/, which is true, if sleeping is not allowed. In
this case, if the function requires sleeping, it can return
<bf/SCST_TGT_RES_NEED_THREAD_CTX/ in order to be recalled in the thread
context, where sleeping is allowed.
Functions <bf/task_mgmt_fn_done()/ and <bf/report_aen()/ are recommended
to be non-blocking as well. Blocking there will stop all management
processing for all target drivers in the system (there is only one
management thread in the system).
Functions <bf/xmit_response()/, <bf/rdy_to_xfer()/ and <bf/report_aen()/
can return the following error codes:
<itemize>
<item><bf/SCST_TGT_RES_SUCCESS/ - success.
<item><bf/SCST_TGT_RES_QUEUE_FULL/ - internal device queue is full, retry
again later.
<item><bf/SCST_TGT_RES_NEED_THREAD_CTX/ - it is impossible to complete
requested task in atomic context. The command should be restarted in the
thread context as described above.
<item><bf/SCST_TGT_RES_FATAL_ERROR/ - fatal error, i.e. it is unable to
perform requested operation. If returned by <bf/xmit_response()/ the
command will be destroyed, if by <bf/rdy_to_xfer()/,
<bf/xmit_response()/ will be called with <bf/HARDWARE ERROR/ sense data.
</itemize>
<sect2>More about <bf/xmit_response()/
<p>
As already written above, function <bf/xmit_response()/ should transmit
the response data and the status from the cmd parameter. Either it
should transmit the data or the status is defined by bits of the value,
returned by <bf/scst_cmd_get_tgt_resp_flags()/. They are:
<itemize>
<item><bf/SCST_TSC_FLAG_DATA/ - set if there are data to be sent
<item><bf/SCST_TSC_FLAG_STATUS/ - set if the command is finished and
there is status/sense to be sent
</itemize>
If <bf/SCST_TSC_FLAG_DATA/ is set, the data contained in the buffer,
returned by <bf/scst_cmd_get_buffer()/ (pay attention to
<bf/scst_cmd_get_use_sg()/ for scatter/gather) with length, returned by
<bf/scst_cmd_get_resp_data_len()/. It is recommended to use
<bf/scst_get_buf_*()/scst_put_buf()/ family of function instead of
direct access to the data buffers, because they hide all HIGHMEM and
SG/plain buffer issues.
If <bf/SCST_TSC_FLAG_STATUS/ is set the status could be received by the
appropriate <bf/scst_cmd_get_*_status()/ functions (see below).
The sense, if any, is contained in the buffer, returned by
<bf/scst_cmd_get_sense_buffer()/, with length, returned by
<bf/scst_cmd_get_sense_buffer_len()/. SCST always works in
<bf/autosense/ mode. If a low-level SCSI driver/device doesn't support
autosense mode, SCST will issue REQUEST SENSE command, if necessary.
Thus, if CHECK CONDITION established, target driver will always see
sense in the sense buffer and isn't required to request the sense
manually.
It is possible, that <bf/SCST_TSC_FLAG_DATA/ is set, but
<bf/SCST_TSC_FLAG_STATUS/ is not set. In this case the driver should
only transmit the data, but not finish the command and transmit the
status. Function <bf/xmit_response()/ will be called again either to
transmit the status or data once more.
After the response is completely sent, the target should call
<bf/scst_tgt_cmd_done()/ function in order to allow SCST to free the
command.
Function <bf/xmit_response()/ returns one of the <bf/SCST_TGT_RES_*/
constants, described above. Pay attention to "atomic" attribute of the
cmd, which can be get via <bf/scst_cmd_atomic()/: it is true if the
function called in the atomic (non-sleeping) context.
<sect1>Target driver registration functions
<sect2>scst_register_target_template()
<p>
Function <bf/scst_register_target_template()/ is defined as the following:
<verb>
int scst_register_target_template(
struct scst_tgt_template *vtt)
</verb>
Where:
<itemize>
<item><bf/vtt/ - pointer to the target driver template
</itemize>
Returns 0 on success or appropriate error code otherwise.
<sect2>scst_register()
<p>
Function <bf/scst_register()/ is defined as the following:
<verb>
struct scst_tgt *scst_register(
struct scst_tgt_template *vtt)
</verb>
Where:
<itemize>
<item><bf/vtt/ - pointer to the target driver template
</itemize>
Returns target structure based on template vtt or NULL in case of error.
<sect>Target driver unregistration
<p>
In order to unregister itself target driver should at first call
<bf/scst_unregister()/ for all its adapters and then call
<bf/scst_unregister_target_template()/ for its template.
<sect1>scst_unregister()
<p>
Function <bf/scst_unregister()/ is defined as the following:
<verb>
void scst_unregister(
struct scst_tgt *tgt)
</verb>
Where:
<itemize>
<item><bf/tgt/ - pointer to the target driver structure
</itemize>
<sect1>scst_unregister_target_template()
<p>
Function <bf/scst_unregister_target_template()/ is defined as the following:
<verb>
void scst_unregister_target_template(
struct scst_tgt_template *vtt)
</verb>
Where:
<itemize>
<item><bf/vtt/ - pointer to the target driver template
</itemize>
<sect>SCST session registration
<p>
When target driver determines that it needs to create new SCST session
(for example, by receiving new TCP connection), it should call
<bf/scst_register_session()/, that is defined as the following:
<verb>
struct scst_session *scst_register_session(
struct scst_tgt *tgt,
int atomic,
const char *initiator_name,
void *data,
void (*result_fn) (
struct scst_session *sess,
void *data,
int result));
</verb>
Where:
<itemize>
<item><bf/tgt/ - target
<item><bf/atomic/ - true, if the function called in the atomic context
<item><bf/initiator_name/ - remote initiator's name, any NULL-terminated
string, e.g. iSCSI name, which used as the key to found appropriate
access control group. Could be NULL, then "default" group is used. The
groups are set up via /proc interface.
<item><bf/data/ - data that will be used as the second
parameter for <bf/bf/result_fn/()/ function
<item><bf/result_fn/ - pointer to the function that will be
asynchronously called when session initialization finishes. Can be NULL.
Parameters:
<itemize>
<item><bf/sess/ - session
<item><bf/data/ - target driver supplied to
<bf/scst_register_session()/ data
<item><bf/result/ - session initialization result, 0 on success or
appropriate error code otherwise
</itemize>
</itemize>
A session creation and initialization is a complex task, which requires
sleeping state, so it can't be fully done in interrupt context.
Therefore the "bottom half" of it, if <bf/scst_register_session()/ is
called from atomic context, will be done in SCST thread context. In this
case <bf/scst_register_session()/ will return not completely initialized
session, but the target driver can supply commands to this session via
<bf/scst_rx_cmd()/. Those commands processing will be delayed inside
SCST until the session initialization is finished, then their processing
will be restarted. The target driver will be notified about finish of
the session initialization by function <bf/result_fn()/. On success the
target driver could do nothing, but if the initialization fails, the
target driver must ensure that no more new commands being sent or will
be sent to SCST after <bf/result_fn()/ returns. All already sent to SCST
commands for failed session will be returned in <bf/xmit_response()/
with BUSY status. In case of failure the driver shall call
<bf/scst_unregister_session()/ inside <bf/result_fn()/, it will NOT be
called automatically. Thus, <bf/scst_register_session()/ can be called
even on IRQ context.
Session registration is illustrated on Figure 2 and Figure 3.
<figure>
<eps file="fig2.png">
<img src="fig2.png">
<caption>
<newline> Session registration when <bf/atomic/ parameter is false
</caption>
</figure>
<figure>
<eps file="fig3.png">
<img src="fig3.png">
<caption>
<newline> Session registration when <bf/atomic/ parameter is true
</caption>
</figure>
<sect>SCST session unregistration
<p>
SCST session unregistration basically is the same, except that instead of
atomic parameter there is <bf/wait/ one.
<verb>
void scst_unregister_session(
struct scst_session *sess,
int wait,
void (* unreg_done_fn)(
struct scst_session *sess))
</verb>
Where:
<itemize>
<item><bf/sess/ - session to be unregistered
<item><bf/wait/ - if true, instructs to wait until all commands, which
currently executing and belonged to the session, finished. Otherwise,
target driver should be prepared to receive <bf/xmit_response()/ for
the session after <bf/scst_unregister_session()/ returns.
<item><bf/unreg_done_fn/ - pointer to the function that will be
asynchronously called when the last session's command finishes and the
session is about to be completely freed. Can be NULL. Parameter:
<itemize>
<item><bf/sess/ - session
</itemize>
</itemize>
All outstanding commands will be finished regularly. After
<bf/scst_unregister_session()/ returned no new commands must be sent to
SCST via <bf/scst_rx_cmd()/. Also, the caller must ensure that no
<bf/scst_rx_cmd()/ or <bf/scst_rx_mgmt_fn_*()/ is called in paralell
with <bf/scst_unregister_session()/.
Function <bf/scst_unregister_session()/ can be called before
<bf/result_fn()/ of <bf/scst_register_session()/ called, i.e. during the
session registration/initialization.
<sect>The commands processing and interaction between SCST and its drivers
<p>
The commands processing by SCST started when target driver calls
<bf/scst_rx_cmd()/. This function returns SCST's command. Then the target
driver finishes the command's initialization, if necessary, for
example, storing necessary target driver specific data there, and calls
<bf/scst_cmd_init_done()/ telling SCST that it can start the processing.
Then SCST translates the command's LUN to local device, determines the
command's data direction and required data buffer size by calling
appropriate device handler's <bf/parse()/ function. Then:
<itemize>
<item>If the command required no data transfer, it will be passed to
SCSI mid-level directly or via device handler's <bf/exec()/ call.
<item>If the command is <bf/READ/ command (data to the target),
necessary space will be allocated and then the command will be passed
to SCSI mid-level directly or via device handler's <bf/exec()/ call.
<item>If the command is <bf/WRITE/ command (data from the target),
necessary space will be allocated, then the target's <bf/rdy_to_xfer()/
function will be called, telling the target that the space is ready and
it can start data transferring. When all the data are read from the
target, it will call <bf/scst_rx_data()/, and the command will be passed
to SCSI mid-level directly or via device handler's <bf/exec()/ call.
</itemize>
When the command is finished by SCSI mid-level, device handler's
<bf/dev_done()/ is called to notify it about the command's
completion. Then in order to send the response the target's
<bf/xmit_response()/ is called. When the response, including data, if
any, is transmitted, the target will call <bf/scst_tgt_cmd_done()/
telling SCST that it can free the command and its data buffer.
Then during the command's deallocation device handler's and the target's
<bf/on_free_cmd()/ will be called in this order, if set.
This sequence is illustrated on Figure 4. To simplify the picture, sign
"..." means SCST's waiting state for the corresponding command to
complete. During this state SCST and its drivers continue processing of
other commands, if there are any. One way arrow, for example to
<bf/xmit_response()/, means that after this function returns, nothing
valuable for the current command will be done and SCST goes sleeping or
to the next command processing until corresponding event happens.
<figure>
<eps file="fig4.png">
<img src="fig4.png">
<caption>
<newline> The commands processing flow
</caption>
</figure>
Additionally, before calling <bf/scst_cmd_init_done()/ the target driver can
set the following the command's flags or parameters:
<itemize>
<item> <bf/DATA_BUF_ALLOCED/ - set if the data buffer is already
allocated. The flag is set via <bf/scst_cmd_set_data_buff_alloced()/ and
get via <bf/scst_cmd_get_data_buff_alloced()/. Useful, for instance, for
iSCSI unsolicited data.
<item> Expected transfer length and direction via
<bf/scst_cmd_set_expected()/ as supplied by remote initiator, if any.
This values will be used only if the command's opcode is unknown for
SCST, for example for vendor-specific commands. If these values not set
and opcode isn't known, the command will be completed by SCST in
preprocessing phase with <bf/INVALID OPCODE/ sense.
</itemize>
<sect1>The commands processing functions
<sect2>scst_rx_cmd()
<p>
Function <bf/scst_rx_cmd()/ creates and sends new command to SCST. Returns
the command on success or NULL otherwise. It is defined as the
following:
<verb>
struct scst_cmd *scst_rx_cmd(
struct scst_session *sess,
const uint8_t *lun,
int lun_len,
const uint8_t *cdb,
int cdb_len,
int atomic)
</verb>
Where:
<itemize>
<item><bf/sess/ - SCST's session
<item><bf/lun/ - pointer to device's LUN as specified in SCSI
Architecture Model 2/3 without any byte order translation. Extended
addressing method is not supported.
<item><bf/lun_len/ - LUN's length
<item><bf/cdb/ - SCSI CDB
<item><bf/cdb_len/ - CDB's length
<item><bf/atomic/ - if true, the command will be allocated with
GFP_ATOMIC flag, otherwise GFP_KERNEL will be used
</itemize>
<sect2>scst_cmd_init_done()
<p>
Function <bf/scst_cmd_init_done()/ notifies SCST that the driver finished
its part of the command initialization, and the command is ready for
execution. It is defined as the following:
<verb>
void scst_cmd_init_done(
struct scst_cmd *cmd,
int pref_context)
</verb>
Where:
<itemize>
<item><bf/cmd/ - the command
<item><bf/pref_context/ - preferred command execution context. See
<bf/SCST_CONTEXT_*/ constants below for details.
</itemize>
<sect2>scst_rx_data()
<p>
Function <bf/scst_rx_data()/ notifies SCST that the driver received all
the necessary data and the command is ready for further processing. It
is defined as the following:
<verb>
void scst_rx_data(
struct scst_cmd *cmd,
int status,
int pref_context)
</verb>
Where:
<itemize>
<item><bf/cmd/ - the command
<item><bf/status/ - completion status, see below.
<item><bf/pref_context/ - preferred command execution context. See
<bf/SCST_CONTEXT_*/ constants below for details.
</itemize>
Parameter <bf/status/ can have one of the following values:
<itemize>
<item><bf/SCST_RX_STATUS_SUCCESS/ - success
<item><bf/SCST_RX_STATUS_ERROR/ - data receiving finished with error, so
SCST should set the sense and finish the command by calling
<bf/xmit_response()/
<item><bf/SCST_RX_STATUS_ERROR_SENSE_SET/ - data receiving finished with
error and the sense is set, so SCST should finish the command by calling
<bf/xmit_response()/
<item><bf/SCST_RX_STATUS_ERROR_FATAL/ - data receiving finished with
fatal error, so SCST should finish the command, but don't call
<bf/xmit_response()/. In this case the driver must free all associated
with the command data before calling <bf/scst_rx_data()/.
</itemize>
<sect2>scst_tgt_cmd_done()
<p>
Function <bf/scst_tgt_cmd_done()/ notifies SCST that the driver sent the
data and/or response. It must not been called if there are an error and
<bf/xmit_response()/ returned something other, than
<bf/SCST_TGT_RES_SUCCESS/. It is defined as the following:
<verb>
void scst_tgt_cmd_done(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - the command
</itemize>
<sect1>The commands processing context
<p>
Execution context often is a major problem in the kernel drivers
development, because many contexts, like IRQ one, greatly limit
available functionality, therefore require additional complex code in
order to pass processing to more simple context. SCST does its best to
undertake most of the context handling.
On the initialization time SCST creates for internal command processing
as many threads as there are processors in the system or specified by
user via <bf/scst_threads/ module parameter. Similarly, as many tasklets
created as there are processors in the system.
Each command can be processed in one of four contexts:
<enum>
<item>Directly, i.e. in the caller's context, without limitations
<item>Directly atomically, i.e. with sleeping forbidden
<item>In the SCST's internal per processor or per session thread
<item>In the SCST's per processor tasklet
</enum>
The target driver sets this context as pref_context parameter for
<bf/scst_cmd_init_done()/ and <bf/scst_rx_data()/. Additionally, target's
template's <bf/xmit_response_atomic/ and <bf/rdy_to_xfer_atomic/ flags
have direct influence on the context. If one of them is false, the
corresponding function will never be called in the atomic context and,
if necessary, the command will be rescheduled to one of the SCST's
threads.
SCST in some circumstances can change preferred context to less
restrictive one, for example, for large data buffer allocation, if
there is not enough GFP_ATOMIC memory.
<sect2>Preferred context constants
<p>
There are the following preferred context constants:
<itemize>
<item><bf/SCST_CONTEXT_DIRECT/ - sets direct command processing (i.e.
regular function calls in the current context) sleeping is allowed, no
context restrictions. Supposed to be used when calling from thread
context where no locks are held and the driver's architecture allows
sleeping without performance degradation or anything like that.
<item><bf/SCST_CONTEXT_DIRECT_ATOMIC/ - sets direct command processing
(i.e. regular function calls in the current context), sleeping is not
allowed. Supposed to be used when calling on thread context where there
are locks held, when calling on softirq context or the driver's
architecture does not allow sleeping without performance degradation or
anything like that.
<item><bf/SCST_CONTEXT_TASKLET/ - tasklet or thread context required for
the command processing. Supposed to be used when calling from IRQ
context.
<item><bf/SCST_CONTEXT_THREAD/ - thread context required for the
command processing. Supposed to be used if the driver's architecture
does not allow using any of above.
</itemize>
<sect>Task management functions
<p>
There are the following task management functions supported:
<itemize>
<item> <bf/SCST_ABORT_TASK/ - <bf/ABORT_TASK/ task management function,
aborts the specified task (command). Returns completion status via
<bf/task_mgmt_fn_done()/ when the command (task) is actually aborted.
<item> <bf/SCST_ABORT_TASK_SET/ - <bf/ABORT_TASK_SET/ task management
function, aborts all tasks (commands) on the specified device. Returns
the success via <bf/task_mgmt_fn_done()/ immediately, not waiting for
the commands being actually aborted.
<item> <bf/SCST_CLEAR_ACA/ - <bf/CLEAR_ACA/ task management function,
currently does nothing.
<item> <bf/SCST_CLEAR_TASK_SET/ - <bf/CLEAR_TASK_SET/ task management
function, the same as <bf/SCST_ABORT_TASK_SET/.
<item> <bf/SCST_LUN_RESET/ - <bf/LUN_RESET/ task management function,
implemented via <bf/scsi_reset_provider()/ call for the specified device
with <bf/SCSI_TRY_RESET_DEVICE/ parameter.
<item> <bf/SCST_TARGET_RESET/ - <bf/TARGET_RESET/ task management
function, implemented via <bf/scsi_reset_provider()/ call for all the
hosts in the system (one device per each host) with
<bf/SCSI_TRY_RESET_BUS/ parameter at first and then, if failed, with
<bf/SCSI_TRY_RESET_HOST/.
</itemize>
<sect1>scst_rx_mgmt_fn_tag()
<p>
Function <bf/scst_rx_mgmt_fn_tag()/ tells SCST to perform the specified
task management function, based on the command's tag. Can be used only
for <bf/SCST_ABORT_TASK/.
It is defined as the following:
<verb>
int scst_rx_mgmt_fn_tag(
struct scst_session *sess,
int fn,
uint32_t tag,
int atomic,
void *tgt_specific)
</verb>
Where:
<itemize>
<item> <bf/sess/ - the session, on which the command should be performed.
<item> <bf/fn/ - task management function, one of the constants above.
<item> <bf/tag/ - the command's tag.
<item> <bf/atomic/ - true, if the function called in the atomic context.
<item> <bf/tgt_specific/ - pointer to the target driver specific data,
can be retrieved in <bf/task_mgmt_fn_done()/ via
<bf/scst_mgmt_cmd_get_status()/ function.
</itemize>
Returns 0 if the command was successfully created and scheduled for
execution, error code otherwise. On success, the completion status of
the command will be reported asynchronously via <bf/task_mgmt_fn_done()/
driver's callback.
<sect1>scst_rx_mgmt_fn_lun()
<p>
Function <bf/scst_rx_mgmt_fn_lun()/ tells SCST to perform the specified
task management function, based on the LUN. Currently it can be used for
any function, except <bf/SCST_ABORT_TASK/.
It is defined as the following:
<verb>
int scst_rx_mgmt_fn_lun(
struct scst_session *sess,
int fn,
const uint8_t *lun,
int lun_len,
int atomic,
void *tgt_specific);
</verb>
Where:
<itemize>
<item> <bf/sess/ - the session, on which the command should be performed.
<item> <bf/fn/ - task management function, one of the constants above.
<item> <bf/lun/ - LUN, the format is the same as for <bf/scst_rx_cmd()/.
<item> <bf/lun_len/ - LUN's length.
<item> <bf/atomic/ - true, if the function called in the atomic context.
<item> <bf/tgt_specific/ - pointer to the target driver specific data,
can be retrieved in <bf/task_mgmt_fn_done()/ via
<bf/scst_mgmt_cmd_get_status()/ function.
</itemize>
Returns 0 if the command was successfully created and scheduled for
execution, error code otherwise. On success, the completion status of
the command will be reported asynchronously via <bf/task_mgmt_fn_done()/
driver's callback.
<sect>Device specific drivers (device handlers)
<p>
Device specific drivers are plugins for SCST, which help SCST to analyze
incoming requests and determine parameters, specific to various types
of devices. Device handlers are intended for the following:
<itemize>
<item>To get data transfer length and direction directly from CDB and
current device's configuration exactly as an end-target SCSI device
does. This serves two purposes:
<itemize>
<item> Improves security and reliability by not trusting the data
supplied by remote initiator via SCSI low-level protocol.
<item> Some low-level SCSI protocols don't provide data transfer
length and direction, so that information can be get only
directly from CDB and current device's configuration. For
example, for tape devices to get data transfer size it might be
necessary to know block size setting.
</itemize>
<item>To process some exceptional conditions, like ILI on tape devices.
<item>To initialize incoming commands with some device-specific
parameters, like timeout value.
<item>To allow some additional device-specific commands pre-, post-
processing or alternative execution, like copying data from system
cache, and do that completely independently from target drivers.
</itemize>
Device handlers performs very lightweight processing and therefore
should not considerably affect performance or CPU load. They are
considered to be part of SCST, so they could directly access any fields
in SCST's structures as well as use the corresponding functions.
Without appropriate device handler SCST hides devices of this type from
remote initiators and returns <bf/HARDWARE ERROR/ sense data to any
requests to them.
<sect1>Device specific driver registration
<sect2>scst_register_dev_driver()
<p>
To work with SCST a device specific driver must register itself in SCST by
calling <bf/scst_register_dev_driver()/. It is defined as the following:
<verb>
int scst_register_dev_driver(
struct scst_dev_type *dev_type)
</verb>
Where:
<itemize>
<item><bf/dev_type/ - device specific driver's description structure
</itemize>
The function returns 0 on success or appropriate error code otherwise.
<sect2>Structure <bf/scst_dev_type/
<p>
Structure <bf/scst_dev_type/ is defined as the following:
<verb>
struct scst_dev_type
{
char name[15];
int type;
unsigned parse_atomic:1;
unsigned exec_atomic:1;
unsigned dev_done_atomic:1;
int (*init) (struct scst_dev_type *dev_type);
void (*release) (struct scst_dev_type *dev_type);
int (*attach) (struct scst_device *dev);
void (*detach) (struct scst_device *dev);
int (*attach_tgt) (struct scst_tgt_device *tgt_dev);
void (*detach_tgt) (struct scst_tgt_device *tgt_dev);
int (*parse) (struct scst_cmd *cmd);
int (*exec) (struct scst_cmd *cmd,
void (*scst_cmd_done)(struct scsi_cmnd *cmd, int next_state));
int (*dev_done) (struct scst_cmd *cmd);
int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd,
struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd_to_abort);
int (*on_free_cmd) (struct scst_cmd *cmd);
int (*proc_info) (char *buffer, char **start, off_t offset,
int length, int *eof, struct scst_dev_type *dev_type,
int inout)
struct module *module;
}
</verb>
Where:
<itemize>
<item><bf/name/ - the name of the device handler. Must be defined and
unique
<item><bf/type/ - SCSI type of the supported device. Must be defined.
<item><bf/parse_atomic/, <bf/exec_atomic/, <bf/dev_done_atomic/ - true,
if corresponding function supports execution in the atomic
(non-sleeping) context
<item><bf/int (*init) (struct scst_dev_type *dev_type)/ - called on the
device handler load, before the first attach(). Returns 0 on success,
error code otherwise.
<item><bf/void (*release) (struct scst_dev_type *dev_type)/ - called on
the device handler unload, after final detach()
<item><bf/int (*attach) (struct scst_device *dev)/ - called when new
device is attaching to the device handler
<item><bf/void (*detach) (struct scst_device *dev)/ - called when new
device is detaching from the device handler
<item><bf/int (*attach_tgt) (struct scst_tgt_device *tgt_dev)/ - called
when new tgt_device (session) is attaching to the device handler
<item><bf/void (*detach_tgt) (struct scst_tgt_device *tgt_dev)/ - called
when tgt_device (session) is detaching from the device handler
<item><bf/int (*parse) (struct scst_cmd *cmd, const struct scst_info_cdb
*cdb_info)/ - called to parse CDB from the command. It should initialize
<bf/cmd->bufflen/ and <bf/cmd->data_direction/ (see below
<bf/SCST_DATA_*/ constants) if necessary, otherwise defaults based on
<bf/cdb_info/ will be used. Parameter <bf/cdb_info/ provides some info
about the CDB (see below). Pay attention to "atomic" attribute of the
cmd, which can be via by <bf/scst_cmd_atomic()/: it is true if the
function called in the atomic (non-sleeping) context. Returns the
command's next state or <bf/SCST_CMD_STATE_DEFAULT/, if the next default
state should be used, or <bf/SCST_CMD_STATE_NEED_THREAD_CTX/ if the
function called in atomic context, but requires sleeping. In the last
case, the function will be recalled in the thread context, where
sleeping is allowed. Additionally, <bf/SCST_CMD_DATA_BUF_ALLOCED/ flag
can be set by <bf/parse()/ (see above). Must be defined.
<item><bf/int (*exec) (struct scst_cmd *cmd, void (*scst_cmd_done)( struct
scst_cmd *cmd, int next_state))/ - called to execute CDB. The result of
the CDB execution is reported via <bf/scst_cmd_done()/ callback. Pay
attention to "atomic" attribute of the command, which can be get via
<bf/scst_cmd_atomic()/: it is true if the function called in the
atomic (non-sleeping) context. For <bf/scst_cmd_done()/ parameter
<bf/next_state/ is the command's next state or
<bf/SCST_CMD_STATE_DEFAULT/, if the next default state should be used.
Using this function modules <bf/devdisk_perf/ and <bf/devtape_perf/ were
implemented. These modules in their <bf/exec()/ method skip (pretend to
execute) all READ and WRITE operations and thus allow direct link
performance measurements without overhead of actual data transferring
from/to underlying SCSI device. See also <bf/scst_is_cmd_local()/ below.
Returns:
<itemize>
<item><bf/SCST_EXEC_COMPLETED/ - the command is done, go to
other ones
<item><bf/SCST_EXEC_NEED_THREAD/ - thread context is required to
execute the command. <bf/Exec()/ will be called again in the
thread context.
<item><bf/SCST_EXEC_NOT_COMPLETED/ - the command should be sent
to SCSI mid-level.
</itemize>
<item><bf/int (*dev_done) (struct scst_cmd *cmd)/ - called to notify
device handler about the result of the command's execution and perform
some post processing. If <bf/parse()/ function is called,
<bf/dev_done()/ is guaranteed to be called as well. The command's fields
<bf/tgt_resp_flags/ and <bf/resp_data_len/ should be set by this
function, but SCST offers good defaults. Pay attention to "atomic"
attribute of the command, which can be get via
<bf/scst_cmd_atomic()/: it is true if the function called in the
atomic (non-sleeping) context. Returns the command's next state or
<bf/SCST_CMD_STATE_DEFAULT/, if the next default state should be used,
or <bf/SCST_CMD_STATE_NEED_THREAD_CTX/ if the function called in atomic
context, but requires sleeping. In the last case, the function will be
recalled in the thread context, where sleeping is allowed.
<item><bf/int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd, struct
scst_tgt_dev *tgt_dev, struct scst_cmd *cmd_to_abort)/ - called to
execute a task management command. Returns:
<itemize>
<item><bf/SCST_DEV_TM_COMPLETED_SUCCESS/ - the command is done
with success, no firther actions required
<item><bf/SCST_DEV_TM_COMPLETED_FAILED/ - the command is failed,
no firther actions required
<item><bf/SCST_DEV_TM_NOT_COMPLETED/ - regular standard actions
for the command should be done
</itemize>
<bf/NOTE/: for <bf/SCST_ABORT_TASK/ called under spinlock
<item><bf/void (*on_free_cmd) (struct scst_cmd *cmd)/ - called to notify
device handler that the command is about to be freed. Could be called on
IRQ context.
<item><bf/int (*proc_info) (char *buffer, char **start, off_t offset,
int length, int *eof, struct scst_dev_type *dev_type, int inout)/ - this
function can be used to export the handler's statistics and other
information to the world outside the kernel. Parameters:
<enum>
<item> <bf/buffer, start, offset, length, eof/ - have the same
meaning as for <bf/read_proc_t/ function of the kernel
<item> <bf/dev_type/ - pointer to the device handler, for which
the function is called
<item> <bf/inout/ - read/write direction flag, 0 - for reads, other
value - for writes
</enum>
If the driver needs to create additional files in its /proc
subdirectory, it can use <bf/scst_proc_get_dev_type_root()/ function to get
the root proc_dir_entry.
<item><bf/struct module *module/ - pointer to device handler's module
</itemize>
Structure <bf/scst_info_cdb/ is defined as the following:
<verb>
struct scst_info_cdb
{
enum scst_cdb_flags flags;
scst_data_direction direction;
unsigned int transfer_len;
unsigned short cdb_len;
const char *op_name;
}
</verb>
Where:
<itemize>
<item><bf/flags/ - CDB's flags can be (OR'ed):
<itemize>
<item><bf/SCST_TRANSFER_LEN_TYPE_FIXED/ - set if data length in
CDB set in blocks
<item><bf/SCST_SMALL_TIMEOUT/ - set if CDB requires small timeout
<item><bf/SCST_LONG_TIMEOUT/ - set if CDB requires long timeout
</itemize>
<item><bf/direction/ - one of the <bf/SCST_DATA_*/ constants (see below)
<item><bf/transfer_len/ - CDB's data length as set in CDB
<item><bf/cdb_len/ - CDB's length
<item><bf/op_name/ - the name of the command
</itemize>
Field <bf/cmd->data_direction/, set by <bf/parse()/, can have one of the
following values:
<itemize>
<item><bf/SCST_DATA_UNKNOWN/ - data flow direction is unknown
<item><bf/SCST_DATA_WRITE/ - data flow direction is <bf/WRITE/ (from
target to initiator)
<item><bf/SCST_DATA_READ/ - data flow direction is <bf/READ/ (from
initiator to target)
<item><bf/SCST_DATA_NONE/ - there is no data transfer
</itemize>
<sect1>Device specific driver unregistration
<p>
Device specific driver is unregistered by calling
<bf/scst_unregister_dev_driver()/. It is defined as the following:
<verb>
void scst_unregister_dev_driver(
struct scst_dev_type *dev_type)
</verb>
Where:
<itemize>
<item><bf/dev_type/ - device specific driver's description structure
</itemize>
<sect>SCST commands' states
<p>
There are the following states, which a SCST command passes through
during execution and which could be returned by device handler's
<bf/parse()/ and <bf/dev_done()/ (but not all states are allowed to be
returned):
<itemize>
<item><bf/SCST_CMD_STATE_INIT_WAIT/ - the command is created, but
<bf/scst_cmd_init_done()/ not called
<item><bf/SCST_CMD_STATE_INIT/ - LUN translation (i.e. <bf/cmd->tgt_dev/
assignment) state
<item><bf/SCST_CMD_STATE_REINIT/ - again LUN translation, used if device
handler wants to restart the command on another LUN
<item><bf/SCST_CMD_STATE_DEV_PARSE/ - device handler's <bf/parse()/ is going
to be called
<item><bf/SCST_CMD_STATE_PREPARE_SPACE/ - allocation of the command's
data buffer
<item><bf/SCST_CMD_STATE_RDY_TO_XFER/ - target driver's
<bf/rdy_to_xfer()/ is going to be called
<item><bf/SCST_CMD_STATE_DATA_WAIT/ - waiting for data from the initiator
(until <bf/scst_rx_data()/ called)
<item><bf/SCST_CMD_STATE_SEND_TO_MIDLEV/ - the command is going to be
sent to SCSI mid-level for execution
<item><bf/SCST_CMD_STATE_EXECUTING/ - waiting for the command's execution
finish
<item><bf/SCST_CMD_STATE_DEV_DONE/ - device handler's <bf/dev_done()/ is
going to be called
<item><bf/SCST_CMD_STATE_XMIT_RESP/ - target driver's
<bf/xmit_response()/ is going to be called
<item><bf/SCST_CMD_STATE_XMIT_WAIT/ - waiting for data/response's
transmission finish (until <bf/scst_tgt_cmd_done()/ called)
<item><bf/SCST_CMD_STATE_FINISHED/ - the command finished and going to be
freed
</itemize>
<sect>SCST's structures manipulation functions
<p>
Target drivers must not directly access any fields in SCST's structures,
they must use only described below functions.
<sect1>SCST target driver manipulation functions
<sect2>scst_tgt_get_tgt_specific() and scst_tgt_set_tgt_specific()
<p>
Function <bf/scst_tgt_get_tgt_specific()/ returns pointer to the target
driver specific data, set by <bf/scst_tgt_set_tgt_specific()/. It is
defined as the following:
<verb>
void *scst_tgt_get_tgt_specific(
struct scst_tgt *tgt)
</verb>
Function <bf/scst_tgt_set_tgt_specific()/ stores the target driver
specific data that could be retrieved later by
by<bf/scst_tgt_get_tgt_specific()/. It is defined as the following:
<verb>
void scst_tgt_set_tgt_specific(
struct scst_tgt *tgt,
void *val)
</verb>
Where:
<itemize>
<item><bf/tgt/ - pointer to the SCST target structure
<item><bf/val/ - pointer to the target driver specific data
</itemize>
<sect1>SCST session manipulation functions
<sect2>scst_sess_get_tgt_specific() and scst_sess_set_tgt_specific()
<p>
Function <bf/scst_sess_get_tgt_specific()/ returns pointer to the target
driver specific data, set by <bf/scst_sess_set_tgt_specific()/. It is
defined as the following:
<verb>
void *scst_sess_get_tgt_specific(
struct scst_session *sess)
</verb>
Function <bf/scst_sess_set_tgt_specific()/ stores the target driver
specific data that could be retrieved later by
by<bf/scst_sess_get_tgt_specific()/. It is defined as the following:
<verb>
void scst_sess_set_tgt_specific(
struct scst_session *sess,
void *val)
</verb>
Where:
<itemize>
<item><bf/sess/ - pointer to the SCST session structure
<item><bf/val/ - pointer to the target driver specific data
</itemize>
<sect1>SCST command manipulation functions
<sect2>scst_cmd_atomic()
<p>
Function <bf/scst_cmd_atomic()/ returns true if the command is
being executed in the atomic context or false otherwise. It is defined
as the following:
<verb>
int scst_cmd_atomic(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command to check
</itemize>
<sect2>scst_cmd_get_session()
<p>
Function <bf/scst_cmd_get_session()/ returns the command's session. It
is defined as the following:
<verb>
struct scst_session *scst_cmd_get_session(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_resp_data_len()
<p>
Function <bf/scst_cmd_get_resp_data_len()/ returns the command's
response data length. It is defined as the following:
<verb>
unsigned int scst_cmd_get_resp_data_len(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_tgt_resp_flags()
<p>
Function <bf/scst_cmd_get_tgt_resp_flags()/ returns the command's
response data response flags (SCST_TSC_FLAG_* constants). It is defined
as the following:
<verb>
int scst_cmd_get_tgt_resp_flags(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_buffer()
<p>
Function <bf/scst_cmd_get_buffer()/ returns the command's data buffer.
It is defined as the following:
<verb>
void *scst_cmd_get_buffer(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
It is recommended to use <bf/scst_get_buf_*()/scst_put_buf()/ family of
function instead of direct access to the data buffers, because they hide
all HIGHMEM and SG/plain buffer issues.
<sect2>scst_cmd_get_bufflen()
<p>
Function <bf/scst_cmd_get_bufflen()/ returns the command's data buffer
length. It is defined as the following:
<verb>
unsigned int scst_cmd_get_bufflen(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
It is recommended to use <bf/scst_get_buf_*()/scst_put_buf()/ family of
function instead of direct access to the data buffers, because they hide
all HIGHMEM and SG/plain buffer issues.
<sect2>scst_cmd_get_use_sg()
<p>
Function <bf/scst_cmd_get_use_sg()/ returns the command's <bf/use_sg/
value. Its meaning is the same as for <bf/scsi_cmnd/. The function is
defined as the following:
<verb>
unsigned short scst_cmd_get_use_sg(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
It is recommended to use <bf/scst_get_buf_*()/scst_put_buf()/ family of
function instead of direct access to the data buffers, because they hide
all HIGHMEM and SG/plain buffer issues.
<sect2>scst_cmd_get_data_direction()
<p>
Function <bf/scst_cmd_get_data_direction()/ returns the command's data
direction (SCST_DATA_* constants). It is defined as the following:
<verb>
scst_data_direction scst_cmd_get_data_direction(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_status()
<p>
Functions <bf/scst_cmd_get_status()/ returns the status byte from
host device. It is defined as the following:
<verb>
uint8_t scst_cmd_get_status(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_masked_status()
<p>
Functions <bf/scst_cmd_get_masked_status()/ returns the status byte set
from host device by status_byte(). It is defined as the following:
<verb>
uint8_t scst_cmd_get_masked_status(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_msg_status()
<p>
Functions <bf/scst_cmd_get_msg_status()/ returns the status from host
adapter itself. It is defined as the following:
<verb>
uint8_t scst_cmd_get_msg_status(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_host_status()
<p>
Functions <bf/scst_cmd_get_host_status()/ returns the status set by
low-level driver to indicate its status. It is defined as the following:
<verb>
uint16_t scst_cmd_get_host_status(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_driver_status()
<p>
Functions <bf/scst_cmd_get_driver_status()/ returns the status set by
SCSI mid-level. It is defined as the following:
<verb>
uint16_t scst_cmd_get_driver_status(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_sense_buffer()
<p>
Functions <bf/scst_cmd_get_sense_buffer()/ returns pointer to the sense
buffer. It is defined as the following:
<verb>
uint8_t *scst_cmd_get_sense_buffer(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_sense_buffer_len()
<p>
Functions <bf/scst_cmd_get_sense_buffer_len()/ returns the sense buffer
length. It is defined as the following:
<verb>
int scst_cmd_get_sense_buffer_len(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_get_tag() and scst_cmd_set_tag()
<p> Function <bf/scst_cmd_get_tag()/ returns the command's tag, set by
<bf/scst_cmd_set_tag()/. It is defined as the following:
<verb>
uint32_t scst_cmd_get_tag(
struct scst_cmd *cmd)
</verb>
Function <bf/scst_cmd_set_tag()/ sets command's tag that could be
retrieved later by <bf/scst_cmd_get_tag()/. It is defined as the
following:
<verb>
void scst_cmd_set_tag(
struct scst_cmd *cmd,
uint32_t tag)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/tag/ - the tag
</itemize>
<sect2>scst_cmd_get_tgt_specific() and scst_cmd_get_tgt_specific_lock()
<p>
Functions <bf/scst_cmd_get_tgt_specific()/ and
<bf/scst_cmd_get_tgt_specific_lock()/ return pointer to the target
driver specific data, set by <bf/scst_cmd_set_tgt_specific()/ or
<bf/scst_cmd_set_tgt_specific_lock()/. Both function are basically the
same, but the later one additionally takes lock, which helps to prevent
some races. See <bf/scst_find_cmd()/ below for details.
They are defined as the following:
<verb>
void *scst_cmd_get_tgt_specific(
struct scst_cmd *cmd)
</verb>
<verb>
void *scst_cmd_get_tgt_specific_lock(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_set_tgt_specific() and scst_cmd_set_tgt_specific_lock()
<p>
Functions <bf/scst_cmd_set_tgt_specific()/ and
<bf/scst_cmd_set_tgt_specific_lock()/ store the target driver specific
data, that could be retrieved later by <bf/scst_cmd_get_tgt_specific()/
or <bf/scst_cmd_get_tgt_specific_lock()/. Both function are basically
the same, but the later one additionally takes lock, which helps to
prevent some races. See <bf/scst_find_cmd()/ below for details.
They are defined as the following:
<verb>
void *scst_cmd_set_tgt_specific(
struct scst_cmd *cmd,
void *val)
</verb>
<verb>
void *scst_cmd_set_tgt_specific_lock(
struct scst_cmd *cmd,
void *val)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/val/ - pointer to the target driver specific data
</itemize>
<sect2>scst_cmd_get_data_buff_alloced() and scst_cmd_set_data_buff_alloced()
<p>
Function <bf/scst_cmd_get_data_buff_alloced()/ returns the state of the
<bf/SCST_CMD_DATA_BUF_ALLOCED/ flag. It is defined as the following:
<verb>
int scst_cmd_get_data_buff_alloced(
struct scst_cmd *cmd)
</verb>
Function <bf/scst_cmd_set_data_buff_alloced()/ tells SCST that the data
buffer is alloced by target driver or device handler by setting the
<bf/SCST_CMD_DATA_BUF_ALLOCED/ flag on. Could be useful, for instance,
for iSCSI unsolicited data. It is defined as the following:
<verb>
void scst_cmd_set_data_buff_alloced(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect2>scst_cmd_set_expected(), scst_cmd_is_expected_set(),
scst_cmd_get_expected_data_direction() and
scst_cmd_get_expected_transfer_len()
<p>
Function <bf/scst_cmd_set_expected()/ tells SCST expected data transfer
direction and its length, as supplied by remote initiator. It is defined
as the following:
<verb>
void scst_cmd_set_expected(
struct scst_cmd *cmd,
scst_data_direction expected_data_direction,
unsigned int expected_transfer_len)
</verb>
Function <bf/scst_cmd_is_expected_set()/ returns true, if the expected
values were set by target driver and false otherwise. It is defined as
the following:
<verb>
int scst_cmd_is_expected_set(
struct scst_cmd *cmd)
</verb>
Function <bf/scst_cmd_get_expected_data_direction()/ returns expected
data direction set by target driver, if any. If this value was not set,
the return value is undefined. It is defined as the following:
<verb>
scst_data_direction scst_cmd_get_expected_data_direction(
struct scst_cmd *cmd)
</verb>
Function <bf/scst_cmd_get_expected_transfer_len()/ returns expected
transfer length set by target driver, if any. If this value was not set,
the return value is undefined. It is defined as the following:
<verb>
unsigned int scst_cmd_get_expected_transfer_len(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/expected_data_direction/ - expected data direction
<item><bf/expected_transfer_len/ - expected transfer length
</itemize>
<sect2>scst_get_buf_first(), scst_get_buf_next(),
scst_put_buf() and scst_get_buf_count()
<p>
These functions are designed to simplify and unify access to the
commands data (SG vector or plain data buffer) in all possible
conditions, including HIGHMEM environment, and should be used instead of
direct access.
Function <bf/scst_get_buf_first()/ starts access to the data. It is defined
as the following:
<verb>
int scst_get_buf_first(
struct scst_cmd *cmd,
uint8_t **buf)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/buf/ - pointer, where pointer to the first data chunk will be put
</itemize>
Returns the length of the chunk of data for success, 0 for the end of
data, negative error code otherwise.
Function <bf/scst_get_buf_next()/ continues access to the data. It is defined
as the following:
<verb>
int scst_get_buf_next(
struct scst_cmd *cmd,
uint8_t **buf)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/buf/ - pointer, where pointer to the next data chunk will be put
</itemize>
Returns the length of the chunk of data for success, 0 for the end of
data, negative error code otherwise.
Function <bf/scst_put_buf()/ tells SCST that the user of the chunk of
data, returned by <bf/scst_get_buf_first()/ or <bf/scst_get_buf_next()/,
finished accessing the data. This function must be called for all chunks
of data, returned by <bf/scst_get_buf_first()/ or
<bf/scst_get_buf_next()/. It is defined as the following:
<verb>
void scst_put_buf(
struct scst_cmd *cmd,
uint8_t *buf)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
<item><bf/buf/ - pointer to the data chunk
</itemize>
Function <bf/scst_get_buf_count()/ returns the approximate higher
rounded count of data chunks that <bf/scst_get_buf_[first|next]()/ will
return. It is defined as the following:
<verb>
int scst_get_buf_count(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - pointer to the command
</itemize>
<sect1>SCST task management commands manipulation functions
<sect2>scst_mgmt_cmd_get_tgt_specific()
<p>
Function <bf/scst_mgmt_cmd_get_tgt_specific()/ returns pointer to the
target driver specific data, set on call of <bf/scst_rx_mgmt_fn_tag()/
or <bf/scst_rx_mgmt_fn_lun()/. It is defined as the following:
<verb>
void *scst_mgmt_cmd_get_tgt_specific(
struct scst_mgmt_cmd *mcmd)
</verb>
Where:
<itemize>
<item><bf/mcmd/ - pointer to the task management command
</itemize>
<sect2>scst_mgmt_cmd_get_status()
<p>
Functions <bf/scst_mgmt_cmd_get_status()/ returns task management
command's completion status. It is defined as the following:
<verb>
void *scst_mgmt_cmd_get_status(
struct scst_mgmt_cmd *mcmd)
</verb>
Where:
<itemize>
<item><bf/mcmd/ - pointer to the task management command
</itemize>
The following status values are possible:
<itemize>
<item> SCST_MGMT_STATUS_SUCCESS - the task management command completed
successfully
<item> SCST_MGMT_STATUS_FAILED - the task management command failed.
</itemize>
<sect>Miscellaneous functions
<sect1>scst_find_cmd_by_tag()
<p>
Function <bf/scst_find_cmd_by_tag()/ is designed to find SCST's command
based on the supplied tag comparing it with one that previously set by
<bf/scst_cmd_set_tag()/. This value should be set by the target driver
on the command's initialization time.
It is defined as the following:
<verb>
struct scst_cmd *scst_find_cmd_by_tag(
struct scst_session *sess,
uint32_t tag)
</verb>
Where:
<itemize>
<item><bf/sess/ - session to which the command belongs
<item><bf/tag/ - the tag
</itemize>
Returns found command or NULL otherwise.
<sect1>scst_find_cmd()
<p>
Function <bf/scst_find_cmd()/ is designed to find SCST's command. For example,
it can be used to find the command by internal serial number that was
supplied by a remote target's response.
It is defined as the following:
<verb>
struct scst_cmd *scst_find_cmd(
struct scst_session *sess,
void *data,
int (*cmp_fn)(struct scst_cmd *cmd, void *data))
</verb>
Where:
<itemize>
<item><bf/sess/ - session to which the command belongs
<item><bf/data/ - comparison data that will be passed to <bf/cmp_fn()/
as is
<item><bf/cmp_fn/ - comparison callback function that will be called for
each the session's command. Should return true if the command is found,
false otherwise. Parameters:
<itemize>
<item><bf/cmd/ - the command to compare
<item><bf/data/ - comparison data.
</itemize>
</itemize>
Returns found command or NULL otherwise.
<bf/IMPORTANT/
SCST is designed in a such way that any command is always processed only
by one thread at any time, so no locking is necessary. But there is one
exception from that rule, it is <bf/scst_find_cmd()/ function. Since it
calls the callback over all commands of the session in the internal
lists, despite of the command's current state, there is a race
possibility accessing to target specific data pointer between
<bf/scst_cmd_set_tgt_specific()/ caller and <bf/cmp_fn()/, which usually
calls <bf/scst_cmd_get_tgt_specific()/ from the different context. The
only place, where it is safe to call <bf/scst_cmd_set_tgt_specific()/
without the race probability, is between <bf/scst_rx_cmd()/ and
<bf/scst_cmd_init_done()/. Thus, if you call
<bf/scst_cmd_set_tgt_specific()/ only there, there is nothing to worry,
always use the functions without "lock" suffix. Otherwise, be careful
and, if necessary, use "lock" functions. In addition, <bf/cmp_fn()/ is
allowed to use only target specific data and forbidden to call any
SCST's functions.
<sect1>scst_get_cdb_info()
<p>
Function <bf/scst_get_cdb_info()/ provides various CDB info. It is
defined as the following:
<verb>
int scst_get_cdb_info(
const uint8_t *cdb_p,
int dev_type,
struct scst_info_cdb *info_p)
</verb>
Where:
<itemize>
<item><bf/cdb_p/ - pointer to CDB
<item><bf/dev_type/ - SCSI device type
<item><bf/info_p/ - the result structure, see description in device
handler's <bf/parse()/ chapter
</itemize>
Returns 0 on success, -1 otherwise.
<sect1>scst_to_dma_dir()
<p>
Function <bf/scst_to_dma_dir()/ translates SCST's data direction to
DMA one. It is defined as the following:
<verb>
int scst_to_dma_dir(
int scst_dir)
</verb>
Where:
<itemize>
<item><bf/scst_dir/ - one of the <bf/SCST_DATA_*/ constants
</itemize>
Returns the corresponding <bf/PCI_DMA_*/ constant.
<sect1>scst_is_cmd_local()
<p>
Function <bf/scst_is_cmd_local()/ checks if the command is handled
by SCST (i.e. locally, as, e.g., REPORT LUNS command). Intended to be
used in device handler's <bf/exec()/, when the device handler wants to
perform all the commands, except ones that should be done by SCST
itself.
It is defined as the following:
<verb>
int scst_is_cmd_local(
struct scst_cmd *cmd)
</verb>
Where:
<itemize>
<item><bf/cmd/ - the command, which CDB should be checked
</itemize>
Returns 1, if the command's CDB is locally handled by SCST or 0
otherwise
<sect1>scst_register_virtual_device() and scst_unregister_virtual_device()
<p>
These functions provide a way for device handlers to register a virtual
(emulated) device, which will be visible only by remote initiators. For
example, FILEIO device handler uses files on file system to makes from
them virtual remotely available SCSI disks.
Function <bf/scst_register_virtual_device()/ registers a virtual device.
During the registration the device handlers functions <bf/init()/ and
<bf/attach()/ will be called, if defined. The function is defined as the
following:
<verb>
int scst_register_virtual_device(
struct scst_dev_type *dev_handler)
</verb>
Where:
<itemize>
<item><bf/dev_handler/ - device handler's descriptor
</itemize>
Returns assigned to the device ID on success, or negative value otherwise.
Function <bf/scst_unregister_virtual_device()/ unregisters a virtual
device. During the unregistration the device handlers functions
<bf/detach()/ and <bf/release()/ will be called, if defined. The
function is defined as the following:
<verb>
void scst_unregister_virtual_device(
int id)
</verb>
Where:
<itemize>
<item><bf/id/ - the device's ID, returned by
<bf/scst_register_virtual_device()/
</itemize>
<sect1>scst_add_threads() and scst_del_threads()
<p>
These functions allows to add or delete some SCST threads. For example,
if <bf/exec()/ function in your device handler works synchronously, i.e.
wait for job's completition, in order to prevent performance loss you
can add for SCST as many threads as there are devices serviced by your
device handler.
Function <bf/scst_add_threads()/ starts requested number of threads. It
is defined as the following:
<verb>
int scst_add_threads(
int num)
</verb>
Where:
<itemize>
<item><bf/num/ - number of the threads to start
</itemize>
Returns 0 on success, error code otherwise.
Function <bf/scst_del_threads()/ stops requested number of threads. It
is defined as the following:
<verb>
void scst_del_threads(
int num)
</verb>
Where:
<itemize>
<item><bf/num/ - number of the threads to stop
</itemize>
<sect1>scst_proc_get_tgt_root()
<p>
Function <bf/scst_proc_get_tgt_root()/ returns target driver's root
entry in SCST's /proc hierarchy. The driver can create own
files/directories here, which should be deleted in the driver's
release(). It is defined as the following:
<verb>
struct proc_dir_entry *scst_proc_get_tgt_root(
struct scst_tgt_template *vtt)
</verb>
Where:
<itemize>
<item><bf/vtt/ - pointer to the driver's template
</itemize>
Returns proc_dir_entry on success, NULL otherwise.
<sect1>scst_proc_get_dev_type_root()
<p>
Function <bf/scst_proc_get_dev_type_root()/ returns device handler's
root entry in SCST's /proc hierarchy. The driver can create own
files/directories here, which should be deleted in the driver's
detach() or release(). It is defined as the following:
<verb>
struct proc_dir_entry *scst_proc_get_dev_type_root(
struct scst_dev_type *dtt)
</verb>
Where:
<itemize>
<item><bf/dtt/ - pointer to the handler's description structure
</itemize>
Returns proc_dir_entry on success, NULL otherwise.
</article>