diff --git a/doc/Makefile b/doc/Makefile index 44257779d..d2b95bd76 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -8,7 +8,7 @@ RTFS = $(SRCS:.sgml=.rtf) COMMAND=linuxdoc --backend= -all: txt pdf html +all: pdf html txt: $(TXTS) diff --git a/doc/fig2.png b/doc/fig2.png index 3bdf882dc..667e41289 100644 Binary files a/doc/fig2.png and b/doc/fig2.png differ diff --git a/doc/fig3.png b/doc/fig3.png deleted file mode 100644 index e502f2dd3..000000000 Binary files a/doc/fig3.png and /dev/null differ diff --git a/doc/fig4.png b/doc/fig4.png deleted file mode 100644 index 667e41289..000000000 Binary files a/doc/fig4.png and /dev/null differ diff --git a/doc/scst_pg.sgml b/doc/scst_pg.sgml index f690b2536..02ff1f810 100644 --- a/doc/scst_pg.sgml +++ b/doc/scst_pg.sgml @@ -2,135 +2,99 @@
-Generic SCSI Target Middle Level for Linux + +SCST technical description + Vladislav Bolkhovitin -Version 0.9.5 2006/12/01, actual for SCST 0.9.5 and later - - -This document describes SCSI target mid-level for Linux (SCST), its -architecture and drivers from the driver writer's point of view. - + +Version 3.0.0 for SCST 3.0.0 and later + Introduction -

-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: +

SCST is a SCSI target mid-level subsystem for Linux. It provides +unified consistent interface between SCSI target drivers, backend device +handlers and Linux kernel as well as simplifies target drivers +development as much as possible. + +It has the following features: - 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. - - 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. + Very low overhead and fine-grained locks, which allow to reach +maximum possible performance and scalability that close to theoretical +limit. Complete SMP support. - Undertakes most problems, related to execution contexts, thus -practically eliminating one of the most complicated problem in the -kernel drivers development. For example, target drivers for Marvell SAS -adapters or for InfiniBand SRP are less 3000 lines of code long. - Performs all required pre- and post- processing of incoming -requests and all necessary error recovery functionality. +requests and all necessary error recovery functionality. - Emulates necessary functionality of SCSI host adapter, because + Emulates necessary functionality of SCSI host adapters, 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: - + Generation of necessary UNIT ATTENTIONs, their storage and delivery to all connected remote initiators (sessions). - RESERVE/RELEASE functionality. + RESERVE/RELEASE functionality, including Persistent Reservations. - CA/ACA conditions. - All types of RESETs and other task management functions. - - 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. + + 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, so different remote initiators could + see different set of devices. Other necessary functionality (task attributes, etc.) as specified in SAM-2, SPC-2, SAM-3, SPC-3 and other SCSI standards. - + - - 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. + + Verifies all incoming requests to ensure commands execution +reliability and security. + + Device handlers architecture provides extra flexibility by +allowing to make additional requests processing, which is completely +independent from target drivers, for example, data caching or device +dependent exceptional conditions treatment. -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 -. - Terms and Definitions -

+SCST Architecture +SCST Core Architecture -

+

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. @@ -171,42 +135,61 @@ interaction between SCST, its drivers and Linux SCSI subsystem. -Target driver registration + Target drivers + +struct scst_tgt_template

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 +calling Structure scst_tgt_template - -

struct scst_tgt_template { int sg_tablesize; - const char name[15]; + const char name[SCST_MAX_NAME]; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; + unsigned no_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); + unsigned no_proc_entry:1; - int (* xmit_response)(struct scst_cmd *cmd); + int max_hw_pending_time; + + int threads_num; + + 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_hw_pending_cmd_timeout) (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); + int (*alloc_data_buf) (struct scst_cmd *cmd); + + void (*preprocessing_done) (struct scst_cmd *cmd); + + int (*pre_exec) (struct scst_cmd *cmd); + + void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd); + void (*task_mgmt_fn_done)(struct scst_mgmt_cmd *mgmt_cmd); + + int (*report_aen) (struct scst_aen *aen); + + int (*read_proc) (struct seq_file *seq, struct scst_tgt *tgt); + int (*write_proc) (char *buffer, char **start, off_t offset, + int length, int *eof, struct scst_tgt *tgt); + + int (*get_initiator_port_transport_id) (struct scst_session *sess, + uint8_t **transport_id); } @@ -225,97 +208,163 @@ the template. Must be defined. unchecked DMA onto an ISA bus. = 0 to signify -the number of detected target adapters. A negative value should be -returned whenever there is an error. Must be defined. += 0 to +signify the number of detected target adapters. A negative value should +be returned whenever there is an error. Must be defined. - +0 if the regular SCST allocation should be done. In case of returning +successfully, scst_cmd->tgt_data_buf_alloced will be set by SCST. It is +possible that both target driver and dev handler request own memory +allocation. If allocation in atomic context, i.e. scst_cmd_atomic() is +true, and < 0 is returned, this function will be recalled in thread +context. Note that the driver will have to handle itself all relevant +details such as scatterlist setup, highmem, freeing the allocated +memory, etc. + + - - + Functions @@ -344,58 +393,35 @@ command will be destroyed, if by -More about More about xmit_response() -

-As already written above, function +As already written above, function xmit_response() should transmit +the response data and the status from the cmd parameter. - - - - -If Target driver registration functions scst_register_target_template() @@ -416,13 +442,13 @@ Where: Returns 0 on success or appropriate error code otherwise. -scst_register() +scst_register_target()

-Function -struct scst_tgt *scst_register( +struct scst_tgt *scst_register_target( struct scst_tgt_template *vtt) @@ -434,20 +460,20 @@ Where: Returns target structure based on template vtt or NULL in case of error. -Target driver unregistration +Target driver unregistration functions

In order to unregister itself target driver should at first call -scst_unregister() +scst_unregister_target()

-Function -void scst_unregister( +void scst_unregister_target( struct scst_tgt *tgt) @@ -457,7 +483,7 @@ Where: -scst_unregister_target_template() +scst_unregister_target_template()

Function -SCST session registration +Device specific drivers (backend device handlers) + +

Device specific drivers are add-ons for SCST, which help SCST to +analyze incoming requests and determine parameters, specific to various +types of devices as well as actually execute specified SCSI commands. +Device handlers are intended for the following: + + + +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: + + + + Improves security and reliability by not trusting the data + supplied by remote initiator via SCSI low-level protocol. + + 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. + + + + Execute commands + +To process some exceptional conditions, like ILI on tape devices. + +To initialize incoming commands with some device-specific +parameters, like timeout value. + +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. + + + +Device handlers 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 Structure +Structure +struct scst_dev_type +{ + char name[]; + int type; + + unsigned parse_atomic:1; + unsigned alloc_data_buf_atomic:1; + unsigned dev_done_atomic:1; + + unsigned no_proc:1; + + unsigned exec_sync:1; + + unsigned pr_cmds_notifications:1; + + int threads_num; + enum scst_dev_type_threads_pool_type threads_pool_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 (*alloc_data_buf) (struct scst_cmd *cmd); + int (*exec) (struct scst_cmd *cmd); + int (*dev_done) (struct scst_cmd *cmd); + int (*on_free_cmd) (struct scst_cmd *cmd); + + int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd, + struct scst_tgt_dev *tgt_dev); + + int (*read_proc) (struct seq_file *seq, struct scst_dev_type *dev_type); + int (*write_proc) (char *buffer, char **start, off_t offset, + int length, int *eof, struct scst_dev_type *dev_type); +} + + +Where: + + + + 0. Possible values: + + + + + +bufflen/ and data_direction/ (both - REQUIRED). Returns the +command's scst_cmd_done()/ callback. + +Returns: + + + + +If this function provides sync execution, you should set +exec_sync flag and consider to setup dedicated threads by +setting 0. + +Optional, if not set, the commands will be sent directly to SCSI +device. + + + + + + + +Device specific drivers registration + + scst_register_dev_driver() + +

+To work with SCST a device specific driver must register itself in SCST by +calling +int scst_register_dev_driver( + struct scst_dev_type *dev_type) + + +Where: + + + + +The function returns 0 on success or appropriate error code otherwise. + + scst_register_virtual_device() + +

+To create a virtual device a device handler must register it in SCST by +calling +int scst_register_virtual_device( + struct scst_dev_type *dev_handler, + const char *dev_name) + + +Where: + + + + + +The function returns ID assigned to the device on success, or negative +value otherwise. + +All local real SCSI devices will be registered and unregistered by the +SCST core automatically, so pass-through dev handlers don't have to +worry about it. + + +Device specific drivers unregistration + + scst_unregister_virtual_device() + +

+Virtual devices unregistered by calling + +void scst_unregister_virtual_device( + int id) + + +Where: + + + + + scst_unregister_dev_driver() + +

+Device specific driver is unregistered by calling + +void scst_unregister_dev_driver( + struct scst_dev_type *dev_type) + + +Where: + + + + +SCST sessions + +SCST sessions registration

When target driver determines that it needs to create new SCST session @@ -485,11 +843,12 @@ struct scst_session *scst_register_session( struct scst_tgt *tgt, int atomic, const char *initiator_name, - void *data, + void *tgt_priv, + void *result_fn_data, void (*result_fn) ( struct scst_session *sess, - void *data, - int result)); + void *data, + int result)) Where: @@ -505,7 +864,9 @@ 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. - - - - - Session registration when - - -

- - - - Session registration when -
- -SCST session unregistration +SCST sessions unregistration

SCST session unregistration basically is the same, except that instead of @@ -571,9 +914,9 @@ atomic parameter there is void scst_unregister_session( - struct scst_session *sess, + struct scst_session *sess, int wait, - void (* unreg_done_fn)( + void (*unreg_done_fn)( struct scst_session *sess)) @@ -584,9 +927,9 @@ Where: - + All outstanding commands will be finished regularly. After -The commands processing and interaction between SCST and its drivers + +Commands processing and interaction between SCST core and its drivers

+Consider simplified commands processing example. It assumes that target +driver doesn't need own memory allocation, i.e. not defined +alloc_data_buf() callback. Example of such target driver is qla2x00t. + The commands processing by SCST started when target driver calls - If the command required no data transfer, it will be passed to -SCSI mid-level directly or via device handler's If the command is a If the command is a If the command is a If the command is a When the command is finished by SCSI mid-level, device handler's - - - + + The commands processing flow -Additionally, before calling - - Expected transfer length and direction via - - The commands processing functions scst_rx_cmd() @@ -696,11 +1026,11 @@ following: struct scst_cmd *scst_rx_cmd( - struct scst_session *sess, - const uint8_t *lun, + struct scst_session *sess, + const uint8_t *lun, int lun_len, - const uint8_t *cdb, - int cdb_len, + const uint8_t *cdb, + int cdb_len, int atomic) @@ -710,15 +1040,14 @@ Where: void scst_cmd_init_done( - struct scst_cmd *cmd, - int pref_context) + struct scst_cmd *cmd, + enum scst_exec_context pref_context) Where: @@ -745,7 +1074,7 @@ Where: @@ -760,7 +1089,7 @@ is defined as the following: void scst_rx_data( struct scst_cmd *cmd, int status, - int pref_context) + enum scst_exec_context pref_context) Where: @@ -772,7 +1101,7 @@ Where: @@ -784,45 +1113,51 @@ Parameter scst_tgt_cmd_done()

-Function void scst_tgt_cmd_done( - struct scst_cmd *cmd) + struct scst_cmd *cmd, + enum scst_exec_context pref_context) Where: + The commands processing context

Execution context often is a major problem in the kernel drivers -development, because many contexts, like IRQ one, greatly limit +development, because many contexts, like IRQ context, 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. +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 @@ -834,17 +1169,16 @@ Each command can be processed in one of four contexts: Directly, i.e. in the caller's context, without limitations Directly atomically, i.e. with sleeping forbidden -In the SCST's internal per processor or per session thread -In the SCST's per processor tasklet +In the SCST's internal threads +In the SCST's per processor tasklets -The target driver sets this context as pref_context parameter for -Preferred context constants

-There are the following preferred context constants: +There are the following preferred context constants: @@ -878,8 +1212,85 @@ context. command processing. Supposed to be used if the driver's architecture does not allow using any of above. + +SCST commands' processing states + +

+There are the following processing states, which a SCST command passes +through during execution and which could be returned by device handler's + + +tgt_dev/ +assignment) state + + + + Task management functions

@@ -887,49 +1298,62 @@ There are the following task management functions supported: - +All task management functions return completion status via +scst_rx_mgmt_fn_tag()

Function int scst_rx_mgmt_fn_tag( - struct scst_session *sess, - int fn, + struct scst_session *sess, + int fn, uint32_t tag, - int atomic, - void *tgt_specific) + int atomic, + void *tgt_priv) Where: @@ -944,15 +1368,15 @@ Where: 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 scst_rx_mgmt_fn_lun() @@ -960,18 +1384,18 @@ driver's callback.

Function int scst_rx_mgmt_fn_lun( - struct scst_session *sess, + struct scst_session *sess, int fn, - const uint8_t *lun, + const uint8_t *lun, int lun_len, - int atomic, - void *tgt_specific); + int atomic, + void *tgt_priv); Where: @@ -988,1312 +1412,767 @@ Where: 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 Device specific drivers (device handlers) +Possible status constants which can be returned by + + + + +SGV cache

-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: +SCST SGV cache is a memory management subsystem in SCST. One can call it +a "memory pool", but Linux kernel already have a mempool interface, +which serves different purposes. SGV cache provides to SCST core, target +drivers and backend dev handlers facilities to allocate, build and cache +SG vectors for data buffers. The main advantage of it is the caching +facility, when it doesn't free to the system each vector, which is not +used anymore, but keeps it for a while (possibly indefinitely) to let it +be reused by the next consecutive command. This allows to: -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: + Reduce commands processing latencies and, hence, improve performance; - - - Improves security and reliability by not trusting the data - supplied by remote initiator via SCSI low-level protocol. - - 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. - - - -To process some exceptional conditions, like ILI on tape devices. - -To initialize incoming commands with some device-specific -parameters, like timeout value. - -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. + Make commands processing latencies predictable, which is essential + for RT applications. -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. +The freed SG vectors are kept by the SGV cache either for some (possibly +indefinite) time, or, optionally, until the system needs more memory and +asks to free some using the set_shrinker() interface. Also the SGV cache +allows to: -Without appropriate device handler SCST hides devices of this type from -remote initiators and returns -Device specific driver registration + Cluster pages together. "Cluster" means merging adjacent pages in a +single SG entry. It allows to have less SG entries in the resulting SG +vector, hence improve performance handling it as well as allow to +work with bigger buffers on hardware with limited SG capabilities. -scst_register_dev_driver() + Set custom page allocator functions. For instance, scst_user device +handler uses this facility to eliminate unneeded mapping/unmapping of +user space pages and avoid unneeded IOCTL calls for buffers allocations. +In fileio_tgt application, which uses a regular malloc() function to +allocate data buffers, this facility allows ~30% less CPU load and +considerable performance increase. + + Prevent each initiator or all initiators altogether to allocate too +much memory and DoS the target. Consider 10 initiators, which can have +access to 10 devices each. Any of them can queue up to 64 commands, each +can transfer up to 1MB of data. So, all of them in a peak can allocate +up to 10*10*64 = ~6.5GB of memory for data buffers. This amount must be +limited somehow and the SGV cache performs this function. + + + + Implementation

-To work with SCST a device specific driver must register itself in SCST by -calling -int scst_register_dev_driver( - struct scst_dev_type *dev_type) - + -Where: + With fixed size buffers. - - + With a set of power 2 size buffers. In this mode each SGV cache +(struct sgv_pool) has SGV_POOL_ELEMENTS (11 currently) of kmem caches. +Each of those kmem caches keeps SGV cache objects (struct sgv_pool_obj) +corresponding to SG vectors with size of order X pages. For instance, +request to allocate 4 pages will be served from kmem cache[2&rsqb, since the +order of the of number of requested pages is 2. If later request to +allocate 11KB comes, the same SG vector with 4 pages will be reused (see +below). This mode is in average allows less memory overhead comparing +with the fixed size buffers mode. -The function returns 0 on success or appropriate error code otherwise. + -Structure Interface + + sgv_pool *sgv_pool_create()

-Structure -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; -} +struct sgv_pool *sgv_pool_create( + const char *name, + enum sgv_clustering_types clustered, int single_alloc_pages, + bool shared, int purge_interval) -Where: +This function creates and initializes an SGV cache. It has the following +arguments: - - - 0, then the SGV cache will work in the + fixed size buffers mode. In this case single_alloc_pages sets the + size of each buffer in pages. - bufflen/ and data_direction/ (see below - - - - - - - - - - - - -If the driver needs to create additional files in its /proc -subdirectory, it can use -Structure -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; -} - - -Where: - - - - - - - - - -Field data_direction/, set by - - - -Device specific driver unregistration + void sgv_pool_del()

-Device specific driver is unregistered by calling - -void scst_unregister_dev_driver( - struct scst_dev_type *dev_type) +void sgv_pool_del( + struct sgv_pool *pool) -Where: +This function deletes the corresponding SGV cache. If the cache is +shared, it will decrease its reference counter. If the reference counter +reaches 0, the cache will be destroyed. - - - -SCST commands' states - -

-There are the following states, which a SCST command passes through -during execution and which could be returned by device handler's - - -tgt_dev/ -assignment) state - - - -SCST's structures manipulation functions + void sgv_pool_flush()

-Target drivers must not directly access any fields in SCST's structures, -they must use only described below functions. - -SCST target driver manipulation functions - -scst_tgt_get_tgt_specific() and scst_tgt_set_tgt_specific() - -

-Function -void *scst_tgt_get_tgt_specific( - struct scst_tgt *tgt) +void sgv_pool_flush( + struct sgv_pool *pool) -Function -void scst_tgt_set_tgt_specific( - struct scst_tgt *tgt, - void *val) - - -Where: - - - - -SCST session manipulation functions - -scst_sess_get_tgt_specific() and scst_sess_set_tgt_specific() + void sgv_pool_set_allocator()

-Function -void *scst_sess_get_tgt_specific( - struct scst_session *sess) +void sgv_pool_set_allocator( + struct sgv_pool *pool, + struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp, void *priv), + void (*free_pages_fn)(struct scatterlist *sg, int sg_count, void *priv)); -Function -void scst_sess_set_tgt_specific( - struct scst_session *sess, - void *val) - - -Where: + - -SCST command manipulation functions +This function should return the allocated page or NULL, if no page was +allocated. -scst_cmd_atomic() + + + + + + struct scatterlist *sgv_pool_alloc()

-Function -int scst_cmd_atomic( - struct scst_cmd *cmd) +struct scatterlist *sgv_pool_alloc( + struct sgv_pool *pool, + unsigned int size, + gfp_t gfp_mask, + int flags, + int *count, + struct sgv_pool_obj **sgv, + struct scst_mem_lim *mem_lim, + void *priv) -Where: +This function allocates an SG vector from the SGV cache. It has the +following parameters: - + + + + -scst_cmd_get_session() +This function returns pointer to the resulting SG vector or NULL in case +of any error. + + void sgv_pool_free()

-Function -struct scst_session *scst_cmd_get_session( - struct scst_cmd *cmd) +void sgv_pool_free( + struct sgv_pool_obj *sgv, + struct scst_mem_lim *mem_lim) -Where: +This function frees previously allocated SG vector, referenced by SGV +cache object sgv. - - - -scst_cmd_get_resp_data_len() + void *sgv_get_priv(struct sgv_pool_obj *sgv)

-Function -unsigned int scst_cmd_get_resp_data_len( - struct scst_cmd *cmd) +void *sgv_get_priv( + struct sgv_pool_obj *sgv) -Where: +This function allows to get the allocation private data for this SGV +cache object sgv. The private data are set by sgv_pool_alloc(). - - - -scst_cmd_get_tgt_resp_flags() + void scst_init_mem_lim()

-Function -int scst_cmd_get_tgt_resp_flags( - struct scst_cmd *cmd) +void scst_init_mem_lim( + struct scst_mem_lim *mem_lim) -Where: +This function initializes memory limits structure mem_lim according to +the current system configuration. This structure should be latter used +to track and limit allocated by one or more SGV caches memory. - - -scst_cmd_get_buffer() + Runtime information and statistics.

-Function /proc/scsi_tgt/sgv. - -void *scst_cmd_get_buffer( - struct scst_cmd *cmd) - -Where: - - - - -It is recommended to use scst_cmd_get_bufflen() + Target driver qla2x00t

-Function -unsigned int scst_cmd_get_bufflen( - struct scst_cmd *cmd) - - -Where: +It consists from two parts: - -It is recommended to use scst_cmd_get_use_sg() + + + To provide support for the target mode add-on via a set of +exported callbacks + + To provide extra info and management interface in the driver's +sysfs interface (attributes target_mode_enabled, ports_database, etc.) + + To fix some problems uncovered during target mode development and +usage. + + + +The changes are relatively small (few thousands lines big patch) and local. + +The changed qla2xxx is still capable to work as initiator only. Mode, +when a host acts as initiator and target simultaneously, is supported as +well. + +Since firmware interface for 24xx+ chips is fundamentally different from +earlier versions, qla2x00t generally contains 2 separate drivers sharing +some common processing. + + Driver initialization

-Function -unsigned short scst_cmd_get_use_sg( - struct scst_cmd *cmd) - +In this function qla2x00tgt registers its callbacks in qla2xxx by +calling qla2xxx_tgt_register_driver(). Qla2xxx_tgt_register_driver() +stores pointer to the being registered callbacks in variable qla_target. -Where: +Then q2t_target_detect() calls qla2xxx_add_targets(), which calls for +each known local FC port (HBA instance) qla_target.tgt_host_action() +callback with ADD_TARGET action. Then q2t_host_action() calls +q2t_add_target() which registers SCST target for this FC port. - - +If later a new FC port is hot added, qla2x00_probe_one() will also call +for all new local ports qla_target.tgt_host_action() with ADD_TARGET +action. -It is recommended to use scst_cmd_get_data_direction() + Driver unload

-Function -scst_data_direction scst_cmd_get_data_direction( - struct scst_cmd *cmd) - +Then q2t_host_action() calls q2t_remove_target(), which unregisters the +corresponding SCST target in SCST. During unregistration SCST core calls +release() callback of tgt2x_template, which is q2t_target_release(). -Where: +Then q2t_target_release() calls q2t_target_stop(). Then +q2t_target_stop() marks this target as stopped by setting flag tgt_stop. +When this flag is set, all incoming from initiators commands are +refused. - - +Then q2t_target_stop() schedules deletion of all sessions of the target. -scst_cmd_get_status() +Then q2t_target_stop() waits until all outstanding commands finished and +sessions deleted. + +Then q2t_target_stop(), if necessary, calls qla2x00_disable_tgt_mode() +to disables target mode, which disables target mode of the corresponding +HBA and resets it. Then qla2x00_disable_tgt_mode() waits until reset +finished. + +Then q2t_target_stop() returns and then q2t_target_release() frees the +target. + + +If module qla2x00tgt is being unloaded, q2t_exit() at first takes +q2t_unreg_rwsem on writing. Taking it is necessary to make sure that +q2t_host_action() will not be active during qla2x00tgt unload. + +Then q2t_exit() calls scst_unregister_target_template() for +tgt2x_template, which then in a loop will unregister all QLA SCST targets +from SCST as described above. + + + Enabling target mode

-Functions -uint8_t scst_cmd_get_status( - struct scst_cmd *cmd) - +Then it calls qla2x00_enable_tgt_mode(), which enables target mode of +the corresponding HBA and resets it. Then qla2x00_enable_tgt_mode() +waits until reset finished. -Where: +During reset firmware initialization functions detect that target mode +is enables and initialize the firmware accordingly. - - -scst_cmd_get_masked_status() + Disabling target mode

-Functions -uint8_t scst_cmd_get_masked_status( - struct scst_cmd *cmd) - -Where: - - - - -scst_cmd_get_msg_status() + SCST sessions management

-Functions -uint8_t scst_cmd_get_msg_status( - struct scst_cmd *cmd) - +Since qla2xxx is not intended to strictly maintain database of remote +initiator FC ports as it is needed for target mode, qla2x00t uses mixed +approach for SCST sessions management, when both qla2xxx and QLogic +firmware generate events and information about currently active remote +FC ports. -Where: +Remote FC ports management also has to handle changing FC and loop IDs +after fabric events, so it needs to constantly monitor FC and loop IDs +of the registered FC ports. This is implemented by checks in +q2t_create_sess() that being registered FC port already has SCST session +and q2t_check_fcport_exist() in q2t_del_sess_work_fn(). See below for +more info. - - +Interaction with qla2xxx is implemented using tgt_fc_port_added() and +tgt_fc_port_deleted() qla_target's callbacks. -scst_cmd_get_host_status() +Callback tgt_fc_port_added() called by qla2xxx when the target driver +detects new remote FC port. Assigned to it q2t_fc_port_added() checks if +an SCST session already exists for this remote FC port and, if not, +creates it. + +Callback tgt_fc_port_deleted() called by qla2xxx when it deletes a +remote FC port from its database. Assigned to it q2t_fc_port_deleted() +checks if an SCST session already exists for this remote FC port and, if +yes, schedules it for deletion. + +Driver qla2x00tgt has 2 types of SCST sessions: local and not local. +Sessions created by q2t_fc_port_added() are not local. Local sessions +created if qla2x00tgt receives a command from remote initiator for which +there is no know remote FC port and, hence, SCST session. Local sessions +are created in tgt->sess_work (q2t_sess_work_fn()) by calling +q2t_make_local_sess(). All received from remote initiators commands for +local sessions are delayed until the sessions are created. + +To minimize affecting initiators by FC fabric events, qla2x00tgt doesn't +immediately delete SCST sessions scheduled for deletion, but instead +delay them for some time. If during this time a command from an unknown +remote initiator received, q2t_make_local_sess()/q2t_create_sess() at +first check if a session for this initiator already exists and, if yes, +undelete then reuse it after updating its s_id and loop_id to new values. + +If a session not reused during the delete delay time, then +q2t_del_sess_work_fn() asks the firmware internal database if it knows +the corresponding remote FC port. If yes, then this session is undeleted +and its s_id and loop_id updated to new values. If no, the session is +deleted. + + + Handling stuck commands

-Functions -uint16_t scst_cmd_get_host_status( - struct scst_cmd *cmd) - +In this callback all the stuck commands are forcibly finished. -Where: + - - - -scst_cmd_get_driver_status() + Debugging and troubleshooting

-Functions -uint16_t scst_cmd_get_driver_status( - struct scst_cmd *cmd) - - -Where: +Depending from amount debugging and logging facilities available, there +are 3 types of builds: - -scst_cmd_get_sense_buffer() +Switch between build modes is done by calling "make x2y", where "x" - +current build mode and "y" - desired build mode. For instance, to switch +from release to debug mode you should run "make release2debug". + + Logging levels management

-Functions -uint8_t *scst_cmd_get_sense_buffer( - struct scst_cmd *cmd) - +Reading from it you can find currently enabled logging levels. -Where: +You can change them by writing in this file, like: + +# echo "add scsi" >/proc/scsi_tgt/trace_level + +The following commands are available: - -scst_cmd_get_sense_buffer_len() +The following trace levels are common for all drivers: + + + + + +The following trace levels are additionally available for SCST core: + + + + + + Preparing a debug kernel

-Functions -int scst_cmd_get_sense_buffer_len( - struct scst_cmd *cmd) - +For that you should change in lib/Kconfig.debug or init/Kconfig +depending from your kernel version LOG_BUF_SHIFT from "12 21" to "12 25". -Where: +Then you should in your .config set CONFIG_LOG_BUF_SHIFT to 25. - - +Also, Linux kernel has a lot of helpful debug facilities, like lockdep, +which allows to catch various deadlocks, or memory allocation debugging. +It is recommended to enable them during SCST debugging. -scst_cmd_get_tag() and scst_cmd_set_tag() +The following options are recommended to be enabled (available depending +from your kernel version): CONFIG_SLUB_DEBUG, CONFIG_PRINTK_TIME, +CONFIG_MAGIC_SYSRQ, CONFIG_DEBUG_FS, CONFIG_DEBUG_KERNEL, +CONFIG_DEBUG_SHIRQ, CONFIG_DETECT_SOFTLOCKUP, CONFIG_DETECT_HUNG_TASK, +CONFIG_SLUB_DEBUG_ON, CONFIG_SLUB_STATS, CONFIG_DEBUG_PREEMPT, +CONFIG_DEBUG_RT_MUTEXES, CONFIG_DEBUG_PI_LIST, CONFIG_DEBUG_SPINLOCK, +CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_LOCK_ALLOC, CONFIG_PROVE_LOCKING, +CONFIG_LOCKDEP, CONFIG_LOCK_STAT, CONFIG_DEBUG_SPINLOCK_SLEEP, +CONFIG_STACKTRACE, CONFIG_DEBUG_BUGVERBOSE, CONFIG_DEBUG_VM, +CONFIG_DEBUG_VIRTUAL, CONFIG_DEBUG_WRITECOUNT, CONFIG_DEBUG_MEMORY_INIT, +CONFIG_DEBUG_LIST, CONFIG_DEBUG_SG, CONFIG_DEBUG_NOTIFIERS, +CONFIG_FRAME_POINTER, CONFIG_FAULT_INJECTION, CONFIG_FAILSLAB, +CONFIG_FAIL_PAGE_ALLOC, CONFIG_FAIL_MAKE_REQUEST, +CONFIG_FAIL_IO_TIMEOUT, CONFIG_FAULT_INJECTION_DEBUG_FS, +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER. -

Function -uint32_t scst_cmd_get_tag( - struct scst_cmd *cmd) - - -Function -void scst_cmd_set_tag( - struct scst_cmd *cmd, - uint32_t tag) - - -Where: - - - - -scst_cmd_get_tgt_specific() and scst_cmd_get_tgt_specific_lock() + Preparing logging subsystem

-Functions -void *scst_cmd_get_tgt_specific( - struct scst_cmd *cmd) - - - -void *scst_cmd_get_tgt_specific_lock( - struct scst_cmd *cmd) - - -Where: +It is recommended that you system logger daemon on the target configured: - To store kernel logs in separate files on the fastest disk you +have. It will be better if this disk is dedicated for logging or, at +least, doesn't contain your LUNs data. + + To write the kernel logs to the disk in asynchronous manner, i.e. +without calling fsync() after each written message. Usually, you can +achieve it, if you add a '-' sign before the corresponding file path in +your syslog daemon conf file, like: + +kern.* -/var/log/kern.log + -scst_cmd_set_tgt_specific() and scst_cmd_set_tgt_specific_lock() + Decoding OOPS messages

-Functions -void *scst_cmd_set_tgt_specific( - struct scst_cmd *cmd, - void *val) +[<ffffffff88646174>&rsqb :iscsi_scst:iscsi_extracheck_is_rd_thread+0x94/0xb0 +You can decode it by: + -void *scst_cmd_set_tgt_specific_lock( - struct scst_cmd *cmd, - void *val) +$ gdb iscsi-scst.ko +(gdb) l *iscsi_scst:iscsi_extracheck_is_rd_thread+0x94 -Where: +For that the corresponding module (iscsi-scst.ko) should be build with +debug info. But modules not always have debug info built-in. To +workaround it you can add "-g" flag in the corresponding Makefile +(without changing anything else!) or enable in .config using "make +menuconfig" building kernel with debug info. Then rebuild only the .o +file you need. - - - -scst_cmd_get_data_buff_alloced() and scst_cmd_set_data_buff_alloced() - -

-Function -int scst_cmd_get_data_buff_alloced( - struct scst_cmd *cmd) +$ make mm/filemap.o +... +$ gdb mm/filemap.o -Function -void scst_cmd_set_data_buff_alloced( - struct scst_cmd *cmd) - - -Where: - - - - -scst_cmd_set_expected(), scst_cmd_is_expected_set(), -scst_cmd_get_expected_data_direction() and -scst_cmd_get_expected_transfer_len() - -

-Function -void scst_cmd_set_expected( - struct scst_cmd *cmd, - scst_data_direction expected_data_direction, - unsigned int expected_transfer_len) - - -Function -int scst_cmd_is_expected_set( - struct scst_cmd *cmd) - - -Function -scst_data_direction scst_cmd_get_expected_data_direction( - struct scst_cmd *cmd) - - -Function -unsigned int scst_cmd_get_expected_transfer_len( - struct scst_cmd *cmd) - - -Where: - - - - -scst_get_buf_first(), scst_get_buf_next(), -scst_put_buf() and scst_get_buf_count() - -

-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 -int scst_get_buf_first( - struct scst_cmd *cmd, - uint8_t **buf) - - -Where: - - - - -Returns the length of the chunk of data for success, 0 for the end of -data, negative error code otherwise. - -Function -int scst_get_buf_next( - struct scst_cmd *cmd, - uint8_t **buf) - - -Where: - - - - -Returns the length of the chunk of data for success, 0 for the end of -data, negative error code otherwise. - -Function -void scst_put_buf( - struct scst_cmd *cmd, - uint8_t *buf) - - -Where: - - - - -Function -int scst_get_buf_count( - struct scst_cmd *cmd) - - -Where: - - - - -SCST task management commands manipulation functions - -scst_mgmt_cmd_get_tgt_specific() - -

-Function -void *scst_mgmt_cmd_get_tgt_specific( - struct scst_mgmt_cmd *mcmd) - - -Where: - - - - -scst_mgmt_cmd_get_status() - -

-Functions -void *scst_mgmt_cmd_get_status( - struct scst_mgmt_cmd *mcmd) - - -Where: - - - - -The following status values are possible: - - - - SCST_MGMT_STATUS_SUCCESS - the task management command completed -successfully - - SCST_MGMT_STATUS_FAILED - the task management command failed. - - - -Miscellaneous functions - -scst_find_cmd_by_tag() - -

-Function -struct scst_cmd *scst_find_cmd_by_tag( - struct scst_session *sess, - uint32_t tag) - - -Where: - - - - -Returns found command or NULL otherwise. - -scst_find_cmd() - -

-Function -struct scst_cmd *scst_find_cmd( - struct scst_session *sess, - void *data, - int (*cmp_fn)(struct scst_cmd *cmd, void *data)) - - -Where: - - - - - - - - -Returns found command or NULL otherwise. - -scst_get_cdb_info() - -

-Function -int scst_get_cdb_info( - const uint8_t *cdb_p, - int dev_type, - struct scst_info_cdb *info_p) - - -Where: - - - - - -Returns 0 on success, -1 otherwise. - -scst_to_dma_dir() - -

-Function -int scst_to_dma_dir( - int scst_dir) - - -Where: - - - - -Returns the corresponding scst_is_cmd_local() - -

-Function -int scst_is_cmd_local( - struct scst_cmd *cmd) - - -Where: - - - - -Returns 1, if the command's CDB is locally handled by SCST or 0 -otherwise - -scst_register_virtual_device() and scst_unregister_virtual_device() - -

-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 -int scst_register_virtual_device( - struct scst_dev_type *dev_handler) - - -Where: - - - - -Returns assigned to the device ID on success, or negative value otherwise. - -Function -void scst_unregister_virtual_device( - int id) - - -Where: - - - - -scst_add_threads() and scst_del_threads() - -

-These functions allows to add or delete some SCST threads. For example, -if -int scst_add_threads( - int num) - - -Where: - - - - -Returns 0 on success, error code otherwise. - -Function -void scst_del_threads( - int num) - - -Where: - - - - -scst_proc_get_tgt_root() - -

-Function -struct proc_dir_entry *scst_proc_get_tgt_root( - struct scst_tgt_template *vtt) - - -Where: - - - - -Returns proc_dir_entry on success, NULL otherwise. - -scst_proc_get_dev_type_root() - -

-Function -struct proc_dir_entry *scst_proc_get_dev_type_root( - struct scst_dev_type *dtt) - - -Where: - - - - -Returns proc_dir_entry on success, NULL otherwise. -

diff --git a/doc/sgv_cache.sgml b/doc/sgv_cache.sgml deleted file mode 100644 index 4d6240031..000000000 --- a/doc/sgv_cache.sgml +++ /dev/null @@ -1,335 +0,0 @@ - - -
- - -SCST SGV cache description - - - - Vladislav Bolkhovitin - - -Version 2.1.0 - - - -Introduction - -

-SCST SGV cache is a memory management subsystem in SCST. One can call it -a "memory pool", but Linux kernel already have a mempool interface, -which serves different purposes. SGV cache provides to SCST core, target -drivers and backend dev handlers facilities to allocate, build and cache -SG vectors for data buffers. The main advantage of it is the caching -facility, when it doesn't free to the system each vector, which is not -used anymore, but keeps it for a while (possibly indefinitely) to let it -be reused by the next consecutive command. This allows to: - - - - Reduce commands processing latencies and, hence, improve performance; - - Make commands processing latencies predictable, which is essential - for RT applications. - - - -The freed SG vectors are kept by the SGV cache either for some (possibly -indefinite) time, or, optionally, until the system needs more memory and -asks to free some using the set_shrinker() interface. Also the SGV cache -allows to: - - - - Cluster pages together. "Cluster" means merging adjacent pages in a -single SG entry. It allows to have less SG entries in the resulting SG -vector, hence improve performance handling it as well as allow to -work with bigger buffers on hardware with limited SG capabilities. - - Set custom page allocator functions. For instance, scst_user device -handler uses this facility to eliminate unneeded mapping/unmapping of -user space pages and avoid unneeded IOCTL calls for buffers allocations. -In fileio_tgt application, which uses a regular malloc() function to -allocate data buffers, this facility allows ~30% less CPU load and -considerable performance increase. - - Prevent each initiator or all initiators altogether to allocate too -much memory and DoS the target. Consider 10 initiators, which can have -access to 10 devices each. Any of them can queue up to 64 commands, each -can transfer up to 1MB of data. So, all of them in a peak can allocate -up to 10*10*64 = ~6.5GB of memory for data buffers. This amount must be -limited somehow and the SGV cache performs this function. - - - - Implementation - -

-From implementation POV the SGV cache is a simple extension of the kmem -cache. It can work in 2 modes: - - - - With fixed size buffers. - - With a set of power 2 size buffers. In this mode each SGV cache -(struct sgv_pool) has SGV_POOL_ELEMENTS (11 currently) of kmem caches. -Each of those kmem caches keeps SGV cache objects (struct sgv_pool_obj) -corresponding to SG vectors with size of order X pages. For instance, -request to allocate 4 pages will be served from kmem cache[2&rsqb, since the -order of the of number of requested pages is 2. If later request to -allocate 11KB comes, the same SG vector with 4 pages will be reused (see -below). This mode is in average allows less memory overhead comparing -with the fixed size buffers mode. - - - -Consider how the SGV cache works in the set of buffers mode. When a -request to allocate new SG vector comes, sgv_pool_alloc() via -sgv_get_obj() checks if there is already a cached vector with that -order. If yes, then that vector will be reused and its length, if -necessary, will be modified to match the requested size. In the above -example request for 11KB buffer, 4 pages vector will be reused and -modified using trans_tbl to contain 3 pages and the last entry will be -modified to contain the requested length - 2*PAGE_SIZE. If there is no -cached object, then a new sgv_pool_obj will be allocated from the -corresponding kmem cache, chosen by the order of number of requested -pages. Then that vector will be filled by pages and returned. - -In the fixed size buffers mode the SGV cache works similarly, except -that it always allocate buffer with the predefined fixed size. I.e. -even for 4K request the whole buffer with predefined size, say, 1MB, -will be used. - -In both modes, if size of a request exceeds the maximum allowed for -caching buffer size, the requested buffer will be allocated, but not -cached. - -Freed cached sgv_pool_obj objects are actually freed to the system -either by the purge work, which is scheduled once in 60 seconds, or in -sgv_shrink() called by system, when it's asking for memory. - - Interface - - sgv_pool *sgv_pool_create() - -

- -struct sgv_pool *sgv_pool_create( - const char *name, - enum sgv_clustering_types clustered, int single_alloc_pages, - bool shared, int purge_interval) - - -This function creates and initializes an SGV cache. It has the following -arguments: - - - - - - - - 0, then the SGV cache will work in the - fixed size buffers mode. In this case single_alloc_pages sets the - size of each buffer in pages. - - - -Returns the resulting SGV cache or NULL in case of any error. - - void sgv_pool_del() - -

- -void sgv_pool_del( - struct sgv_pool *pool) - - -This function deletes the corresponding SGV cache. If the cache is -shared, it will decrease its reference counter. If the reference counter -reaches 0, the cache will be destroyed. - - void sgv_pool_flush() - -

- -void sgv_pool_flush( - struct sgv_pool *pool) - - -This function flushes, i.e. frees, all the cached entries in the SGV -cache. - - void sgv_pool_set_allocator() - -

- -void sgv_pool_set_allocator( - struct sgv_pool *pool, - struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp, void *priv), - void (*free_pages_fn)(struct scatterlist *sg, int sg_count, void *priv)); - - -This function allows to set for the SGV cache a custom pages allocator. For -instance, scst_user uses such function to supply to the cache mapped from -user space pages. - - - - - -This function should return the allocated page or NULL, if no page was -allocated. - - - - - - - struct scatterlist *sgv_pool_alloc() - -

- -struct scatterlist *sgv_pool_alloc( - struct sgv_pool *pool, - unsigned int size, - gfp_t gfp_mask, - int flags, - int *count, - struct sgv_pool_obj **sgv, - struct scst_mem_lim *mem_lim, - void *priv) - - -This function allocates an SG vector from the SGV cache. It has the -following parameters: - - - - - - - - - -This function returns pointer to the resulting SG vector or NULL in case -of any error. - - void sgv_pool_free() - -

- -void sgv_pool_free( - struct sgv_pool_obj *sgv, - struct scst_mem_lim *mem_lim) - - -This function frees previously allocated SG vector, referenced by SGV -cache object sgv. - - void *sgv_get_priv(struct sgv_pool_obj *sgv) - -

- -void *sgv_get_priv( - struct sgv_pool_obj *sgv) - - -This function allows to get the allocation private data for this SGV -cache object sgv. The private data are set by sgv_pool_alloc(). - - void scst_init_mem_lim() - -

- -void scst_init_mem_lim( - struct scst_mem_lim *mem_lim) - - -This function initializes memory limits structure mem_lim according to -the current system configuration. This structure should be latter used -to track and limit allocated by one or more SGV caches memory. - - - Runtime information and statistics. - -

-Runtime information and statistics is available in /sys/kernel/scst_tgt/sgv. - -