mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-16 18:21:27 +00:00
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@422 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2280 lines
65 KiB
Plaintext
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>
|