mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 01:01:27 +00:00
These changes have been generated by running the following command: $ scripts/update-version 3 11 0 -pre
1327 lines
40 KiB
Plaintext
1327 lines
40 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
|
|
<title>
|
|
SCST user space device handler interface description
|
|
</title>
|
|
|
|
<author>
|
|
<name>Vladislav Bolkhovitin</name>
|
|
</author>
|
|
|
|
<date>Version 3.11.0-pre</date>
|
|
|
|
<toc>
|
|
|
|
<sect>Introduction
|
|
|
|
<p>
|
|
SCST user space device handler module scst_user is a device handler for
|
|
SCST, which provides a way to implement in the user space complete, full
|
|
feature virtual SCSI devices in the SCST environment.
|
|
|
|
<p>
|
|
This document assumes that the reader is familiar with the SCST
|
|
architecture and the states through which SCSI commands go during
|
|
processing in SCST. Module scst_user basically only provides hooks to
|
|
them. Their description could be found on the SCST web page on
|
|
http://scst.sf.net.
|
|
|
|
|
|
<sect> User space API
|
|
|
|
<p>
|
|
Module scst_user provides /dev/scst_user character device with the
|
|
following system calls available:
|
|
|
|
<itemize>
|
|
<item> <bf/open()/ - allows to open the device and get a file handle, which
|
|
will be used in all subsequent actions until close() is called
|
|
|
|
<item> <bf/close()/ - closes file handle returned by open()
|
|
|
|
<item> <bf/poll()/ - allows to wait until some pending command from SCST to
|
|
process is available.
|
|
|
|
<item> <bf/ioctl()/ - main call, which allows commands interchange with the SCST
|
|
core.
|
|
</itemize>
|
|
|
|
Device /dev/scst_user could be opened in blocking or non-blocking mode
|
|
using O_NONBLOCK flag. In the blocking mode ioctl()
|
|
SCST_USER_REPLY_GET_CMD function blocks until there is a new subcommand
|
|
to process. In the non-blocking mode if there are no pending subcommands
|
|
SCST_USER_REPLY_GET_CMD function returns immediately with EAGAIN error
|
|
code, and the user space device handler can use poll() call to get
|
|
notification about new subcommands arrival. The blocking mode is the
|
|
default.
|
|
|
|
The module scst_user API is defined in scst_user.h file.
|
|
|
|
<sect> IOCTL() functions
|
|
|
|
<p>
|
|
There are following IOCTL functions available. All of them has one
|
|
argument. They all, except SCST_USER_REGISTER_DEVICE return 0 for
|
|
success or -1 in case of error, and errno is set appropriately.
|
|
|
|
<sect1> SCST_USER_REGISTER_DEVICE
|
|
|
|
<p>
|
|
SCST_USER_REGISTER_DEVICE registers new virtual user space device. The
|
|
argument is:
|
|
|
|
<verb>
|
|
struct scst_user_dev_desc
|
|
{
|
|
aligned_u64 version_str;
|
|
aligned_u64 license_str;
|
|
uint8_t type;
|
|
uint8_t sgv_shared;
|
|
uint8_t sgv_disable_clustered_pool;
|
|
int32_t sgv_single_alloc_pages;
|
|
int32_t sgv_purge_interval;
|
|
uint8_t has_own_order_mgmt;
|
|
struct scst_user_opt opt;
|
|
uint32_t block_size;
|
|
char name[SCST_MAX_NAME];
|
|
char sgv_name[SCST_MAX_NAME];
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
|
|
<item> <bf/version_str/ - protocol version, shall be DEV_USER_VERSION.
|
|
|
|
<item> <bf/license_str/ - license of this module, for instance, "GPL", "GPL v2", or
|
|
"Proprietary". This field serves the same purpose as macroses
|
|
EXPORT_SYMBOL/EXPORT_SYMBOL_GPL of the Linux kernel. You can find
|
|
more info about it, if you ask at license@scst-tgt.com e-mail
|
|
address.
|
|
|
|
<item> <bf/type/ - SCSI type of the device.
|
|
|
|
<item> <bf/sgv_shared/ - true, if the SGV cache for this device should be shared with
|
|
other devices. False, if the SGV cache should be dedicated.
|
|
|
|
<item> <bf/sgv_disable_clustered_pool/ - disable usage of clustered pool for this device.
|
|
Normally, 2 independent SGV pools created and used for each device -
|
|
normal and clustered. Clustered pool creates and contains SG vectors,
|
|
in which coalesced paged merged (clustered) in single SG entries.
|
|
This is good for performance. But not all target drivers can use such
|
|
SG vectors, plus in some cases it is more convenient to have a single
|
|
memory pool. So, this option provides such possibility.
|
|
|
|
<item> <bf/sgv_single_alloc_pages/ - if 0, then the SGV cache for this device will
|
|
work in the set of power 2 size buffers mode. If >0, then the SGV
|
|
cache will work in the fixed size buffers mode. In this case it sets
|
|
the size of each buffer in pages. See the SGV cache documentation
|
|
(http://scst.sourceforge.net/sgv_cache.txt) for more details.
|
|
|
|
<item> <bf/sgv_purge_interval/ - sets the SGV cache purging interval. I.e. an SG
|
|
buffer will be freed if it's unused for time t purge_interval <= t <
|
|
2*purge_interval. If purge_interval is 0, then the default interval
|
|
will be used (60 seconds). If purge_interval <0, then the automatic
|
|
purging will be disabled. Shrinking by the system's demand will also
|
|
be disabled.
|
|
|
|
<item> <bf/has_own_order_mgmt/ - set it in non-zero, if device implements own
|
|
ORDERED commands management, i.e. guarantees commands execution order
|
|
requirements, specified by SAM.
|
|
|
|
<item> <bf/opt/ - device options, see SCST_USER_SET_OPTIONS/SCST_USER_GET_OPTIONS below
|
|
|
|
<item> <bf/block_size/ - block size, shall be divisible by 512 for block devices
|
|
|
|
<item> <bf/name/ - name of the device
|
|
|
|
<item> <bf/sgv_name/ - name of SGV cache for this device
|
|
</itemize>
|
|
|
|
SCST_USER_REGISTER_DEVICE returns registered device's handler or -1
|
|
in case of error, and errno is set appropriately.
|
|
|
|
In order to unregister the device, either call SCST_USER_UNREGISTER_DEVICE
|
|
function, or close on its file descriptor.
|
|
|
|
|
|
<sect1> SCST_USER_UNREGISTER_DEVICE
|
|
|
|
<p>
|
|
SCST_USER_UNREGISTER_DEVICE is obsolete and should not be used. Just
|
|
close the device's fd instead.
|
|
|
|
|
|
<sect1> SCST_USER_SET_OPTIONS/SCST_USER_GET_OPTIONS
|
|
|
|
<p>
|
|
SCST_USER_SET_OPTIONS/SCST_USER_GET_OPTIONS allows to set or get
|
|
correspondingly various options that control various aspects of SCSI
|
|
commands processing.
|
|
|
|
The argument is:
|
|
|
|
<verb>
|
|
struct scst_user_opt
|
|
{
|
|
uint8_t parse_type;
|
|
uint8_t on_free_cmd_type;
|
|
uint8_t memory_reuse_type;
|
|
uint8_t partial_transfers_type;
|
|
uint32_t partial_len;
|
|
|
|
uint8_t tst;
|
|
uint8_t queue_alg;
|
|
uint8_t tas;
|
|
uint8_t swp;
|
|
uint8_t d_sense;
|
|
|
|
uint8_t has_own_order_mgmt;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/parse_type/ - defines how the user space handler wants to process
|
|
PARSE subcommand. Possible values are:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_USER_PARSE_STANDARD/ - tells SCST use standard internal parser
|
|
for this SCSI device type.
|
|
|
|
<item> <bf/SCST_USER_PARSE_CALL/ - tells SCST generate SCST_USER_PARSE for all
|
|
SCSI commands
|
|
|
|
<item> <bf/SCST_USER_PARSE_EXCEPTION/ - tells SCST generate SCST_USER_PARSE
|
|
for unknown SCSI commands or SCSI commands that produce errors in
|
|
the standard parser.
|
|
</itemize>
|
|
|
|
<item> <bf/on_free_cmd_type/ - defines how the user space handler wants to
|
|
process ON_FREE_CMD subcommand. Possible values are:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_USER_ON_FREE_CMD_CALL/ - tells SCST generate
|
|
SCST_USER_ON_FREE_CMD for all SCSI commands
|
|
|
|
<item> <bf/SCST_USER_ON_FREE_CMD_IGNORE/ - tells SCST do nothing on this event.
|
|
</itemize>
|
|
|
|
<item> <bf/memory_reuse_type/ - defines how memory allocated by the user space
|
|
handler for a SCSI commands data buffers is then reused by the SCST
|
|
core as data buffer for subsequent commands. Possible values are:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_USER_MEM_NO_REUSE/ - no memory reuse is possible, for each
|
|
commands the user space handler will each time allocate a dedicated
|
|
data buffer
|
|
|
|
<item> <bf/SCST_USER_MEM_REUSE_READ/ - memory reuse by only READ-type commands
|
|
(i.e. which involve data transfer from target to initiator) is
|
|
allowed. For all WRITE-type commands (i.e. which involves data
|
|
transfer from initiator to target) the user space handler will
|
|
each time allocate a dedicated data buffer
|
|
|
|
<item> <bf/SCST_USER_MEM_REUSE_WRITE/ - memory reuse by only WRITE-type
|
|
commands is allowed. For all READ-type commands the user space
|
|
handler will each time allocate a dedicated data buffer
|
|
|
|
<item> <bf/SCST_USER_MEM_REUSE_ALL/ - unlimited memory reuse is possible.
|
|
</itemize>
|
|
|
|
<item> <bf/partial_transfers_type/ - defines if the user space handler supports
|
|
partial data transfers, when a SCSI command, which required big data
|
|
transfer, is broken on several subcommands with smaller data
|
|
transfers. This allows to improve performance by simultaneous data
|
|
transfers from/to remote initiator and to/from the underlying storage
|
|
device as well as lower allocation memory requirements for each
|
|
(sub)command. All subcommands will have the same unique value in
|
|
"parent_cmd_h" field and SCST_USER_SUBCOMMAND flag in "partial" field
|
|
of struct scst_user_scsi_cmd_exec. The final subcommand will also
|
|
have in that field SCST_USER_SUBCOMMAND_FINAL flag. All the
|
|
subcommands will have the original unmodified CDB. Possible values
|
|
are:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED/ - the partial data
|
|
transfers are not supported
|
|
|
|
<item> <bf/SCST_USER_PARTIAL_TRANSFERS_SUPPORTED_ORDERED/ - the partial data
|
|
transfers are supported, but all the subcommands must come in order
|
|
of data chunks. Could be used, e.g., for tape devices.
|
|
|
|
<item> <bf/SCST_USER_PARTIAL_TRANSFERS_SUPPORTED/ - the partial data transfers
|
|
are supported without limitations.
|
|
</itemize>
|
|
|
|
<item> <bf/tst/, <bf/queue_alg/, <bf/tas/, <bf/swp/, <bf/d_sense/ - set values for TST,
|
|
QUEUE ALGORITHM MODIFIER, TAS, SWP and D_SENSE fields from control mode page correspondingly,
|
|
see SPC.
|
|
|
|
<item> <bf/has_own_order_mgmt/ - true, if the user space handler has full
|
|
commands execution order management, i.e. guarantees commands execution
|
|
order as required by SAM. False otherwise.
|
|
</itemize>
|
|
|
|
Flags <it/parse_type/ and <it/on_free_cmd_type/ are designed to improve
|
|
performance by eliminating context switches to the user space handler,
|
|
when processing of the corresponding events isn't needed.
|
|
|
|
Flag <it/memory_reuse_type/ is designed to improve performance by eliminating
|
|
memory allocation, preparation and then freeing each time for each
|
|
commands, if the same memory will be allocated again and again. See
|
|
SCST_USER_ALLOC_MEM description below for more info.
|
|
|
|
SCST_USER_SET_OPTIONS should not be used from the same and the only
|
|
thread, which also handles incoming commands, otherwise there could be a
|
|
"deadlock", when SCST_USER_SET_OPTIONS waits for active commands finish,
|
|
but nobody handles them. This "deadlock" will be resolved only when
|
|
initiator, which sent those commands, aborts them after timeout.
|
|
|
|
<bf/IMPORTANT!/ It is duty of the caller to serialize
|
|
SCST_USER_SET_OPTIONS invocations. The kernel code does not have any
|
|
locking around modifying above properties.
|
|
|
|
|
|
<sect1> SCST_USER_REPLY_AND_GET_CMD
|
|
|
|
<p>
|
|
SCST_USER_REPLY_AND_GET_CMD allows at one call reply on the current
|
|
subcommand from SCST and get the next one. If 0 is returned by ioctl(),
|
|
SCST_USER_REPLY_AND_GET_CMD returns a SCST subcommand in the argument,
|
|
which is defined as the following:
|
|
|
|
<verb>
|
|
struct scst_user_get_cmd
|
|
{
|
|
uint32_t cmd_h;
|
|
uint32_t subcode;
|
|
union {
|
|
uint64_t preply;
|
|
struct scst_user_sess sess;
|
|
struct scst_user_scsi_cmd_parse parse_cmd;
|
|
struct scst_user_scsi_cmd_alloc_mem alloc_cmd;
|
|
struct scst_user_scsi_cmd_exec exec_cmd;
|
|
struct scst_user_scsi_on_free_cmd on_free_cmd;
|
|
struct scst_user_on_cached_mem_free on_cached_mem_free;
|
|
struct scst_user_tm tm_cmd;
|
|
};
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ - command handle used to identify the command in the reply.
|
|
|
|
<item> <bf/subcode/ - subcommand code, see 4.1 below
|
|
|
|
<item> <bf/preply/ - pointer to the reply data or, if 0, there is no reply. See
|
|
SCST_USER_REPLY_CMD for description of struct scst_user_reply_cmd
|
|
fields
|
|
</itemize>
|
|
|
|
Other union members contain command's specific payload.
|
|
|
|
For all received subcommands the user space device handler shall call
|
|
SCST_USER_REPLY_AND_GET_CMD or SCST_USER_REPLY_CMD function to tell SCST
|
|
that the subcommand's processing is finished, although some subcommands
|
|
don't return a value.
|
|
|
|
You can see description of possible subcommands in section
|
|
<ref id="subcommands" name="subcommands">.
|
|
|
|
|
|
<sect1> SCST_USER_REPLY_AND_GET_MULTI
|
|
|
|
<p>
|
|
SCST_USER_REPLY_AND_GET_MULTI allows at one call reply on the multiple
|
|
subcommands from SCST and get the multiple next subcommands.
|
|
|
|
Its argument is defined as:
|
|
|
|
<verb>
|
|
struct scst_user_get_multi {
|
|
aligned_u64 preplies;
|
|
int16_t replies_cnt;
|
|
int16_t replies_done;
|
|
int16_t cmds_cnt;
|
|
struct scst_user_get_cmd cmds[0];
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
|
|
<item> <bf/preplies/ - pointer to array of replies with size
|
|
<it/replies_cnt/. See SCST_USER_REPLY_CMD for description of struct
|
|
scst_user_reply_cmd fields
|
|
|
|
<item> <bf/replies_cnt/ - number of entries in <it/preplies/ array. If 0,
|
|
there are no replies
|
|
|
|
<item> <bf/replies_done/ - returns how many replies were processed by SCST. If there are
|
|
unprocessed replies, the user space device handler must retry the
|
|
unprocessed replies.
|
|
|
|
<item> <bf/cmds_cnt/ - on entry: number of available entries in <it/cmds/ array; on exit -
|
|
number of valid subcommands in <it/cmds/ array
|
|
|
|
<item> <bf/cmds/ - returned array of subcommands
|
|
|
|
</itemize>
|
|
|
|
Returns 0 on success or -1 in case of error, and errno is set
|
|
appropriately.
|
|
|
|
|
|
<sect1> SCST_USER_REPLY_CMD
|
|
|
|
<p>
|
|
SCST_USER_REPLY_CMD IOCTL function allows the user space handler to
|
|
return the result of a command's execution. Its argument is defined as:
|
|
|
|
<verb>
|
|
struct scst_user_reply_cmd
|
|
{
|
|
uint32_t cmd_h;
|
|
uint32_t subcode;
|
|
union {
|
|
int32_t result;
|
|
struct scst_user_scsi_cmd_reply_parse parse_reply;
|
|
struct scst_user_scsi_cmd_reply_alloc_mem alloc_reply;
|
|
struct scst_user_scsi_cmd_reply_exec exec_reply;
|
|
};
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ - command handle used to identify the command in the reply.
|
|
|
|
<item> <bf/subcode/ - subcommand code, see 4.1
|
|
</itemize>
|
|
|
|
<it/Union/ contains the subcommand's specific payloads:
|
|
|
|
<bf/result/ - subcommand's result code
|
|
|
|
<bf/OR/
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_reply_parse
|
|
{
|
|
uint8_t queue_type;
|
|
uint8_t data_direction;
|
|
uint16_t cdb_len;
|
|
aligned_i64 lba;
|
|
uint32_t op_flags;
|
|
aligned_i64 data_len;
|
|
int32_t bufflen;
|
|
int32_t out_bufflen;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/queue_type/ - SCSI task attribute (queue type). NOTE! In current
|
|
implementation setting changing this field from the provided value
|
|
affects commands execution only when then produced by iSCSI-SCST
|
|
target. With all other target drivers, this field is ignored. This is
|
|
because for them commands queueing is set before parse() called.
|
|
|
|
<item> <bf/data_direction/ - command's data flow direction, one of SCST_DATA_*
|
|
constants
|
|
|
|
<item> <bf/cdb_len/ - length of CDB
|
|
|
|
<item> <bf/lba/ - LBA of the command, if any
|
|
|
|
<item> <bf/op_flags/ - commands flags, one or more scst_cdb_flags bits, see above.
|
|
At least SCST_INFO_VALID must be set for correct processing.
|
|
SCST_IMPLICIT_HQ not implemented (yet) for single stage init target
|
|
drivers (all, except iSCSI), because custom parse can reorder
|
|
commands due to multithreaded processing.
|
|
|
|
<item> <bf/data_len/ - command's data length. Could be different from bufflen for
|
|
commands like VERIFY, which transfer different amount of data, than
|
|
process, or even none of them
|
|
|
|
<item> <bf/bufflen/ - command's buffer length
|
|
|
|
<item> <bf/out_bufflen/ - command's out buffer length (for bidirectional commands)
|
|
</itemize>
|
|
|
|
<bf/OR/
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_reply_alloc_mem
|
|
{
|
|
uint64_t pbuf;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/pbuf/ - pointer to command's data buffer
|
|
</itemize>
|
|
|
|
<bf/OR/
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_reply_exec
|
|
{
|
|
int32_t resp_data_len;
|
|
uint64_t pbuf;
|
|
|
|
uint8_t reply_type;
|
|
|
|
uint8_t status;
|
|
uint8_t sense_len;
|
|
aligned_u64 psense_buffer;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/resp_data_len/ - length of the response data
|
|
|
|
<item> <bf/pbuf/ - pointer to command's data buffer. Used only when in the
|
|
original SCST_USER_EXEC subcommand pbuf field is 0
|
|
|
|
<item> <bf/reply_type/ - could be one of the following constants:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_EXEC_REPLY_BACKGROUND/ - tells SCST send to the remote
|
|
initiator GOOD status, but the command not yet completed by the
|
|
user space handler, it is being executed in the background. When
|
|
it completed, the user space handler must call
|
|
SCST_USER_REPLY_CMD again with reply_type
|
|
SCST_EXEC_REPLY_COMPLETED. This mode can be used only for WRITEs
|
|
and with no mem reuse for them. Also in this mode
|
|
SCST_USER_ON_FREE_CMD_IGNORE supposed to be used.
|
|
SCST_USER_ON_FREE_CMD_IGNORE should be OK, because in this mode
|
|
the user space handler knows when this memory can be reused
|
|
(SCST_EXEC_REPLY_COMPLETED time). In case if the user space
|
|
handler finishes before SCST sent reply to the initiator, SCST
|
|
can still have reference to that memory, but it is harmless,
|
|
because SCST is not going to touch this memory anyhow in this
|
|
processing path, because WRITEs are not sending data, so this
|
|
memory can be safely reused for other needs.
|
|
|
|
<item> <bf/SCST_EXEC_REPLY_COMPLETED/ - the user space handler completed the command
|
|
</itemize>
|
|
|
|
<item> <bf/status/ - SAM status of the commands execution
|
|
|
|
<item> <bf/sense_len/ - length of sense data in psense_buffer, if any
|
|
|
|
<item> <bf/psense_buffer/ - pointed to sense buffer
|
|
</itemize>
|
|
|
|
|
|
<sect1> SCST_USER_FLUSH_CACHE
|
|
|
|
<p>
|
|
SCST_USER_FLUSH_CACHE - flushes SGV cache for the corresponding virtual
|
|
user space device and queues for all cached memory buffers corresponding
|
|
SCST_USER_ON_CACHED_MEM_FREE subcommands.
|
|
|
|
During execution of SCST_USER_FLUSH_CACHE at least one another thread
|
|
must process all coming subcommands, otherwise after timeout it will
|
|
fail with EBUSY error.
|
|
|
|
SCST_USER_FLUSH_CACHE doesn't have any parameters.
|
|
|
|
SCST_USER_FLUSH_CACHE returns 0 on success or -1 in case of error,
|
|
and errno is set appropriately.
|
|
|
|
|
|
<sect1> SCST_USER_DEVICE_CAPACITY_CHANGED
|
|
|
|
<p>
|
|
SCST_USER_DEVICE_CAPACITY_CHANGED - queues CAPACITY DATA HAS CHANGED
|
|
Unit Attention or corresponding Asynchronous Event to the corresponding
|
|
virtual device. It will notify remote initiators, connected to the
|
|
device, and allow them to automatically refresh new device size. You
|
|
should use SCST_USER_DEVICE_CAPACITY_CHANGED after resize of the device.
|
|
|
|
SCST_USER_DEVICE_CAPACITY_CHANGED doesn't have any parameters.
|
|
|
|
SCST_USER_DEVICE_CAPACITY_CHANGED returns 0 on success or -1 in case of
|
|
error, and errno is set appropriately.
|
|
|
|
|
|
<sect1> SCST_USER_GET_EXTENDED_CDB
|
|
|
|
<p>
|
|
SCST_USER_GET_EXTENDED_CDB - requests extended CDB, if CDB size is more
|
|
than SCST_MAX_CDB_SIZE bytes. In this case SCST_USER_GET_EXTENDED_CDB
|
|
returns additional CDB data beyond SCST_MAX_CDB_SIZE bytes.
|
|
|
|
SCST_USER_GET_EXTENDED_CDB has the following arguments:
|
|
|
|
<verb>
|
|
struct scst_user_get_ext_cdb {
|
|
uint32_t cmd_h;
|
|
aligned_u64 ext_cdb_buffer;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ - command handle used to identify the command in the reply.
|
|
|
|
<item> <bf/ext_cdb_buffer/ - pointer to buffer, where extended CDB will be copied.
|
|
</itemize>
|
|
|
|
SCST_USER_GET_EXTENDED_CDB returns 0 on success or -1 in case of error,
|
|
and errno is set appropriately.
|
|
|
|
|
|
<sect1> SCST_USER_PREALLOC_BUFFER
|
|
|
|
<p>
|
|
SCST_USER_PREALLOC_BUFFER - asks to preallocate a buffer.
|
|
|
|
It has the following arguments:
|
|
|
|
<verb>
|
|
union scst_user_prealloc_buffer {
|
|
struct scst_user_prealloc_buffer_in in;
|
|
struct scst_user_prealloc_buffer_out out;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/in/ - provides data about buffer to preallocate
|
|
|
|
<item> <bf/out/ - returns information about preallocated buffer
|
|
</itemize>
|
|
|
|
Structure <it/scst_user_prealloc_buffer_in/ has the following definition:
|
|
|
|
<verb>
|
|
struct scst_user_prealloc_buffer_in {
|
|
aligned_u64 pbuf;
|
|
uint32_t bufflen;
|
|
uint8_t for_clust_pool;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/pbuf/ - pointer to the buffer
|
|
|
|
<item> <bf/bufflen/ - size of the buffer
|
|
|
|
<item> <bf/for_clust_pool/ - if 1, then the buffer will be preallocated in the
|
|
clustered pool. If 0, then the buffer will be preallocated in the
|
|
normal pool.
|
|
</itemize>
|
|
|
|
Structure <it/scst_user_prealloc_buffer_out/ has the following definition:
|
|
|
|
<verb>
|
|
struct scst_user_prealloc_buffer_out {
|
|
uint32_t cmd_h;
|
|
}
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ - handle used to identify the buffer in
|
|
SCST_USER_ON_CACHED_MEM_FREE subcommand.
|
|
</itemize>
|
|
|
|
SCST_USER_PREALLOC_BUFFER returns 0 on success or -1 in case of error,
|
|
and errno is set appropriately.
|
|
|
|
<sect> SCST_USER subcommands<label id="subcommands">
|
|
|
|
<sect1> SCST_USER_ATTACH_SESS
|
|
|
|
<p>
|
|
SCST_USER_ATTACH_SESS notifies the user space handler that a new
|
|
initiator's session is about to be attached to the device. Payload
|
|
contains struct scst_user_sess, which is defined as the following:
|
|
|
|
<verb>
|
|
struct scst_user_sess
|
|
{
|
|
uint64_t sess_h;
|
|
uint64_t lun;
|
|
uint16_t threads_num;
|
|
uint8_t rd_only;
|
|
uint16_t scsi_transport_version;
|
|
uint16_t phys_transport_version;
|
|
char initiator_name[SCST_MAX_NAME];
|
|
char target_name[SCST_MAX_NAME];
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/sess_h/ - session's handle, may not be 0
|
|
|
|
<item> <bf/lun/ - assigned LUN for this device in this session
|
|
|
|
<item> <bf/threads_num/ - specifies amount of additional threads, requested by
|
|
the corresponding target driver
|
|
|
|
<item> <bf/rd_only/ - if true, this device is read only in this session
|
|
|
|
<item> <bf/scsi_transport_version/ - version descriptor value for SCSI transport
|
|
of this session
|
|
|
|
<item> <bf/phys_transport_version/ - version descriptor value for physical transport
|
|
of this session
|
|
|
|
<item> <bf/initiator_name/ - name of the remote initiator, which initiated this
|
|
session
|
|
|
|
<item> <bf/target_name/ - name of the target, to which this session belongs
|
|
</itemize>
|
|
|
|
When SCST_USER_ATTACH_SESS is returned, it is guaranteed that there are
|
|
no other commands are being executed or pending.
|
|
|
|
After SCST_USER_ATTACH_SESS function completed, the user space device
|
|
handler shall reply using "result" field of the corresponding reply
|
|
command.
|
|
|
|
|
|
<sect1> SCST_USER_DETACH_SESS
|
|
|
|
<p>
|
|
SCST_USER_DETACH_SESS notifies the user space handler that the
|
|
corresponding initiator is about to be detached from the particular
|
|
device. Payload contains struct scst_user_sess, where only handle field
|
|
is valid.
|
|
|
|
When SCST_USER_DETACH_SESS is returned, it is guaranteed that there are
|
|
no other commands are being executed or pending.
|
|
|
|
This command doesn't reply any return value, although
|
|
SCST_USER_REPLY_AND_GET_CMD or SCST_USER_REPLY_CMD function must be
|
|
called.
|
|
|
|
|
|
<sect1> SCST_USER_PARSE
|
|
|
|
<p>
|
|
SCST_USER_PARSE returns SCSI command on PARSE state of the SCST
|
|
processing. The PARSE state is intended to check validity of the
|
|
command, determine data transfer type and the necessary data buffer
|
|
size. This subcommand is returned only if SCST_USER_SET_OPTIONS
|
|
parse_type isn't set to SCST_USER_PARSE_STANDARD. In this case the
|
|
standard SCST internal parser for this SCSI device type will do all the
|
|
job.
|
|
|
|
Payload contains struct scst_user_scsi_cmd_parse, which is defined as
|
|
the following:
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_parse
|
|
{
|
|
uint64_t sess_h;
|
|
|
|
uint8_t cdb[SCST_MAX_CDB_SIZE];
|
|
uint16_t cdb_len;
|
|
|
|
aligned_i64 lba;
|
|
|
|
uint32_t timeout;
|
|
int32_t bufflen;
|
|
aligned_i64 data_len;
|
|
int32_t out_bufflen;
|
|
|
|
uint32_t op_flags;
|
|
|
|
uint8_t queue_type;
|
|
uint8_t data_direction;
|
|
|
|
uint8_t expected_values_set;
|
|
uint8_t expected_data_direction;
|
|
int32_t expected_transfer_len;
|
|
int32_t expected_out_transfer_len;
|
|
|
|
uint32_t sn;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/sess_h/ - corresponding session handler
|
|
|
|
<item> <bf/cdb/ - SCSI CDB
|
|
|
|
<item> <bf/cdb_len/ - SCSI CDB length
|
|
|
|
<item> <bf/lba/ - LBA of the command, if any
|
|
|
|
<item> <bf/timeout/ - CDB execution timeout
|
|
|
|
<item> <bf/bufflen/ - command's buffer length
|
|
|
|
<item> <bf/data_len/ - command's data length. Could be different from bufflen for
|
|
commands like VERIFY, which transfer different amount of data, than
|
|
process, or even none of them
|
|
|
|
<item> <bf/out_bufflen/ - for bidirectional commands command's OUT, i.e. from
|
|
initiator to target, buffer length
|
|
|
|
<item> <bf/op_flags/ - CDB flags, one or more scst_cdb_flags bits, see below.
|
|
|
|
<item> <bf/queue_type/ - SCSI task attribute (queue type)
|
|
|
|
<item> <bf/data_direction/ - command's data flow direction, one of SCST_DATA_*
|
|
constants
|
|
|
|
<item> <bf/expected_values_set/ - true if expected_data_direction and
|
|
expected_transfer_len contain valid values
|
|
|
|
<item> <bf/expected_data_direction/ - remote initiator supplied command's data
|
|
flow direction
|
|
|
|
<item> <bf/expected_transfer_len/ - remote initiator supplied transfer length
|
|
|
|
<item> <bf/expected_out_transfer_len/ - remote initiator supplied out, i.e. from
|
|
initiator to target, transfer length for bidirectional commands.
|
|
|
|
<item> <bf/sn/ - command's SN, which might be used for task management
|
|
</itemize>
|
|
|
|
Bits of scst_cdb_flags can be:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_TRANSFER_LEN_TYPE_FIXED/ - this command uses fixed blocks addressing
|
|
|
|
<item> <bf/SCST_SMALL_TIMEOUT/ - this command needs small timeout
|
|
|
|
<item> <bf/SCST_LONG_TIMEOUT/ - this command needs a long timeout
|
|
|
|
<item> <bf/SCST_UNKNOWN_LENGTH/ - data buffer length for this command is unknown
|
|
|
|
<item> <bf/SCST_INFO_VALID/ - bits of op_flags are valid
|
|
|
|
<item> <bf/SCST_IMPLICIT_HQ/ - this command is an implicit HEAD OF QUEUE command
|
|
|
|
<item> <bf/SCST_SKIP_UA/ - Unit Attentions shouldn't be delivered for this command
|
|
|
|
<item> <bf/SCST_WRITE_MEDIUM/ - this command writes data on the medium, so should be
|
|
forbidden for read-only devices
|
|
|
|
<item> <bf/SCST_LOCAL_CMD/ - this command can be processed by SCST core.
|
|
</itemize>
|
|
|
|
In the PARSE state of SCSI commands processing the user space device
|
|
handler shall check and provide SCST values for command data buffer
|
|
length, data flow direction and timeout, which it shall reply using the
|
|
corresponding reply command.
|
|
|
|
In case of any error the error reporting should be deferred until
|
|
SCST_USER_EXEC subcommand, where the appropriate SAM status and sense
|
|
shall be set.
|
|
|
|
|
|
<sect1> SCST_USER_ALLOC_MEM
|
|
|
|
<p>
|
|
SCST_USER_ALLOC_MEM returns SCSI command on memory allocation state of
|
|
the SCST processing. On this state the user space device handler shall
|
|
allocate the command's data buffer with bufflen length and then return
|
|
it to SCST using the corresponding reply command. Then SCST internally
|
|
will convert it in SG vector in order to use it itself and by target
|
|
drivers.
|
|
|
|
If the memory reuse type is disabled (i.e. set to SCST_USER_MEM_NO_REUSE)
|
|
there are no special requirements for buffer memory or its alignment, it
|
|
could be just what malloc() returned. If the memory reuse type is enabled,
|
|
the buffer shall be page size aligned, for example using memalign()
|
|
function.
|
|
|
|
Payload contains struct scst_user_scsi_cmd_alloc_mem, which is defined
|
|
as the following:
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_alloc_mem
|
|
{
|
|
uint64_t sess_h;
|
|
|
|
uint8_t cdb[SCST_MAX_CDB_SIZE];
|
|
uint16_t cdb_len;
|
|
|
|
int32_t alloc_len;
|
|
|
|
uint8_t queue_type;
|
|
uint8_t data_direction;
|
|
|
|
uint32_t sn;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/sess_h/ - corresponding session handler
|
|
|
|
<item> <bf/cdb/ - SCSI CDB
|
|
|
|
<item> <bf/cdb_len/ - SCSI CDB length
|
|
|
|
<item> <bf/alloc_len/ - command's buffer length
|
|
|
|
<item> <bf/queue_type/ - SCSI task attribute (queue type)
|
|
|
|
<item> <bf/data_direction/ - command's data flow direction, one of SCST_DATA_*
|
|
constants
|
|
|
|
<item> <bf/sn/ - command's SN, which might be used for task management
|
|
</itemize>
|
|
|
|
Memory allocation, preparation and freeing are ones of the most
|
|
complicated and expensive operations during SCSI commands processing.
|
|
Module scst_user provides a way to almost completely eliminate those
|
|
operations by reusing once allocated memory for subsequent SCSI
|
|
commands. It is controlled by <it/memory_reuse_type/ option, which could be
|
|
set by SCST_USER_SET_OPTIONS function. If any type memory reusage is
|
|
enabled, then SCST will use its internal SGV cache in order to cache
|
|
allocated and fully built SG vectors for subsequent commands of this
|
|
type, so for them SCST_USER_ALLOC_MEM subfunction will not be called and
|
|
in SCST_USER_EXEC pbuf pointer will point to that reused buffer.
|
|
|
|
SGV cache is a backend cache made on top of Linux kernel kmem cache. It
|
|
caches unused SG vectors for future allocations to improve performance.
|
|
Then, after some time of inactivity or when the system is under memory
|
|
pressure, the cache entries will be freed and the user space handler
|
|
will be notified using SCST_USER_ON_CACHED_MEM_FREE. See the SGV cache
|
|
documentation <url url="http://scst.sourceforge.net/sgv_cache.txt"> for more
|
|
details.
|
|
|
|
Since the SGV cache caches SG vectors, which can be bigger, than actual
|
|
data sizes of SCSI commands, alloc_len field could also be bigger, than
|
|
actually required by the SCSI command.
|
|
|
|
The memory reuse could be used in both SCSI tagged and untagged queuing
|
|
environments. In the SCSI tagged queuing environment the SGV cache will
|
|
take care that several commands don't use the same buffer simultaneously
|
|
by asking the user space handler to allocate a new data buffer, when all
|
|
cached ones are busy.
|
|
|
|
Some important notes:
|
|
|
|
<enum>
|
|
<item> If the user space handler needs to call fork(), it must call
|
|
madvise() with MADV_DONTFORK flag for all allocated data buffers,
|
|
otherwise parent or child process could loose the connection with them,
|
|
which could lead to data corruption. See <url url="http://lwn.net/Articles/171941/">
|
|
for details.
|
|
|
|
<item> The interface assumes that all allocated memory by the user space
|
|
handler is DMA'able by the target hardware. This is almost always true
|
|
for most modern systems, except if the target hardware isn't capable of
|
|
using 64-bit address space and the system has >4GB of memory or the
|
|
memory addresses are in address space, which is unavailable with 32-bit
|
|
addresses.
|
|
</enum>
|
|
|
|
In case of any error the error reporting should be deferred until
|
|
SCST_USER_EXEC subcommand, where the appropriate SAM status and sense
|
|
should be set.
|
|
|
|
|
|
<sect1> SCST_USER_EXEC
|
|
|
|
<p>
|
|
SCST_USER_EXEC returns SCSI command on execution state of the SCST
|
|
processing. The user space handler should execute the SCSI command and
|
|
reply using the corresponding reply command.
|
|
|
|
In some cases for performance reasons for READ-type SCSI commands
|
|
SCST_USER_ALLOC_MEM subcommand isn't returned before SCST_USER_EXEC.
|
|
Thus, if pbuf pointer is 0 and the SCSI command needs data transfer, the
|
|
user space handler should be prepared to allocate the data buffer with
|
|
size alloc_len, which could be bigger (due to the SGV cache), than
|
|
actually required by the SCSI command. But field bufflen will contain
|
|
the correct value. All the memory reusage rules, described for
|
|
SCST_USER_ALLOC_MEM, apply to SCST_USER_EXEC as well.
|
|
|
|
Payload contains struct scst_user_scsi_cmd_exec, which is defined as the
|
|
following:
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_exec
|
|
{
|
|
uint64_t sess_h;
|
|
|
|
uint8_t cdb[SCST_MAX_CDB_SIZE];
|
|
uint16_t cdb_len;
|
|
|
|
aligned_i64 lba;
|
|
|
|
aligned_i64 data_len;
|
|
int32_t bufflen;
|
|
int32_t alloc_len;
|
|
uint64_t pbuf;
|
|
uint8_t queue_type;
|
|
uint8_t data_direction;
|
|
uint8_t partial;
|
|
uint32_t timeout;
|
|
|
|
aligned_u64 p_out_buf;
|
|
int32_t out_bufflen;
|
|
|
|
uint32_t sn;
|
|
|
|
uint32_t parent_cmd_h;
|
|
int32_t parent_cmd_data_len;
|
|
uint32_t partial_offset;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/sess_h/ - corresponding session handler
|
|
|
|
<item> <bf/cdb/ - SCSI CDB
|
|
|
|
<item> <bf/cdb_len/ - SCSI CDB length
|
|
|
|
<item> <bf/lba/ - LBA of the command, if any
|
|
|
|
<item> <bf/data_len/ - command's data length. Could be different from bufflen for
|
|
commands like VERIFY, which transfer different amount of data, than
|
|
process, or even none of them
|
|
|
|
<item> <bf/bufflen/ - command's buffer length
|
|
|
|
<item> <bf/alloc_len/ - command's buffer length, which should be allocated, if pbuf
|
|
is 0 and the command requires data transfer
|
|
|
|
<item> <bf/pbuf/ - pointer to command's data buffer or 0 for SCSI commands
|
|
without data transfer.
|
|
|
|
<item> <bf/queue_type/ - SCSI task attribute (queue type)
|
|
|
|
<item> <bf/data_direction/ - command's data flow direction, one of SCST_DATA_*
|
|
constants
|
|
|
|
<item> <bf/partial/ - specifies, if the command is a partial subcommand, could
|
|
have the following OR'ed flags:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_USER_SUBCOMMAND/ - set if the command is a partial subcommand
|
|
|
|
<item> <bf/SCST_USER_SUBCOMMAND_FINAL/ - set if the subcommand is a final one
|
|
</itemize>
|
|
|
|
<item> <bf/timeout/ - CDB execution timeout
|
|
|
|
<item> <bf/p_out_buf/ - for bidirectional commands pointer on command's OUT, i.e. from
|
|
initiator to target, data buffer or 0 for SCSI commands without data
|
|
transfer
|
|
|
|
<item> <bf/out_bufflen/ - for bidirectional commands command's OUT, i.e. from
|
|
initiator to target, buffer length
|
|
|
|
<item> <bf/sn/ - command's SN, which might be used for task management
|
|
|
|
<item> <bf/parent_cmd_h/ - has the same unique value for all partial data
|
|
transfers subcommands of one original (parent) command
|
|
|
|
<item> <bf/parent_cmd_data_len/ - for partial data transfers subcommand has the
|
|
size of the overall data transfer of the original (parent) command
|
|
|
|
<item> <bf/partial_offset/ - has offset of the subcommand in the original
|
|
(parent) command
|
|
</itemize>
|
|
|
|
It is guaranteed that only commands of the same queue_type per session
|
|
can be returned simultaneously.
|
|
|
|
In case of any error it should be reported via appropriate SAM status
|
|
and sense. If it happens for a subcommand of a partial data transfers
|
|
command, all other subcommands of this command, which already passed the
|
|
the user space handler or will be passed in the future, will be aborted
|
|
by scst_user, the user space handler should ignore them.
|
|
|
|
|
|
<sect1> SCST_USER_ON_FREE_CMD
|
|
|
|
<p>
|
|
SCST_USER_ON_FREE_CMD returns SCSI command when the command is about to
|
|
be freed. At this stage, the user space device handler could do any
|
|
necessary cleanups, for instance, free allocated for data buffer memory.
|
|
|
|
<bf/NOTE!/ If the memory reusage is enabled, then the data buffer must not be
|
|
freed, it will be reused by subsequent SCSI commands. The buffer must be
|
|
freed only on SCST_USER_ON_CACHED_MEM_FREE event.
|
|
|
|
Payload contains struct scst_user_scsi_on_free_cmd, which is defined
|
|
as the following:
|
|
|
|
<verb>
|
|
struct scst_user_scsi_on_free_cmd
|
|
{
|
|
uint64_t pbuf;
|
|
int32_t resp_data_len;
|
|
uint8_t buffer_cached;
|
|
uint8_t aborted;
|
|
uint8_t status;
|
|
uint8_t delivery_status;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/pbuf/ - pointer to command's data buffer or 0 for SCSI commands
|
|
without data transfer.
|
|
|
|
<item> <bf/resp_data_len/ - length of the response data
|
|
|
|
<item> <bf/buffer_cached/ - true, if memory reusage is enabled for this command
|
|
|
|
<item> <bf/aborted/ - true, if command was aborted
|
|
|
|
<item> <bf/status/ - SAM status of the commands execution
|
|
|
|
<item> <bf/delivery_status/ - status of cmd's status/data delivery to remote
|
|
initiator. Can be:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_CMD_DELIVERY_SUCCESS/ - delivery succeeded
|
|
|
|
<item> <bf/SCST_CMD_DELIVERY_FAILED/ - delivery failed
|
|
</itemize>
|
|
</itemize>
|
|
|
|
The user space handler should reply using the corresponding reply
|
|
command. No error code is needed.
|
|
|
|
|
|
<sect1> SCST_USER_ON_CACHED_MEM_FREE
|
|
|
|
<p>
|
|
SCST_USER_ON_CACHED_MEM_FREE subcommand is returned, when SGV cache
|
|
decided that this buffer isn't needed anymore. This happens after some
|
|
time of inactivity or when the system is under memory pressure.
|
|
|
|
Payload contains struct scst_user_on_cached_mem_free, which is defined
|
|
as the following:
|
|
|
|
<verb>
|
|
struct scst_user_scsi_cmd_alloc_mem
|
|
{
|
|
uint64_t pbuf;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/pbuf/ - pointer to buffer, which should be freed
|
|
</itemize>
|
|
|
|
|
|
<sect1> SCST_USER_TASK_MGMT_RECEIVED
|
|
|
|
<p>
|
|
SCST_USER_TASK_MGMT_RECEIVED subcommand notifies that a task management
|
|
function has been received. Payload contains struct scst_user_tm, which
|
|
is defined as the following:
|
|
|
|
<verb>
|
|
struct scst_user_tm
|
|
{
|
|
uint64_t sess_h;
|
|
uint32_t fn;
|
|
uint32_t cmd_h_to_abort;
|
|
uint32_t cmd_sn;
|
|
uint8_t cmd_sn_set;
|
|
},
|
|
</verb>
|
|
|
|
where:
|
|
|
|
<itemize>
|
|
<item> <bf/sess_h/ - corresponding session handler
|
|
|
|
<item> <bf/fn/ - task management function, see below
|
|
|
|
<item> <bf/cmd_h_to_abort/ - handle of command to abort. Valid only if fn is
|
|
SCST_ABORT_TASK
|
|
|
|
<item> <bf/cmd_sn/ - if cmd_sn_set is set, contains maximum commands SN, which
|
|
this task management function affects. See iSCSI RFC 3720 10.5.1 for
|
|
more details.
|
|
|
|
<item> <bf/cmd_sn_set/ - specifies if cmd_sn is valid
|
|
</itemize>
|
|
|
|
On this notification dev handler should do the best to ensure that all
|
|
aborted by this TM command SCSI commands complete ASAP.
|
|
|
|
Possible values of <it/fn/ field:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_ABORT_TASK/ - cmd_h_to_abort shall be aborted
|
|
|
|
<item> <bf/SCST_ABORT_TASK_SET/ - task set on the device shall be aborted
|
|
|
|
<item> <bf/SCST_CLEAR_ACA/ - ACA status shall be cleared
|
|
|
|
<item> <bf/SCST_CLEAR_TASK_SET/ - task set on the device shall be cleared
|
|
|
|
<item> <bf/SCST_LUN_RESET/, <bf/SCST_TARGET_RESET/ - reset of the device shall be done
|
|
|
|
<item> <bf/SCST_NEXUS_LOSS_SESS/ - notifies about nexus loss event for the session
|
|
|
|
<item> <bf/SCST_ABORT_ALL_TASKS_SESS/ - all tasks in the session shall be aborted
|
|
|
|
<item> <bf/SCST_NEXUS_LOSS/ - notifies about global nexus loss event
|
|
|
|
<item> <bf/SCST_ABORT_ALL_TASKS/ - all tasks shall be aborted
|
|
</itemize>
|
|
|
|
The "result" field of the corresponding reply command is ignored for
|
|
this subcommand.
|
|
|
|
|
|
<sect1> SCST_USER_TASK_MGMT_DONE
|
|
|
|
<p>
|
|
SCST_USER_TASK_MGMT_DONE subcommand notifies that all aborted by task
|
|
management function commands have finished, so the dev handler can
|
|
perform actual actions required by this TM command. For instance, reset
|
|
all MODE PAGES variables to default values.
|
|
|
|
Payload contains struct scst_user_tm, which was defined above.
|
|
|
|
After the TM function is completed, the device handler shall reply using
|
|
"result" field of the corresponding reply command.
|
|
|
|
Possible return values are:
|
|
|
|
<itemize>
|
|
<item> <bf/SCST_MGMT_STATUS_SUCCESS/ - success
|
|
|
|
<item> <bf/SCST_MGMT_STATUS_TASK_NOT_EXIST/ - task does not exist
|
|
|
|
<item> <bf/SCST_MGMT_STATUS_LUN_NOT_EXIST/ - LUN does not exist
|
|
|
|
<item> <bf/SCST_MGMT_STATUS_FN_NOT_SUPPORTED/ - task management function not
|
|
supported
|
|
|
|
<item> <bf/SCST_MGMT_STATUS_REJECTED/ - task management function was rejected
|
|
|
|
<item> <bf/SCST_MGMT_STATUS_FAILED/ - task management function failed
|
|
</itemize>
|
|
|
|
|
|
<sect> Commands processing flow example.
|
|
|
|
<p>
|
|
As the example consider a simple synchronous VTL, which serves one
|
|
virtual SCSI tape device and can process only one command at time from
|
|
any initiator.
|
|
|
|
<itemize>
|
|
|
|
<item> At the beginning the VTL opens using <bf/open()/ call /dev/scst_user/ in the
|
|
default blocking mode.
|
|
|
|
<item> Then it using <bf/SCST_USER_REGISTER_DEVICE/ ioctl() function registers the
|
|
tape device. Since only one command at time is supported, the allocated
|
|
command's data memory could be reused for both READ-type (i.e. which
|
|
involve data transfer from target to initiator) and WRITE-type (i.e.
|
|
which involve data transfer from initiator to target) commands. So the
|
|
device is configured with <bf/parse_type/ <it/SCST_USER_PARSE_STANDARD/,
|
|
<bf/on_free_cmd_type/ <it/SCST_USER_ON_FREE_CMD_IGNORE/, <bf/memory_reuse_type/
|
|
<it/SCST_USER_MEM_REUSE_ALL/ and <bf/partial_transfers_type/
|
|
<it/SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED/.
|
|
|
|
<item> Then it prepares struct <bf/scst_user_get_cmd/ with reply set to <it/0/, calls
|
|
<bf/SCST_USER_REPLY_AND_GET_CMD/ ioctl() and waits until some initiator
|
|
connects to its tape device. On that event the VTL receives
|
|
<bf/SCST_USER_ATTACH_SESS/ subcommand. Since the VTL doesn't use any
|
|
initiator specific data, it can do nothing on that subcommand, so it
|
|
prepares scst_user_reply_cmd structure, where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ set to returned by SCST_USER_REPLY_AND_GET_CMD ioctl() cmd_h
|
|
|
|
<item> <bf/subcode/ set to <it/SCST_USER_ATTACH_SESS/
|
|
|
|
<item> <bf/result/ set to <it/0/
|
|
</itemize>
|
|
|
|
<item> Then it prepares <bf/struct scst_user_get_cmd/ with reply set to the prepared
|
|
scst_user_reply_cmd structure, calls <bf/SCST_USER_REPLY_AND_GET_CMD/ ioctl()
|
|
and waits for some SCSI command arrives from the initiator.
|
|
|
|
<item> If the received SCSI command is READ-type one, SCST does the necessary
|
|
preparations, then the VTL receives <bf/SCST_USER_EXEC/ subcommand, where
|
|
<bf/bufflen/ and <bf/data_len/ fields set correctly, but memory for buffer isn't
|
|
allocated, so <bf/pbuf/ field is <it/0/. The VTL then allocates the data buffer
|
|
with size <bf/alloc_len/, e.g. using malloc(). Then the VTL reads the data
|
|
from disk in it, e.g. using O_DIRECT read() function, then prepares
|
|
scst_user_reply_cmd structure, where:
|
|
|
|
<itemize>
|
|
<item> <bf/cmd_h/ set to returned by SCST_USER_REPLY_AND_GET_CMD ioctl() cmd_h
|
|
|
|
<item> <bf/subcode/ set to <it/SCST_USER_EXEC/
|
|
|
|
<item> <bf/exec_reply.resp_data_len/ set to length of the read data
|
|
|
|
<item> <bf/exec_reply.pbuf/ set to the data buffer, where the data were read
|
|
|
|
<item> <bf/exec_reply.reply_type/ set to <it/SCST_EXEC_REPLY_COMPLETED/
|
|
|
|
<item> <bf/exec_reply.status/ set to the SAM defined status of the
|
|
operation
|
|
|
|
<item> <bf/exec_reply.sense_len/ set and <bf/exec_reply.psense_buffer/ filled with
|
|
sense data, if necessary
|
|
</itemize>
|
|
|
|
<item> Then it prepares <bf/struct scst_user_get_cmd/ with reply set to the prepared
|
|
scst_user_reply_cmd structure, calls <bf/SCST_USER_REPLY_AND_GET_CMD/ ioctl()
|
|
and waits for the next SCSI command arrives from the initiator.
|
|
|
|
<item> That's all for this SCSI command. For the next command the used
|
|
data buffer will be reused.
|
|
|
|
</itemize>
|
|
|
|
For WRITE-type SCSI commands the processing is the same, but
|
|
<bf/SCST_USER_ALLOC_MEM/ will be returned before <bf/SCST_USER_EXEC/, since the
|
|
data transfer from the initiator precedes the commands execution.
|
|
|
|
In case, if the first command requires 4K data buffer, but the second
|
|
one - 1M, for it the VTL also will be asked to allocate the buffer.
|
|
Then, if no more 4K commands come for some time, for it
|
|
<bf/SCST_USER_ON_CACHED_MEM_FREE/ subcommand will be returned to the VTL in
|
|
order to ask it to free that buffer.
|
|
|
|
</article>
|