mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
- Make internal comments be in the kernel's style
- Minor cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1603 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -3,6 +3,8 @@ To be done
|
||||
|
||||
- See http://scst.sourceforge.net/contributing.html
|
||||
|
||||
- Remove cmd->data_len
|
||||
|
||||
- Reimplement VDISK handler with usage of async. read/write operations
|
||||
(in order to avoid unnecessary context switches) and direct access to
|
||||
the page cache (in order to avoid data copy between it and internal
|
||||
@@ -27,12 +29,10 @@ To be done
|
||||
|
||||
- Small ToDo's spread all over the code.
|
||||
|
||||
- Investigate possible missed emulated UA cases.
|
||||
|
||||
- Additional ability for target drivers to ask for command's retry also
|
||||
after xmit_response() and rdy_to_xfer() returned (for example, if a
|
||||
command was successfully sent to the target card, but later it was
|
||||
returned by the card with BUSY completion status).
|
||||
|
||||
- Advanced SCSI commands support: COPY, EXTENDED COPY, PERSISTENT
|
||||
RESERVE IN/OUT, third party RESERVE, etc.
|
||||
- Advanced SCSI commands support: COPY, EXTENDED COPY, third party
|
||||
RESERVE, etc.
|
||||
|
||||
@@ -552,24 +552,11 @@ struct scst_aen;
|
||||
typedef enum dma_data_direction scst_data_direction;
|
||||
|
||||
/*
|
||||
* Scsi_Target_Template: defines what functions a target driver will
|
||||
* have to provide in order to work with the target mid-level.
|
||||
* MUST HAVEs define functions that are expected to be in order to work.
|
||||
* OPTIONAL says that there is a choice.
|
||||
* SCST target template: defines target driver's parameters and callback
|
||||
* functions.
|
||||
*
|
||||
* Also, pay attention to the fact that a command is BLOCKING or NON-BLOCKING.
|
||||
* NON-BLOCKING means that a function returns immediately and will not wait
|
||||
* for actual data transfer to finish. Blocking in such command could have
|
||||
* negative impact on overall system performance. If blocking is necessary,
|
||||
* it is worth to consider creating dedicated thread(s) in target driver, to
|
||||
* which the commands would be passed and which would perform blocking
|
||||
* operations instead of SCST.
|
||||
*
|
||||
* If the function allowed to sleep or not is determined by its last
|
||||
* argument, which is true, if sleeping is not allowed. In this case,
|
||||
* if the function requires sleeping, it can return
|
||||
* SCST_TGT_RES_NEED_THREAD_CTX, and it will be recalled in the thread context,
|
||||
* where sleeping is allowed.
|
||||
* MUST HAVEs define functions that are expected to be defined in order to
|
||||
* work. OPTIONAL says that there is a choice.
|
||||
*/
|
||||
struct scst_tgt_template {
|
||||
/* public: */
|
||||
@@ -968,6 +955,13 @@ enum scst_dev_type_threads_pool_type {
|
||||
SCST_THREADS_POOL_TYPE_INVALID,
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST dev handler template: defines dev handler's parameters and callback
|
||||
* functions.
|
||||
*
|
||||
* MUST HAVEs define functions that are expected to be defined in order to
|
||||
* work. OPTIONAL says that there is a choice.
|
||||
*/
|
||||
struct scst_dev_type {
|
||||
/* SCSI type of the supported device. MUST HAVE */
|
||||
int type;
|
||||
@@ -1216,6 +1210,9 @@ struct scst_dev_type {
|
||||
struct completion devt_kobj_release_compl;
|
||||
};
|
||||
|
||||
/*
|
||||
* An SCST target, analog of SCSI target port.
|
||||
*/
|
||||
struct scst_tgt {
|
||||
/* List of remote sessions per target, protected by scst_mutex */
|
||||
struct list_head sess_list;
|
||||
@@ -1230,7 +1227,7 @@ struct scst_tgt {
|
||||
/*
|
||||
* Device ACG groups
|
||||
*/
|
||||
struct list_head acg_list;
|
||||
struct list_head tgt_acg_list;
|
||||
|
||||
/*
|
||||
* Maximum SG table size. Needed here, since different cards on the
|
||||
@@ -1324,6 +1321,9 @@ struct scst_ext_latency_stat {
|
||||
|
||||
#endif /* CONFIG_SCST_MEASURE_LATENCY */
|
||||
|
||||
/*
|
||||
* SCST session, analog of SCSI I_T nexus
|
||||
*/
|
||||
struct scst_session {
|
||||
/*
|
||||
* Initialization phase, one of SCST_SESS_IPH_* constants, protected by
|
||||
@@ -1440,12 +1440,15 @@ struct scst_session {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to control commands' queuing and threads pool processing the queue
|
||||
*/
|
||||
struct scst_cmd_threads {
|
||||
spinlock_t cmd_list_lock;
|
||||
struct list_head active_cmd_list;
|
||||
struct list_head active_cmd_list; /* commands queue */
|
||||
wait_queue_head_t cmd_list_waitQ;
|
||||
|
||||
struct io_context *io_context;
|
||||
struct io_context *io_context; /* IO context of the threads pool */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
/*
|
||||
@@ -1455,12 +1458,15 @@ struct scst_cmd_threads {
|
||||
struct kref *io_context_kref;
|
||||
#endif
|
||||
|
||||
int nr_threads;
|
||||
struct list_head threads_list;
|
||||
int nr_threads; /* number of processing threads */
|
||||
struct list_head threads_list; /* processing threads */
|
||||
|
||||
struct list_head lists_list_entry;
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST command, analog of I_T_L_Q nexus or task
|
||||
*/
|
||||
struct scst_cmd {
|
||||
/* List entry for below *_cmd_threads */
|
||||
struct list_head cmd_list_entry;
|
||||
@@ -1756,6 +1762,9 @@ struct scst_cmd {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Parameters for SCST management commands
|
||||
*/
|
||||
struct scst_rx_mgmt_params {
|
||||
int fn;
|
||||
uint64_t tag;
|
||||
@@ -1769,6 +1778,9 @@ struct scst_rx_mgmt_params {
|
||||
unsigned char cmd_sn_set;
|
||||
};
|
||||
|
||||
/*
|
||||
* A stub structure to link an management command and affected regular commands
|
||||
*/
|
||||
struct scst_mgmt_cmd_stub {
|
||||
struct scst_mgmt_cmd *mcmd;
|
||||
|
||||
@@ -1779,6 +1791,9 @@ struct scst_mgmt_cmd_stub {
|
||||
unsigned int done_counted:1;
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST task management structure
|
||||
*/
|
||||
struct scst_mgmt_cmd {
|
||||
/* List entry for *_mgmt_cmd_list */
|
||||
struct list_head mgmt_cmd_list_entry;
|
||||
@@ -1788,7 +1803,7 @@ struct scst_mgmt_cmd {
|
||||
/* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
|
||||
int state;
|
||||
|
||||
int fn;
|
||||
int fn; /* task management function */
|
||||
|
||||
unsigned int completed:1; /* set, if the mcmd is completed */
|
||||
/* Set if device(s) should be unblocked after mcmd's finish */
|
||||
@@ -1832,6 +1847,9 @@ struct scst_mgmt_cmd {
|
||||
void *tgt_priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST device
|
||||
*/
|
||||
struct scst_device {
|
||||
struct scst_dev_type *handler; /* corresponding dev handler */
|
||||
|
||||
@@ -1981,7 +1999,8 @@ struct scst_async_io_context_keeper {
|
||||
};
|
||||
|
||||
/*
|
||||
* Used to store per-session specific device information
|
||||
* Used to store per-session specific device information, analog of
|
||||
* SCSI I_T_L nexus.
|
||||
*/
|
||||
struct scst_tgt_dev {
|
||||
/* List entry in sess->sess_tgt_dev_list_hash */
|
||||
@@ -2125,7 +2144,7 @@ struct scst_acg {
|
||||
/* List of attached acn's, protected by scst_mutex */
|
||||
struct list_head acn_list;
|
||||
|
||||
/* List entry in tgt acg_list */
|
||||
/* List entry in acg_lists */
|
||||
struct list_head acg_list_entry;
|
||||
|
||||
/* Name of this acg */
|
||||
@@ -2218,133 +2237,34 @@ static inline int scst_register_target_template(struct scst_tgt_template *vtt)
|
||||
return __scst_register_target_template(vtt, SCST_INTERFACE_VERSION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregisters target template
|
||||
*/
|
||||
void scst_unregister_target_template(struct scst_tgt_template *vtt);
|
||||
|
||||
/*
|
||||
* Registers and returns target adapter
|
||||
* Returns new target structure on success or NULL otherwise.
|
||||
*
|
||||
* If parameter "target_name" isn't NULL, then security group with name
|
||||
* "Default_##target_name", if created, will be used as the default
|
||||
* instead of "Default" one for all initiators not assigned to any other group.
|
||||
*/
|
||||
struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
const char *target_name);
|
||||
|
||||
/*
|
||||
* Unregisters target adapter
|
||||
*/
|
||||
void scst_unregister(struct scst_tgt *tgt);
|
||||
|
||||
/*
|
||||
* Registers and returns a session
|
||||
*
|
||||
* Returns new session on success or NULL otherwise
|
||||
*
|
||||
* Parameters:
|
||||
* tgt - target
|
||||
* atomic - true, if the function called in the atomic context. If false,
|
||||
* this function will block until the session registration is completed.
|
||||
* initiator_name - remote initiator's name, any NULL-terminated string,
|
||||
* e.g. iSCSI name, which used as the key to found appropriate access
|
||||
* control group. Could be NULL, then the default target's LUNs are used.
|
||||
* data - any target driver supplied data
|
||||
* result_fn - pointer to the function that will be
|
||||
* asynchronously called when session initialization finishes.
|
||||
* Can be NULL. Parameters:
|
||||
* - sess - session
|
||||
* - data - target driver supplied to scst_register_session() data
|
||||
* - result - session initialization result, 0 on success or
|
||||
* appropriate error code otherwise
|
||||
*
|
||||
* Note: A session creation and initialization is a complex task,
|
||||
* which requires sleeping state, so it can't be fully done
|
||||
* in interrupt context. Therefore the "bottom half" of it, if
|
||||
* scst_register_session() is called from atomic context, will be
|
||||
* done in SCST thread context. In this case scst_register_session()
|
||||
* will return not completely initialized session, but the target
|
||||
* driver can supply commands to this session via scst_rx_cmd().
|
||||
* Those commands processing will be delayed inside SCST until
|
||||
* the session initialization is finished, then their processing
|
||||
* will be restarted. The target driver will be notified about
|
||||
* finish of the session initialization by function result_fn().
|
||||
* On success the target driver could do nothing, but if the
|
||||
* initialization fails, the target driver must ensure that
|
||||
* no more new commands being sent or will be sent to SCST after
|
||||
* result_fn() returns. All already sent to SCST commands for
|
||||
* failed session will be returned in xmit_response() with BUSY status.
|
||||
* In case of failure the driver shall call scst_unregister_session()
|
||||
* inside result_fn(), it will NOT be called automatically.
|
||||
*/
|
||||
struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
|
||||
const char *initiator_name, void *data,
|
||||
void (*result_fn) (struct scst_session *sess, void *data, int result));
|
||||
|
||||
/*
|
||||
* Unregisters a session.
|
||||
* Parameters:
|
||||
* sess - session to be unregistered
|
||||
* wait - if true, instructs to wait until all commands, which
|
||||
* currently is being executed and belonged to the session, finished.
|
||||
* Otherwise, target driver should be prepared to receive
|
||||
* xmit_response() for the session's command after
|
||||
* scst_unregister_session() returns.
|
||||
* unreg_done_fn - pointer to the function that will be
|
||||
* asynchronously called when the last session's command finishes and
|
||||
* the session is about to be completely freed. Can be NULL.
|
||||
* Parameter:
|
||||
* - sess - session
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* - All outstanding commands will be finished regularly. After
|
||||
* scst_unregister_session() returned no new commands must be sent to
|
||||
* SCST via scst_rx_cmd().
|
||||
*
|
||||
* - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is
|
||||
* called in paralell with scst_unregister_session().
|
||||
*
|
||||
* - Can be called before result_fn() of scst_register_session() called,
|
||||
* i.e. during the session registration/initialization.
|
||||
*
|
||||
* - It is highly recommended to call scst_unregister_session() as soon as it
|
||||
* gets clear that session will be unregistered and not to wait until all
|
||||
* related commands finished. This function provides the wait functionality,
|
||||
* but it also starts recovering stuck commands, if there are any.
|
||||
* Otherwise, your target driver could wait for those commands forever.
|
||||
*/
|
||||
void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess));
|
||||
|
||||
/*
|
||||
* Registers dev handler driver.
|
||||
* Returns 0 on success or appropriate error code otherwise.
|
||||
*
|
||||
* Note: *dev_type must be static!
|
||||
*/
|
||||
int __scst_register_dev_driver(struct scst_dev_type *dev_type,
|
||||
const char *version);
|
||||
static inline int scst_register_dev_driver(struct scst_dev_type *dev_type)
|
||||
{
|
||||
return __scst_register_dev_driver(dev_type, SCST_INTERFACE_VERSION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregisters dev handler driver
|
||||
*/
|
||||
void scst_unregister_dev_driver(struct scst_dev_type *dev_type);
|
||||
|
||||
int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
|
||||
const char *version);
|
||||
/*
|
||||
* Registers dev handler driver for virtual devices (eg VDISK).
|
||||
* Returns 0 on success or appropriate error code otherwise.
|
||||
*
|
||||
* Note: *dev_type must be static!
|
||||
*/
|
||||
int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
|
||||
const char *version);
|
||||
static inline int scst_register_virtual_dev_driver(
|
||||
struct scst_dev_type *dev_type)
|
||||
{
|
||||
@@ -2352,38 +2272,11 @@ static inline int scst_register_virtual_dev_driver(
|
||||
SCST_INTERFACE_VERSION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregisters dev handler driver for virtual devices
|
||||
*/
|
||||
void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type);
|
||||
|
||||
/*
|
||||
* Creates and sends new command to SCST.
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same sess. Returns the command on success or NULL otherwise
|
||||
*/
|
||||
struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, const uint8_t *cdb,
|
||||
int cdb_len, int atomic);
|
||||
|
||||
/*
|
||||
* Notifies SCST that the driver finished its part of the command
|
||||
* initialization, and the command is ready for execution.
|
||||
* The second argument sets preferred command execition context.
|
||||
* See SCST_CONTEXT_* constants for details.
|
||||
*
|
||||
* !!IMPORTANT!!
|
||||
*
|
||||
* If cmd->set_sn_on_restart_cmd not set, this function, as well as
|
||||
* scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be
|
||||
* called simultaneously for the same session (more precisely,
|
||||
* for the same session/LUN, i.e. tgt_dev), i.e. they must be
|
||||
* somehow externally serialized. This is needed to have lock free fast path in
|
||||
* scst_cmd_set_sn(). For majority of targets those functions are naturally
|
||||
* serialized by the single source of commands. Only iSCSI immediate commands
|
||||
* with multiple connections per session seems to be an exception. For it, some
|
||||
* mutex/lock shall be used for the serialization.
|
||||
*/
|
||||
void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
@@ -2394,7 +2287,7 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
* should be called. The second argument sets preferred command execition
|
||||
* context. See SCST_CONTEXT_* constants for details.
|
||||
*
|
||||
* See also scst_cmd_init_done() comment for the serialization requirements.
|
||||
* See comment for scst_cmd_init_done() for the serialization requirements.
|
||||
*/
|
||||
static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context, int set_sn)
|
||||
@@ -2404,45 +2297,15 @@ static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
|
||||
scst_cmd_init_done(cmd, pref_context);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifies SCST that the driver finished its part of the command's
|
||||
* preprocessing and it is ready for further processing.
|
||||
* The second argument sets data receiving completion status
|
||||
* (see SCST_PREPROCESS_STATUS_* constants for details)
|
||||
* The third argument sets preferred command execition context
|
||||
* (see SCST_CONTEXT_* constants for details).
|
||||
*
|
||||
* See also scst_cmd_init_done() comment for the serialization requirements.
|
||||
*/
|
||||
void scst_restart_cmd(struct scst_cmd *cmd, int status,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
/*
|
||||
* Notifies SCST that the driver received all the necessary data
|
||||
* and the command is ready for further processing.
|
||||
* The second argument sets data receiving completion status
|
||||
* (see SCST_RX_STATUS_* constants for details)
|
||||
* The third argument sets preferred command execition context
|
||||
* (see SCST_CONTEXT_* constants for details)
|
||||
*/
|
||||
void scst_rx_data(struct scst_cmd *cmd, int status,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
/*
|
||||
* Notifies SCST that the driver sent the response and the command
|
||||
* can be freed now. Don't forget to set the delivery status, if it
|
||||
* isn't success, using scst_set_delivery_status() before calling
|
||||
* this function. The third argument sets preferred command execition
|
||||
* context (see SCST_CONTEXT_* constants for details)
|
||||
*/
|
||||
void scst_tgt_cmd_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
/*
|
||||
* Creates new management command sends it for execution.
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same sess. Returns 0 for success, error code otherwise.
|
||||
*/
|
||||
int scst_rx_mgmt_fn(struct scst_session *sess,
|
||||
const struct scst_rx_mgmt_params *params);
|
||||
|
||||
@@ -2495,74 +2358,24 @@ static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn,
|
||||
return scst_rx_mgmt_fn(sess, ¶ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* Provides various info about command's CDB.
|
||||
*
|
||||
* Returns: 0 on success, <0 if command is unknown, >0 if command is invalid.
|
||||
*/
|
||||
int scst_get_cdb_info(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Set error SCSI status in the command and prepares it for returning it.
|
||||
*
|
||||
* Returns 0 on success, error code otherwise.
|
||||
*/
|
||||
int scst_set_cmd_error_status(struct scst_cmd *cmd, int status);
|
||||
|
||||
/*
|
||||
* Set error in the command and fill the sense buffer.
|
||||
*
|
||||
* Returns 0 on success, error code otherwise.
|
||||
*/
|
||||
int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Sets BUSY or TASK QUEUE FULL status
|
||||
*/
|
||||
void scst_set_busy(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Check if sense in the sense buffer, if any, in the correct format. If not,
|
||||
* convert it to the correct format.
|
||||
*/
|
||||
void scst_check_convert_sense(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Sets initial Unit Attention for sess, replacing default scst_sense_reset_UA
|
||||
*/
|
||||
void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Notifies SCST core that dev changed its capacity
|
||||
*/
|
||||
void scst_capacity_data_changed(struct scst_device *dev);
|
||||
|
||||
/*
|
||||
* Finds a command based on the supplied tag comparing it with one
|
||||
* that previously set by scst_cmd_set_tag().
|
||||
* Returns the command on success or NULL otherwise
|
||||
*/
|
||||
struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag);
|
||||
|
||||
/*
|
||||
* Finds a command based on user supplied data and comparision
|
||||
* callback function, that should return true, if the command is found.
|
||||
* Returns the command on success or NULL otherwise
|
||||
*/
|
||||
struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
|
||||
int (*cmp_fn) (struct scst_cmd *cmd,
|
||||
void *data));
|
||||
|
||||
/*
|
||||
* Translates SCST's data direction to DMA one from backend storage
|
||||
* perspective.
|
||||
*/
|
||||
enum dma_data_direction scst_to_dma_dir(int scst_dir);
|
||||
|
||||
/*
|
||||
* Translates SCST data direction to DMA data direction from the perspective
|
||||
* of the target device.
|
||||
*/
|
||||
enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
|
||||
|
||||
/*
|
||||
@@ -2589,24 +2402,8 @@ static inline bool scst_is_ua_command(struct scst_cmd *cmd)
|
||||
return (cmd->op_flags & SCST_SKIP_UA) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers a virtual device.
|
||||
* Parameters:
|
||||
* dev_type - the device's device handler
|
||||
* dev_name - the new device name, NULL-terminated string. Must be uniq
|
||||
* among all virtual devices in the system. The value isn't
|
||||
* copied, only the reference is stored, so the value must
|
||||
* remain valid during the device lifetime.
|
||||
* Returns assinged to the device ID on success, or negative value otherwise
|
||||
*/
|
||||
int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
const char *dev_name);
|
||||
|
||||
/*
|
||||
* Unegisters a virtual device.
|
||||
* Parameters:
|
||||
* id - the device's ID, returned by the registration function
|
||||
*/
|
||||
void scst_unregister_virtual_device(int id);
|
||||
|
||||
/*
|
||||
@@ -2949,9 +2746,6 @@ static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val)
|
||||
cmd->tgt_priv = val;
|
||||
}
|
||||
|
||||
void *scst_cmd_get_tgt_priv_lock(struct scst_cmd *cmd);
|
||||
void scst_cmd_set_tgt_priv_lock(struct scst_cmd *cmd, void *val);
|
||||
|
||||
/*
|
||||
* Get/Set functions for tgt_need_alloc_data_buf flag
|
||||
*/
|
||||
@@ -3192,12 +2986,6 @@ static inline void scst_set_aen_delivery_status(struct scst_aen *aen,
|
||||
aen->delivery_status = status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifies SCST that the driver has sent the AEN and it
|
||||
* can be freed now. Don't forget to set the delivery status, if it
|
||||
* isn't success, using scst_set_aen_delivery_status() before calling
|
||||
* this function.
|
||||
*/
|
||||
void scst_aen_done(struct scst_aen *aen);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
@@ -3264,10 +3052,6 @@ enum scst_sg_copy_dir {
|
||||
SCST_SG_COPY_TO_TARGET
|
||||
};
|
||||
|
||||
/*
|
||||
* Copies data between cmd->tgt_sg and cmd->sg in direction defined by
|
||||
* copy_dir parameter.
|
||||
*/
|
||||
void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
|
||||
|
||||
/*
|
||||
@@ -3368,54 +3152,15 @@ static inline int cancel_delayed_work_sync(struct work_struct *work)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Suspends and resumes any activity.
|
||||
* Function scst_suspend_activity() doesn't return 0, until there are any
|
||||
* active commands (state after SCST_CMD_STATE_INIT). If "interruptible"
|
||||
* is true, it returns after SCST_SUSPENDING_TIMEOUT or if it was interrupted
|
||||
* by a signal with the coresponding error status < 0. If "interruptible"
|
||||
* is false, it will wait virtually forever.
|
||||
*
|
||||
* New arriving commands stay in that state until scst_resume_activity()
|
||||
* is called.
|
||||
*/
|
||||
int scst_suspend_activity(bool interruptible);
|
||||
void scst_resume_activity(void);
|
||||
|
||||
/*
|
||||
* Main SCST commands processing routing. Must be used only by dev handlers.
|
||||
* Argument atomic is true if function called in atomic context.
|
||||
*/
|
||||
void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic);
|
||||
|
||||
/*
|
||||
* SCST commands processing routine, which should be called by dev handler
|
||||
* after its parse() callback returned SCST_CMD_STATE_STOP. Arguments
|
||||
* the same as for scst_process_active_cmd().
|
||||
*/
|
||||
void scst_post_parse_process_active_cmd(struct scst_cmd *cmd, bool atomic);
|
||||
|
||||
/*
|
||||
* Checks if command can be executed (reservations, etc.) or there are local
|
||||
* events, like pending UAs. Returns < 0 if command must be aborted, > 0 if
|
||||
* there is an event and command should be immediately completed, or 0
|
||||
* otherwise.
|
||||
*
|
||||
* !! Dev handlers implementing exec() callback must call this function there !!
|
||||
* !! just before the actual command's execution !!
|
||||
*/
|
||||
int scst_check_local_events(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Returns the next state of the SCSI target state machine in case if command's
|
||||
* completed abnormally.
|
||||
*/
|
||||
int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Sets state of the SCSI target state machine in case if command's completed
|
||||
* abnormally.
|
||||
*/
|
||||
void scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd);
|
||||
|
||||
struct scst_trace_log {
|
||||
@@ -3423,10 +3168,6 @@ struct scst_trace_log {
|
||||
const char *token;
|
||||
};
|
||||
|
||||
/*
|
||||
* Main SCST mutex. All targets, devices and dev_types management is done
|
||||
* under this mutex.
|
||||
*/
|
||||
extern struct mutex scst_mutex;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -3489,7 +3230,6 @@ struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root,
|
||||
|
||||
#else /* CONFIG_SCST_PROC */
|
||||
|
||||
/* Regular SCST sysfs operations */
|
||||
extern struct sysfs_ops scst_sysfs_ops;
|
||||
|
||||
/*
|
||||
@@ -3554,78 +3294,32 @@ int scst_alloc_sense(struct scst_cmd *cmd, int atomic);
|
||||
int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
|
||||
const uint8_t *sense, unsigned int len);
|
||||
|
||||
/*
|
||||
* Sets the corresponding field in the sense buffer taking sense type
|
||||
* into account. Returns resulting sense length.
|
||||
*/
|
||||
int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
|
||||
int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Returns true if the sense is valid and carrying a Unit Attention or
|
||||
* false otherwise.
|
||||
*/
|
||||
bool scst_is_ua_sense(const uint8_t *sense, int len);
|
||||
|
||||
/*
|
||||
* Returnes true if sense matches to (key, asc, ascq) and false otherwise.
|
||||
* Valid_mask is one or several SCST_SENSE_*_VALID constants setting valid
|
||||
* (key, asc, ascq) values.
|
||||
*/
|
||||
bool scst_analyze_sense(const uint8_t *sense, int len,
|
||||
unsigned int valid_mask, int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Returnes a pseudo-random number for debugging purposes. Available only in
|
||||
* the DEBUG build.
|
||||
*/
|
||||
unsigned long scst_random(void);
|
||||
|
||||
/*
|
||||
* Sets response data length for cmd and truncates its SG vector accordingly.
|
||||
* The cmd->resp_data_len must not be set directly, it must be set only
|
||||
* using this function. Value of resp_data_len must be <= cmd->bufflen.
|
||||
*/
|
||||
void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len);
|
||||
|
||||
/*
|
||||
* Get/put global ref counter that prevents from entering into suspended
|
||||
* activities stage, so protects from any global management operations.
|
||||
*/
|
||||
void scst_get(void);
|
||||
void scst_put(void);
|
||||
|
||||
/*
|
||||
* Cmd ref counters
|
||||
*/
|
||||
void scst_cmd_get(struct scst_cmd *cmd);
|
||||
void scst_cmd_put(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Allocates and returns pointer to SG vector with data size "size".
|
||||
* In *count returned the count of entries in the vector.
|
||||
* Returns NULL for failure.
|
||||
*/
|
||||
struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count);
|
||||
|
||||
/* Frees SG vector returned by scst_alloc() */
|
||||
void scst_free(struct scatterlist *sg, int count);
|
||||
|
||||
/*
|
||||
* Adds local to the current thread data to tgt_dev
|
||||
* (they will be local for the tgt_dev and current thread).
|
||||
*/
|
||||
void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
|
||||
struct scst_thr_data_hdr *data,
|
||||
void (*free_fn) (struct scst_thr_data_hdr *data));
|
||||
|
||||
/* Deletes all local to threads data from tgt_dev */
|
||||
void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev);
|
||||
|
||||
/* Deletes all local to threads data from all tgt_dev's of the dev */
|
||||
void scst_dev_del_all_thr_data(struct scst_device *dev);
|
||||
|
||||
/* Finds local to the thread data. Returns NULL, if they not found. */
|
||||
struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
|
||||
struct task_struct *tsk);
|
||||
|
||||
@@ -3636,84 +3330,42 @@ static inline struct scst_thr_data_hdr *scst_find_thr_data(
|
||||
return __scst_find_thr_data(tgt_dev, current);
|
||||
}
|
||||
|
||||
/* Increase ref counter for the thread data */
|
||||
static inline void scst_thr_data_get(struct scst_thr_data_hdr *data)
|
||||
{
|
||||
atomic_inc(&data->ref);
|
||||
}
|
||||
|
||||
/* Decrease ref counter for the thread data */
|
||||
static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
|
||||
{
|
||||
if (atomic_dec_and_test(&data->ref))
|
||||
data->free_fn(data);
|
||||
}
|
||||
|
||||
/**
|
||||
** Generic parse() support routines.
|
||||
** Done via pointer on functions to avoid unneeded dereferences on
|
||||
** the fast path.
|
||||
**/
|
||||
|
||||
/* Calculates and returns block shift for the given sector size */
|
||||
int scst_calc_block_shift(int sector_size);
|
||||
|
||||
/* Generic parse() for SBC (disk) devices */
|
||||
int scst_sbc_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for MMC (cdrom) devices */
|
||||
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for MO disk devices */
|
||||
int scst_modisk_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for tape devices */
|
||||
int scst_tape_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_size)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for changer devices */
|
||||
int scst_changer_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for "processor" devices */
|
||||
int scst_processor_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd));
|
||||
|
||||
/* Generic parse() for RAID devices */
|
||||
int scst_raid_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd));
|
||||
|
||||
/**
|
||||
** Generic dev_done() support routines.
|
||||
** Done via pointer on functions to avoid unneeded dereferences on
|
||||
** the fast path.
|
||||
**/
|
||||
|
||||
/* Generic dev_done() for block devices */
|
||||
int scst_block_generic_dev_done(struct scst_cmd *cmd,
|
||||
void (*set_block_shift)(struct scst_cmd *cmd, int block_shift));
|
||||
|
||||
/* Generic dev_done() for tape devices */
|
||||
int scst_tape_generic_dev_done(struct scst_cmd *cmd,
|
||||
void (*set_block_size)(struct scst_cmd *cmd, int block_size));
|
||||
|
||||
/*
|
||||
* Issues a MODE SENSE for control mode page data and sets the corresponding
|
||||
* dev's parameter from it. Returns 0 on success and not 0 otherwise.
|
||||
*/
|
||||
int scst_obtain_device_parameters(struct scst_device *dev);
|
||||
|
||||
/*
|
||||
* Returns maximum commands count which can be queued to this LUN in this
|
||||
* session.
|
||||
*
|
||||
* If lun is NO_SUCH_LUN, returns minimum of maximum commands count which
|
||||
* can be queued to any LUN in this session.
|
||||
*
|
||||
* If sess is NULL, returns minimum of maximum commands count which can be
|
||||
* queued to any SCST device.
|
||||
*/
|
||||
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
|
||||
|
||||
/*
|
||||
@@ -3734,12 +3386,9 @@ static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q,
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
/**
|
||||
** Helper functionality to help target drivers and dev handlers support
|
||||
** sending events to user space and wait for their completion in a safe
|
||||
** manner. See samples how to use it in iscsi-scst or scst_user.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Structure to match events to user space and replies on them
|
||||
*/
|
||||
struct scst_sysfs_user_info {
|
||||
/* Unique cookie to identify request */
|
||||
uint32_t info_cookie;
|
||||
@@ -3761,61 +3410,21 @@ struct scst_sysfs_user_info {
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function creates an info structure and adds it in the info_list.
|
||||
* Returns 0 and out_info on success, error code otherwise.
|
||||
*/
|
||||
int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info);
|
||||
|
||||
/* This function deletes and frees info */
|
||||
void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info);
|
||||
|
||||
/*
|
||||
* This function finds the info based on cookie and set for it flag
|
||||
* info_being_executed. Returns found entry or NULL.
|
||||
*/
|
||||
struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie);
|
||||
|
||||
/*
|
||||
* This function waits for the info request been completed by user space.
|
||||
* Returns status of the request completion.
|
||||
*/
|
||||
int scst_wait_info_completion(struct scst_sysfs_user_info *info,
|
||||
unsigned long timeout);
|
||||
|
||||
/*
|
||||
* This function returns SCST setup ID. This ID can be used with multiple
|
||||
* setups with the same configuration.
|
||||
*/
|
||||
unsigned int scst_get_setup_id(void);
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
/*
|
||||
* This function returns pointer to the next lexem from token_str skipping
|
||||
* spaces and '=' character and using them then as a delimeter. Content
|
||||
* of token_str is modified by setting '\0' at the delimeter's position.
|
||||
*/
|
||||
char *scst_get_next_lexem(char **token_str);
|
||||
|
||||
/*
|
||||
* This function restores token_str modified by scst_get_next_lexem() to the
|
||||
* previous value before scst_get_next_lexem() was called. Prev_lexem is
|
||||
* a pointer to lexem returned by scst_get_next_lexem().
|
||||
*/
|
||||
void scst_restore_token_str(char *prev_lexem, char *token_str);
|
||||
|
||||
/*
|
||||
* This function returns pointer to the next token strings from input_str
|
||||
* using '\n', ';' and '\0' as a delimeter. Content of input_str is
|
||||
* modified by setting '\0' at the delimeter's position.
|
||||
*/
|
||||
char *scst_get_next_token_str(char **input_str);
|
||||
|
||||
/* Initializes scst_cmd_threads structure */
|
||||
void scst_init_threads(struct scst_cmd_threads *cmd_threads);
|
||||
|
||||
/* Deinitializes scst_cmd_threads structure */
|
||||
void scst_deinit_threads(struct scst_cmd_threads *cmd_threads);
|
||||
|
||||
#endif /* __SCST_H */
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
struct sgv_pool_obj;
|
||||
struct sgv_pool;
|
||||
|
||||
/*
|
||||
* Structure to keep a memory limit for an SCST object
|
||||
*/
|
||||
struct scst_mem_lim {
|
||||
/* How much memory allocated under this object */
|
||||
atomic_t alloced_pages;
|
||||
@@ -68,131 +71,27 @@ enum sgv_clustering_types {
|
||||
sgv_full_clustering,
|
||||
};
|
||||
|
||||
/**
|
||||
* sgv_pool_create - creates and initializes an SGV cache
|
||||
* @name: the name of the SGV cache
|
||||
* @clustered: sets type of the pages clustering.
|
||||
* @single_alloc_pages: if 0, then the SGV cache 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
|
||||
* single_alloc_pages sets the size of each buffer in pages.
|
||||
* @shared: sets if the SGV cache can be shared between devices or not.
|
||||
* The cache sharing allowed only between devices created inside
|
||||
* the same address space. If an SGV cache is shared, each
|
||||
* subsequent call of sgv_pool_create() with the same cache name
|
||||
* will not create a new cache, but instead return a reference
|
||||
* to it.
|
||||
* @purge_interval sets the 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.
|
||||
*
|
||||
* Description:
|
||||
* Returns the resulting SGV cache or NULL in case of any error.
|
||||
*/
|
||||
struct sgv_pool *sgv_pool_create(const char *name,
|
||||
enum sgv_clustering_types clustered, int single_alloc_pages,
|
||||
bool shared, int purge_interval);
|
||||
|
||||
/**
|
||||
* sgv_pool_del - deletes the corresponding SGV cache
|
||||
* @:pool the cache to delete.
|
||||
*
|
||||
* Description:
|
||||
* 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_del(struct sgv_pool *pool);
|
||||
|
||||
/**
|
||||
* sgv_pool_get - increases reference counter for the corresponding SGV cache
|
||||
* @:pool the cache to get.
|
||||
*
|
||||
* Description:
|
||||
*/
|
||||
void sgv_pool_get(struct sgv_pool *pool);
|
||||
|
||||
/**
|
||||
* sgv_pool_put - decreases reference counter for the corresponding SGV cache
|
||||
* @:pool the cache to put.
|
||||
*
|
||||
* Description:
|
||||
* If the reference counter reaches 0, the cache will be destroyed.
|
||||
*/
|
||||
void sgv_pool_put(struct sgv_pool *pool);
|
||||
|
||||
/**
|
||||
* sgv_pool_flush - flushes the SGV cache
|
||||
* @:pool the cache to flush
|
||||
*
|
||||
* Description:
|
||||
* Flushes, i.e. frees, all the cached entries in the SGV cache.
|
||||
*/
|
||||
void sgv_pool_flush(struct sgv_pool *pool);
|
||||
|
||||
/**
|
||||
* sgv_pool_set_allocator - allows to set a custom pages allocator
|
||||
* @:pool the cache
|
||||
* @:alloc_pages_fn pages allocation function
|
||||
* @:free_pages_fn pages freeing function
|
||||
*
|
||||
* Description:
|
||||
* See the SGV cache documentation for more details.
|
||||
*/
|
||||
void sgv_pool_set_allocator(struct sgv_pool *pool,
|
||||
struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
|
||||
void (*free_pages_fn)(struct scatterlist *, int, void *));
|
||||
|
||||
/**
|
||||
* sgv_pool_alloc - allocates an SG vector from the SGV cache
|
||||
* @:pool the cache to alloc from
|
||||
* @:size size of the resulting SG vector in bytes
|
||||
* @:gfp_mask the allocation mask
|
||||
* @:flags the allocation flags
|
||||
* @:count the resulting count of SG entries in the resulting SG vector
|
||||
* @:sgv the resulting SGV object
|
||||
* @:mem_lim memory limits
|
||||
* @:priv pointer to private for this allocation data
|
||||
*
|
||||
* Description:
|
||||
* Returns pointer to the resulting SG vector or NULL in case
|
||||
* of any error. See the SGV cache documentation for more details.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* sgv_pool_free - frees previously allocated SG vector
|
||||
* @:sgv the SGV object to free
|
||||
* @:mem_lim memory limits
|
||||
*
|
||||
* Description:
|
||||
* Frees previously allocated SG vector, referenced by SGV cache object sgv
|
||||
*/
|
||||
void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim);
|
||||
|
||||
/**
|
||||
* sgv_get_priv - returns the private allocation data
|
||||
* @:sgv the SGV object
|
||||
*
|
||||
* Description:
|
||||
* Allows to get the allocation private data for this SGV
|
||||
* cache object sgv. The private data are set by sgv_pool_alloc().
|
||||
*/
|
||||
void *sgv_get_priv(struct sgv_pool_obj *sgv);
|
||||
|
||||
/**
|
||||
* scst_init_mem_lim - initializes memory limits
|
||||
* @:mem_lim memory limits
|
||||
*
|
||||
* Description:
|
||||
* 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.
|
||||
*/
|
||||
void scst_init_mem_lim(struct scst_mem_lim *mem_lim);
|
||||
|
||||
#endif /* __SCST_SGV_H */
|
||||
|
||||
@@ -46,6 +46,11 @@ static inline int get_current_tid(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* debug_print_prefix() - print debug prefix for a log line
|
||||
*
|
||||
* Prints, if requested by trace_flag, debug prefix for each log line
|
||||
*/
|
||||
int debug_print_prefix(unsigned long trace_flag,
|
||||
const char *prefix, const char *func, int line)
|
||||
{
|
||||
@@ -75,6 +80,11 @@ int debug_print_prefix(unsigned long trace_flag,
|
||||
}
|
||||
EXPORT_SYMBOL(debug_print_prefix);
|
||||
|
||||
/**
|
||||
* debug_print_buffer() - print a buffer
|
||||
*
|
||||
* Prints in the log data from the buffer
|
||||
*/
|
||||
void debug_print_buffer(const void *data, int len)
|
||||
{
|
||||
int z, z1, i;
|
||||
|
||||
@@ -585,6 +585,13 @@ static inline void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
|
||||
static inline void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
|
||||
#endif /* CONFIG_SCST_DEBUG_TM */
|
||||
|
||||
/**
|
||||
* scst_alloc_sense() - allocate sense buffer for command
|
||||
*
|
||||
* Allocates, if necessary, sense buffer for command. Returns 0 on success
|
||||
* and error code othrwise. Parameter "atomic" should be non-0 if the
|
||||
* function called in atomic context.
|
||||
*/
|
||||
int scst_alloc_sense(struct scst_cmd *cmd, int atomic)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -615,6 +622,13 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_alloc_sense);
|
||||
|
||||
/**
|
||||
* scst_alloc_set_sense() - allocate and fill sense buffer for command
|
||||
*
|
||||
* Allocates, if necessary, sense buffer for command and copies in
|
||||
* it data from the supplied sense buffer. Returns 0 on success
|
||||
* and error code othrwise.
|
||||
*/
|
||||
int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
|
||||
const uint8_t *sense, unsigned int len)
|
||||
{
|
||||
@@ -649,6 +663,15 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_alloc_set_sense);
|
||||
|
||||
/**
|
||||
* scst_set_cmd_error_status() - set error SCSI status
|
||||
* @cmd: SCST command
|
||||
* @status: SCSI status to set
|
||||
*
|
||||
* Description:
|
||||
* Sets error SCSI status in the command and prepares it for returning it.
|
||||
* Returns 0 on success, error code otherwise.
|
||||
*/
|
||||
int scst_set_cmd_error_status(struct scst_cmd *cmd, int status)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -778,6 +801,12 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_set_cmd_error() - set error in the command and fill the sense buffer.
|
||||
*
|
||||
* Sets error in the command and fill the sense buffer. Returns 0 on success,
|
||||
* error code otherwise.
|
||||
*/
|
||||
int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq)
|
||||
{
|
||||
int res;
|
||||
@@ -825,6 +854,12 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_cmd_error);
|
||||
|
||||
/**
|
||||
* scst_set_sense() - set sense from KEY/ASC/ASCQ numbers
|
||||
*
|
||||
* Sets the corresponding fields in the sense buffer taking sense type
|
||||
* into account. Returns resulting sense length.
|
||||
*/
|
||||
int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
|
||||
int key, int asc, int ascq)
|
||||
{
|
||||
@@ -873,6 +908,13 @@ int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_sense);
|
||||
|
||||
/**
|
||||
* scst_analyze_sense() - analyze sense
|
||||
*
|
||||
* Returns true if sense matches to (key, asc, ascq) and false otherwise.
|
||||
* Valid_mask is one or several SCST_SENSE_*_VALID constants setting valid
|
||||
* (key, asc, ascq) values.
|
||||
*/
|
||||
bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
|
||||
int key, int asc, int ascq)
|
||||
{
|
||||
@@ -942,6 +984,12 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_analyze_sense);
|
||||
|
||||
/**
|
||||
* scst_is_ua_sense() - determine if the sense is UA sense
|
||||
*
|
||||
* Returns true if the sense is valid and carrying a Unit
|
||||
* Attention or false otherwise.
|
||||
*/
|
||||
bool scst_is_ua_sense(const uint8_t *sense, int len)
|
||||
{
|
||||
if (SCST_SENSE_VALID(sense))
|
||||
@@ -967,6 +1015,12 @@ bool scst_is_ua_global(const uint8_t *sense, int len)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_check_convert_sense() - check sense type and convert it if needed
|
||||
*
|
||||
* Checks if sense in the sense buffer, if any, is in the correct format.
|
||||
* If not, converts it in the correct format.
|
||||
*/
|
||||
void scst_check_convert_sense(struct scst_cmd *cmd)
|
||||
{
|
||||
bool d_sense;
|
||||
@@ -1026,6 +1080,12 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_set_busy() - set BUSY or TASK QUEUE FULL status
|
||||
*
|
||||
* Sets BUSY or TASK QUEUE FULL status depending on if this session has other
|
||||
* outstanding commands or not.
|
||||
*/
|
||||
void scst_set_busy(struct scst_cmd *cmd)
|
||||
{
|
||||
int c = atomic_read(&cmd->sess->sess_cmd_count);
|
||||
@@ -1051,6 +1111,12 @@ void scst_set_busy(struct scst_cmd *cmd)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_busy);
|
||||
|
||||
/**
|
||||
* scst_set_initial_UA() - set initial Unit Attention
|
||||
*
|
||||
* Sets initial Unit Attention on all devices of the session,
|
||||
* replacing default scst_sense_reset_UA
|
||||
*/
|
||||
void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
|
||||
{
|
||||
int i;
|
||||
@@ -1185,7 +1251,11 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
/**
|
||||
* scst_capacity_data_changed() - notify SCST about device capacity change
|
||||
*
|
||||
* Notifies SCST core that dev has changed its capacity. Called under no locks.
|
||||
*/
|
||||
void scst_capacity_data_changed(struct scst_device *dev)
|
||||
{
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
@@ -1376,6 +1446,14 @@ void scst_report_luns_changed(struct scst_acg *acg)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_aen_done() - AEN processing done
|
||||
*
|
||||
* Notifies SCST that the driver has sent the AEN and it
|
||||
* can be freed now. Don't forget to set the delivery status, if it
|
||||
* isn't success, using scst_set_aen_delivery_status() before calling
|
||||
* this function.
|
||||
*/
|
||||
void scst_aen_done(struct scst_aen *aen)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -1605,6 +1683,12 @@ void scst_check_reassign_sessions(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_get_cmd_abnormal_done_state() - get command's next abnormal done state
|
||||
*
|
||||
* Returns the next state of the SCSI target state machine in case if command's
|
||||
* completed abnormally.
|
||||
*/
|
||||
int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
|
||||
{
|
||||
int res;
|
||||
@@ -1672,6 +1756,12 @@ int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get_cmd_abnormal_done_state);
|
||||
|
||||
/**
|
||||
* scst_set_cmd_abnormal_done_state() - set command's next abnormal done state
|
||||
*
|
||||
* Sets state of the SCSI target state machine in case if command's completed
|
||||
* abnormally.
|
||||
*/
|
||||
void scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -1705,6 +1795,14 @@ void scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_cmd_abnormal_done_state);
|
||||
|
||||
/**
|
||||
* scst_set_resp_data_len() - set response data length
|
||||
*
|
||||
* Sets response data length for cmd and truncates its SG vector accordingly.
|
||||
*
|
||||
* The cmd->resp_data_len must not be set directly, it must be set only
|
||||
* using this function. Value of resp_data_len must be <= cmd->bufflen.
|
||||
*/
|
||||
void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len)
|
||||
{
|
||||
int i, l;
|
||||
@@ -2066,6 +2164,13 @@ void scst_free_device(struct scst_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_init_mem_lim - initialize memory limits structure
|
||||
*
|
||||
* 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 pools memory.
|
||||
*/
|
||||
void scst_init_mem_lim(struct scst_mem_lim *mem_lim)
|
||||
{
|
||||
atomic_set(&mem_lim->alloced_pages, 0);
|
||||
@@ -2173,7 +2278,7 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
if (tgt != NULL) {
|
||||
TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
|
||||
tgt->tgt_name);
|
||||
list_add_tail(&acg->acg_list_entry, &tgt->acg_list);
|
||||
list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
|
||||
acg->in_tgt_acg_list = 1;
|
||||
}
|
||||
#endif
|
||||
@@ -2273,7 +2378,7 @@ struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_for_each_entry(acg, &tgt->acg_list, acg_list_entry) {
|
||||
list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
|
||||
if (strcmp(acg->acg_name, name) == 0) {
|
||||
acg_ret = acg;
|
||||
break;
|
||||
@@ -3551,12 +3656,18 @@ void scst_sched_session_free(struct scst_session *sess)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_cmd_get() - increase command's reference counter
|
||||
*/
|
||||
void scst_cmd_get(struct scst_cmd *cmd)
|
||||
{
|
||||
__scst_cmd_get(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cmd_get);
|
||||
|
||||
/**
|
||||
* scst_cmd_put() - decrease command's reference counter
|
||||
*/
|
||||
void scst_cmd_put(struct scst_cmd *cmd)
|
||||
{
|
||||
__scst_cmd_put(cmd);
|
||||
@@ -4258,6 +4369,12 @@ out_free_sioc:
|
||||
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) && defined(SCSI_EXEC_REQ_FIFO_DEFINED) */
|
||||
|
||||
/**
|
||||
* scst_copy_sg() - copy data between the command's SGs
|
||||
*
|
||||
* Copies data between cmd->tgt_sg and cmd->sg in direction defined by
|
||||
* copy_dir parameter.
|
||||
*/
|
||||
void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir)
|
||||
{
|
||||
struct scatterlist *src_sg, *dst_sg;
|
||||
@@ -4493,6 +4610,16 @@ static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_get_cdb_info() - fill various info about the command's CDB
|
||||
*
|
||||
* Description:
|
||||
* Fills various info about the command's CDB in the corresponding fields
|
||||
* in the command.
|
||||
*
|
||||
* Returns: 0 on success, <0 if command is unknown, >0 if command
|
||||
* is invalid.
|
||||
*/
|
||||
int scst_get_cdb_info(struct scst_cmd *cmd)
|
||||
{
|
||||
int dev_type = cmd->dev->type;
|
||||
@@ -4676,6 +4803,17 @@ out_err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
** Generic parse() support routines.
|
||||
** Done via pointer on functions to avoid unneeded dereferences on
|
||||
** the fast path.
|
||||
**/
|
||||
|
||||
/**
|
||||
* scst_calc_block_shift() - calculate block shift
|
||||
*
|
||||
* Calculates and returns block shift for the given sector size
|
||||
*/
|
||||
int scst_calc_block_shift(int sector_size)
|
||||
{
|
||||
int block_shift = 0;
|
||||
@@ -4701,6 +4839,11 @@ int scst_calc_block_shift(int sector_size)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_calc_block_shift);
|
||||
|
||||
/**
|
||||
* scst_sbc_generic_parse() - generic SBC parsing
|
||||
*
|
||||
* Generic parse() for SBC (disk) devices
|
||||
*/
|
||||
int scst_sbc_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4757,6 +4900,11 @@ set_timeout:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_sbc_generic_parse);
|
||||
|
||||
/**
|
||||
* scst_cdrom_generic_parse() - generic MMC parse
|
||||
*
|
||||
* Generic parse() for MMC (cdrom) devices
|
||||
*/
|
||||
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4809,6 +4957,11 @@ set_timeout:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cdrom_generic_parse);
|
||||
|
||||
/**
|
||||
* scst_modisk_generic_parse() - generic MO parse
|
||||
*
|
||||
* Generic parse() for MO disk devices
|
||||
*/
|
||||
int scst_modisk_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_shift)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4861,6 +5014,11 @@ set_timeout:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_modisk_generic_parse);
|
||||
|
||||
/**
|
||||
* scst_tape_generic_parse() - generic tape parse
|
||||
*
|
||||
* Generic parse() for tape devices
|
||||
*/
|
||||
int scst_tape_generic_parse(struct scst_cmd *cmd,
|
||||
int (*get_block_size)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4933,6 +5091,11 @@ static int scst_null_parse(struct scst_cmd *cmd)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_changer_generic_parse() - generic changer parse
|
||||
*
|
||||
* Generic parse() for changer devices
|
||||
*/
|
||||
int scst_changer_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4947,6 +5110,11 @@ int scst_changer_generic_parse(struct scst_cmd *cmd,
|
||||
}
|
||||
EXPORT_SYMBOL(scst_changer_generic_parse);
|
||||
|
||||
/**
|
||||
* scst_processor_generic_parse - generic SCSI processor parse
|
||||
*
|
||||
* Generic parse() for SCSI processor devices
|
||||
*/
|
||||
int scst_processor_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4961,6 +5129,11 @@ int scst_processor_generic_parse(struct scst_cmd *cmd,
|
||||
}
|
||||
EXPORT_SYMBOL(scst_processor_generic_parse);
|
||||
|
||||
/**
|
||||
* scst_raid_generic_parse() - generic RAID parse
|
||||
*
|
||||
* Generic parse() for RAID devices
|
||||
*/
|
||||
int scst_raid_generic_parse(struct scst_cmd *cmd,
|
||||
int (*nothing)(struct scst_cmd *cmd))
|
||||
{
|
||||
@@ -4975,6 +5148,17 @@ int scst_raid_generic_parse(struct scst_cmd *cmd,
|
||||
}
|
||||
EXPORT_SYMBOL(scst_raid_generic_parse);
|
||||
|
||||
/**
|
||||
** Generic dev_done() support routines.
|
||||
** Done via pointer on functions to avoid unneeded dereferences on
|
||||
** the fast path.
|
||||
**/
|
||||
|
||||
/**
|
||||
* scst_block_generic_dev_done() - generic SBC dev_done
|
||||
*
|
||||
* Generic dev_done() for block (SBC) devices
|
||||
*/
|
||||
int scst_block_generic_dev_done(struct scst_cmd *cmd,
|
||||
void (*set_block_shift)(struct scst_cmd *cmd, int block_shift))
|
||||
{
|
||||
@@ -5034,6 +5218,11 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_block_generic_dev_done);
|
||||
|
||||
/**
|
||||
* scst_tape_generic_dev_done() - generic tape dev done
|
||||
*
|
||||
* Generic dev_done() for tape devices
|
||||
*/
|
||||
int scst_tape_generic_dev_done(struct scst_cmd *cmd,
|
||||
void (*set_block_size)(struct scst_cmd *cmd, int block_shift))
|
||||
{
|
||||
@@ -5121,6 +5310,12 @@ static void scst_check_internal_sense(struct scst_device *dev, int result,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_to_dma_dir() - translate SCST's data direction to DMA direction
|
||||
*
|
||||
* Translates SCST's data direction to DMA one from backend storage
|
||||
* perspective.
|
||||
*/
|
||||
enum dma_data_direction scst_to_dma_dir(int scst_dir)
|
||||
{
|
||||
static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
|
||||
@@ -5130,6 +5325,12 @@ enum dma_data_direction scst_to_dma_dir(int scst_dir)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_to_dma_dir);
|
||||
|
||||
/*
|
||||
* scst_to_tgt_dma_dir() - translate SCST data direction to DMA direction
|
||||
*
|
||||
* Translates SCST data direction to DMA data direction from the perspective
|
||||
* of the target device.
|
||||
*/
|
||||
enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir)
|
||||
{
|
||||
static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
|
||||
@@ -5139,6 +5340,12 @@ enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_to_tgt_dma_dir);
|
||||
|
||||
/**
|
||||
* scst_obtain_device_parameters() - obtain device control parameters
|
||||
*
|
||||
* Issues a MODE SENSE for control mode page data and sets the corresponding
|
||||
* dev's parameter from it. Returns 0 on success and not 0 otherwise.
|
||||
*/
|
||||
int scst_obtain_device_parameters(struct scst_device *dev)
|
||||
{
|
||||
int rc, i;
|
||||
@@ -5703,6 +5910,18 @@ out_unlock:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
** The following thr_data functions are necessary, because the
|
||||
** kernel doesn't provide a better way to have threads local
|
||||
** storage
|
||||
*****************************************************************/
|
||||
|
||||
/**
|
||||
* scst_add_thr_data() - add the current thread's local data
|
||||
*
|
||||
* Adds local to the current thread data to tgt_dev
|
||||
* (they will be local for the tgt_dev and current thread).
|
||||
*/
|
||||
void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
|
||||
struct scst_thr_data_hdr *data,
|
||||
void (*free_fn) (struct scst_thr_data_hdr *data))
|
||||
@@ -5717,6 +5936,11 @@ void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
|
||||
}
|
||||
EXPORT_SYMBOL(scst_add_thr_data);
|
||||
|
||||
/**
|
||||
* scst_del_all_thr_data() - delete all thread's local data
|
||||
*
|
||||
* Deletes all local to threads data from tgt_dev
|
||||
*/
|
||||
void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
spin_lock(&tgt_dev->thr_data_lock);
|
||||
@@ -5734,6 +5958,11 @@ void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_del_all_thr_data);
|
||||
|
||||
/**
|
||||
* scst_dev_del_all_thr_data() - delete all thread's local data from device
|
||||
*
|
||||
* Deletes all local to threads data from all tgt_dev's of the device
|
||||
*/
|
||||
void scst_dev_del_all_thr_data(struct scst_device *dev)
|
||||
{
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
@@ -5770,6 +5999,11 @@ static struct scst_thr_data_hdr *__scst_find_thr_data_locked(
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* __scst_find_thr_data() - find local to the thread data
|
||||
*
|
||||
* Finds local to the thread data. Returns NULL, if they not found.
|
||||
*/
|
||||
struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
@@ -6107,12 +6341,31 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_get_max_lun_commands() - return maximum supported commands count
|
||||
*
|
||||
* Returns maximum commands count which can be queued to this LUN in this
|
||||
* session.
|
||||
*
|
||||
* If lun is NO_SUCH_LUN, returns minimum of maximum commands count which
|
||||
* can be queued to any LUN in this session.
|
||||
*
|
||||
* If sess is NULL, returns minimum of maximum commands count which can be
|
||||
* queued to any SCST device.
|
||||
*/
|
||||
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun)
|
||||
{
|
||||
return SCST_MAX_TGT_DEV_COMMANDS;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get_max_lun_commands);
|
||||
|
||||
/**
|
||||
* scst_get_next_lexem() - parse and return next lexem in the string
|
||||
*
|
||||
* Returns pointer to the next lexem from token_str skipping
|
||||
* spaces and '=' character and using them then as a delimeter. Content
|
||||
* of token_str is modified by setting '\0' at the delimeter's position.
|
||||
*/
|
||||
char *scst_get_next_lexem(char **token_str)
|
||||
{
|
||||
char *p = *token_str;
|
||||
@@ -6136,6 +6389,13 @@ char *scst_get_next_lexem(char **token_str)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get_next_lexem);
|
||||
|
||||
/**
|
||||
* scst_restore_token_str() - restore string modified by scst_get_next_lexem()
|
||||
*
|
||||
* Restores token_str modified by scst_get_next_lexem() to the
|
||||
* previous value before scst_get_next_lexem() was called. Prev_lexem is
|
||||
* a pointer to lexem returned by scst_get_next_lexem().
|
||||
*/
|
||||
void scst_restore_token_str(char *prev_lexem, char *token_str)
|
||||
{
|
||||
if (&prev_lexem[strlen(prev_lexem)] != token_str)
|
||||
@@ -6144,6 +6404,13 @@ void scst_restore_token_str(char *prev_lexem, char *token_str)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_restore_token_str);
|
||||
|
||||
/**
|
||||
* scst_get_next_token_str() - parse and return next token
|
||||
*
|
||||
* This function returns pointer to the next token strings from input_str
|
||||
* using '\n', ';' and '\0' as a delimeter. Content of input_str is
|
||||
* modified by setting '\0' at the delimeter's position.
|
||||
*/
|
||||
char *scst_get_next_token_str(char **input_str)
|
||||
{
|
||||
char *p = *input_str;
|
||||
@@ -6220,7 +6487,15 @@ void scst_lib_exit(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCST_DEBUG
|
||||
/* Original taken from the XFS code */
|
||||
|
||||
/**
|
||||
* scst_random() - return a pseudo-random number for debugging purposes.
|
||||
*
|
||||
* Returns a pseudo-random number for debugging purposes. Available only in
|
||||
* the DEBUG build.
|
||||
*
|
||||
* Original taken from the XFS code
|
||||
*/
|
||||
unsigned long scst_random(void)
|
||||
{
|
||||
static int Inited;
|
||||
|
||||
@@ -60,7 +60,8 @@
|
||||
**/
|
||||
|
||||
/*
|
||||
* All targets, devices and dev_types management is done under this mutex.
|
||||
* Main SCST mutex. All targets, devices and dev_types management is done
|
||||
* under this mutex.
|
||||
*
|
||||
* It must NOT be used in any works (schedule_work(), etc.), because
|
||||
* otherwise a deadlock (double lock, actually) is possible, e.g., with
|
||||
@@ -161,6 +162,19 @@ struct scst_dev_type scst_null_devtype = {
|
||||
|
||||
static void __scst_resume_activity(void);
|
||||
|
||||
/**
|
||||
* __scst_register_target_template() - register target template.
|
||||
* @vtt: target template
|
||||
* @version: SCST_INTERFACE_VERSION version string to ensure that
|
||||
* SCST core and the target driver use the same version of
|
||||
* the SCST interface
|
||||
*
|
||||
* Description:
|
||||
* Registers a target template and returns 0 on success or appropriate
|
||||
* error code otherwise.
|
||||
*
|
||||
* Note: *vtt must be static!
|
||||
*/
|
||||
int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
const char *version)
|
||||
{
|
||||
@@ -291,6 +305,9 @@ out_err:
|
||||
}
|
||||
EXPORT_SYMBOL(__scst_register_target_template);
|
||||
|
||||
/**
|
||||
* scst_unregister_target_template() - unregister target template
|
||||
*/
|
||||
void scst_unregister_target_template(struct scst_tgt_template *vtt)
|
||||
{
|
||||
struct scst_tgt *tgt;
|
||||
@@ -341,6 +358,12 @@ out_err_up:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_unregister_target_template);
|
||||
|
||||
/**
|
||||
* scst_register_target() - register target
|
||||
*
|
||||
* Rgisters a target for template vtt and returns new target structure on
|
||||
* success or NULL otherwise.
|
||||
*/
|
||||
struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
const char *target_name)
|
||||
{
|
||||
@@ -414,7 +437,7 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
if (tgt->default_acg == NULL)
|
||||
goto out_free_tgt_name;
|
||||
|
||||
INIT_LIST_HEAD(&tgt->acg_list);
|
||||
INIT_LIST_HEAD(&tgt->tgt_acg_list);
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
rc = scst_build_proc_target_entries(tgt);
|
||||
@@ -492,6 +515,9 @@ static inline int test_sess_list(struct scst_tgt *tgt)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_unregister_target() - unregister target
|
||||
*/
|
||||
void scst_unregister(struct scst_tgt *tgt)
|
||||
{
|
||||
struct scst_session *sess;
|
||||
@@ -541,7 +567,8 @@ again:
|
||||
|
||||
scst_clear_acg(tgt->default_acg);
|
||||
|
||||
list_for_each_entry_safe(acg, acg_tmp, &tgt->acg_list, acg_list_entry) {
|
||||
list_for_each_entry_safe(acg, acg_tmp, &tgt->tgt_acg_list,
|
||||
acg_list_entry) {
|
||||
scst_acg_sysfs_put(acg);
|
||||
}
|
||||
|
||||
@@ -585,6 +612,19 @@ static int scst_susp_wait(bool interruptible)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_suspend_activity() - globally suspend any activity
|
||||
*
|
||||
* Description:
|
||||
* Globally suspends any activity and doesn't return, until there are any
|
||||
* active commands (state after SCST_CMD_STATE_INIT). If "interruptible"
|
||||
* is true, it returns after SCST_SUSPENDING_TIMEOUT or if it was interrupted
|
||||
* by a signal with the corresponding error status < 0. If "interruptible"
|
||||
* is false, it will wait virtually forever. On success returns 0.
|
||||
*
|
||||
* New arriving commands stay in the suspended state until
|
||||
* scst_resume_activity() is called.
|
||||
*/
|
||||
int scst_suspend_activity(bool interruptible)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -709,6 +749,11 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_resume_activity() - globally resume all activities
|
||||
*
|
||||
* Resumes suspended by scst_suspend_activity() activities.
|
||||
*/
|
||||
void scst_resume_activity(void)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -918,6 +963,15 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_register_virtual_device() - register a virtual device.
|
||||
* @dev_handler: the device's device handler
|
||||
* @dev_name: the new device name, NULL-terminated string. Must be uniq
|
||||
* among all virtual devices in the system.
|
||||
*
|
||||
* Registers a virtual device and returns assinged to the device ID on
|
||||
* success, or negative value otherwise
|
||||
*/
|
||||
int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
const char *dev_name)
|
||||
{
|
||||
@@ -1018,6 +1072,10 @@ out_release:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_register_virtual_device);
|
||||
|
||||
/**
|
||||
* scst_unregister_virtual_device() - unegister a virtual device.
|
||||
* @id: the device's ID, returned by the registration function
|
||||
*/
|
||||
void scst_unregister_virtual_device(int id)
|
||||
{
|
||||
struct scst_device *d, *dev = NULL;
|
||||
@@ -1063,6 +1121,19 @@ out_unblock:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_unregister_virtual_device);
|
||||
|
||||
/**
|
||||
* __scst_register_dev_driver() - register pass-through dev handler driver
|
||||
* @dev_type: dev handler template
|
||||
* @version: SCST_INTERFACE_VERSION version string to ensure that
|
||||
* SCST core and the dev handler use the same version of
|
||||
* the SCST interface
|
||||
*
|
||||
* Description:
|
||||
* Registers a pass-through dev handler driver. Returns 0 on success
|
||||
* or appropriate error code otherwise.
|
||||
*
|
||||
* Note: *dev_type must be static!
|
||||
*/
|
||||
int __scst_register_dev_driver(struct scst_dev_type *dev_type,
|
||||
const char *version)
|
||||
{
|
||||
@@ -1179,6 +1250,9 @@ out_error:
|
||||
}
|
||||
EXPORT_SYMBOL(__scst_register_dev_driver);
|
||||
|
||||
/**
|
||||
* scst_unregister_dev_driver() - unregister pass-through dev handler driver
|
||||
*/
|
||||
void scst_unregister_dev_driver(struct scst_dev_type *dev_type)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
@@ -1234,6 +1308,19 @@ out_up:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_unregister_dev_driver);
|
||||
|
||||
/**
|
||||
* __scst_register_virtual_dev_driver() - register virtual dev handler driver
|
||||
* @dev_type: dev handler template
|
||||
* @version: SCST_INTERFACE_VERSION version string to ensure that
|
||||
* SCST core and the dev handler use the same version of
|
||||
* the SCST interface
|
||||
*
|
||||
* Description:
|
||||
* Registers a virtual dev handler driver. Returns 0 on success or
|
||||
* appropriate error code otherwise.
|
||||
*
|
||||
* Note: *dev_type must be static!
|
||||
*/
|
||||
int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
|
||||
const char *version)
|
||||
{
|
||||
@@ -1292,6 +1379,9 @@ out_err:
|
||||
}
|
||||
EXPORT_SYMBOL(__scst_register_virtual_dev_driver);
|
||||
|
||||
/**
|
||||
* scst_unregister_virtual_dev_driver() - unregister virtual dev driver
|
||||
*/
|
||||
void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -1591,6 +1681,11 @@ out_null:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_init_threads() - initialize SCST processing threads pool
|
||||
*
|
||||
* Initializes scst_cmd_threads structure
|
||||
*/
|
||||
void scst_init_threads(struct scst_cmd_threads *cmd_threads)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -1610,6 +1705,11 @@ void scst_init_threads(struct scst_cmd_threads *cmd_threads)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_init_threads);
|
||||
|
||||
/**
|
||||
* scst_deinit_threads() - deinitialize SCST processing threads pool
|
||||
*
|
||||
* Deinitializes scst_cmd_threads structure
|
||||
*/
|
||||
void scst_deinit_threads(struct scst_cmd_threads *cmd_threads)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -1692,12 +1792,25 @@ out_unlock:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_get() - increase global SCST ref counter
|
||||
*
|
||||
* Increases global SCST ref counter that prevents from entering into suspended
|
||||
* activities stage, so protects from any global management operations.
|
||||
*/
|
||||
void scst_get(void)
|
||||
{
|
||||
__scst_get(0);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get);
|
||||
|
||||
/**
|
||||
* scst_put() - decrease global SCST ref counter
|
||||
*
|
||||
* Decreses global SCST ref counter that prevents from entering into suspended
|
||||
* activities stage, so protects from any global management operations. On
|
||||
* zero, if suspending activities is waiting, they will be suspended.
|
||||
*/
|
||||
void scst_put(void)
|
||||
{
|
||||
__scst_put();
|
||||
@@ -1705,6 +1818,12 @@ void scst_put(void)
|
||||
EXPORT_SYMBOL(scst_put);
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
/**
|
||||
* scst_get_setup_id() - return SCST setup ID
|
||||
*
|
||||
* Returns SCST setup ID. This ID can be used for multiple
|
||||
* setups with the same configuration.
|
||||
*/
|
||||
unsigned int scst_get_setup_id(void)
|
||||
{
|
||||
return scst_setup_id;
|
||||
|
||||
@@ -883,6 +883,21 @@ static void sgv_uncheck_allowed_mem(struct scst_mem_lim *mem_lim, int pages)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sgv_pool_alloc - allocate an SG vector from the SGV pool
|
||||
* @pool: the cache to alloc from
|
||||
* @size: size of the resulting SG vector in bytes
|
||||
* @gfp_mask: the allocation mask
|
||||
* @flags: the allocation flags
|
||||
* @count: the resulting count of SG entries in the resulting SG vector
|
||||
* @sgv: the resulting SGV object
|
||||
* @mem_lim: memory limits
|
||||
* @priv: pointer to private for this allocation data
|
||||
*
|
||||
* Description:
|
||||
* Allocate an SG vector from the SGV pool and returns pointer to it or
|
||||
* NULL in case of any error. See the SGV pool documentation for more details.
|
||||
*/
|
||||
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)
|
||||
@@ -1140,12 +1155,26 @@ out_uncheck:
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_alloc);
|
||||
|
||||
/**
|
||||
* sgv_get_priv - return the private allocation data
|
||||
*
|
||||
* Allows to get the allocation private data for this SGV
|
||||
* cache object. The private data supposed to be set by sgv_pool_alloc().
|
||||
*/
|
||||
void *sgv_get_priv(struct sgv_pool_obj *obj)
|
||||
{
|
||||
return obj->allocator_priv;
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_get_priv);
|
||||
|
||||
/**
|
||||
* sgv_pool_free - free previously allocated SG vector
|
||||
* @sgv: the SGV object to free
|
||||
* @mem_lim: memory limits
|
||||
*
|
||||
* Description:
|
||||
* Frees previously allocated SG vector and updates memory limits
|
||||
*/
|
||||
void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim)
|
||||
{
|
||||
int pages = (obj->sg_count != 0) ? obj->pages : 0;
|
||||
@@ -1168,6 +1197,13 @@ void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim)
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_free);
|
||||
|
||||
/**
|
||||
* scst_alloc() - allocates an SG vector
|
||||
*
|
||||
* Allocates and returns pointer to SG vector with data size "size".
|
||||
* In *count returned the count of entries in the vector.
|
||||
* Returns NULL for failure.
|
||||
*/
|
||||
struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count)
|
||||
{
|
||||
struct scatterlist *res;
|
||||
@@ -1230,6 +1266,11 @@ out_uncheck:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_alloc);
|
||||
|
||||
/**
|
||||
* scst_free() - frees SG vector
|
||||
*
|
||||
* Frees SG vector returned by scst_alloc().
|
||||
*/
|
||||
void scst_free(struct scatterlist *sg, int count)
|
||||
{
|
||||
TRACE_MEM("Freeing sg=%p", sg);
|
||||
@@ -1403,6 +1444,11 @@ static void sgv_evaluate_local_max_pages(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sgv_pool_flush - flushe the SGV pool
|
||||
*
|
||||
* Flushes, i.e. frees, all the cached entries in the SGV pool.
|
||||
*/
|
||||
void sgv_pool_flush(struct sgv_pool *pool)
|
||||
{
|
||||
int i;
|
||||
@@ -1457,6 +1503,16 @@ static void sgv_pool_deinit_put(struct sgv_pool *pool)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sgv_pool_set_allocator - set custom pages allocator
|
||||
* @pool: the cache
|
||||
* @alloc_pages_fn: pages allocation function
|
||||
* @free_pages_fn: pages freeing function
|
||||
*
|
||||
* Description:
|
||||
* Allows to set custom pages allocator for the SGV pool.
|
||||
* See the SGV pool documentation for more details.
|
||||
*/
|
||||
void sgv_pool_set_allocator(struct sgv_pool *pool,
|
||||
struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
|
||||
void (*free_pages_fn)(struct scatterlist *, int, void *))
|
||||
@@ -1467,6 +1523,30 @@ void sgv_pool_set_allocator(struct sgv_pool *pool,
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_set_allocator);
|
||||
|
||||
/**
|
||||
* sgv_pool_create - creates and initializes an SGV pool
|
||||
* @name: the name of the SGV pool
|
||||
* @clustered: sets type of the pages clustering.
|
||||
* @single_alloc_pages: if 0, then the SGV pool will work in the set of
|
||||
* power 2 size buffers mode. If >0, then the SGV pool will
|
||||
* work in the fixed size buffers mode. In this case
|
||||
* single_alloc_pages sets the size of each buffer in pages.
|
||||
* @shared: sets if the SGV pool can be shared between devices or not.
|
||||
* The cache sharing allowed only between devices created inside
|
||||
* the same address space. If an SGV pool is shared, each
|
||||
* subsequent call of sgv_pool_create() with the same cache name
|
||||
* will not create a new cache, but instead return a reference
|
||||
* to it.
|
||||
* @purge_interval: sets the 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.
|
||||
*
|
||||
* Description:
|
||||
* Returns the resulting SGV pool or NULL in case of any error.
|
||||
*/
|
||||
struct sgv_pool *sgv_pool_create(const char *name,
|
||||
enum sgv_clustering_types clustering_type,
|
||||
int single_alloc_pages, bool shared, int purge_interval)
|
||||
@@ -1548,6 +1628,11 @@ void sgv_pool_destroy(struct sgv_pool *pool)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sgv_pool_get - increase ref counter for the corresponding SGV pool
|
||||
*
|
||||
* Increases ref counter for the corresponding SGV pool
|
||||
*/
|
||||
void sgv_pool_get(struct sgv_pool *pool)
|
||||
{
|
||||
atomic_inc(&pool->sgv_pool_ref);
|
||||
@@ -1557,6 +1642,12 @@ void sgv_pool_get(struct sgv_pool *pool)
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_get);
|
||||
|
||||
/**
|
||||
* sgv_pool_put - decrease ref counter for the corresponding SGV pool
|
||||
*
|
||||
* Decreases ref counter for the corresponding SGV pool. If the ref
|
||||
* counter reaches 0, the cache will be destroyed.
|
||||
*/
|
||||
void sgv_pool_put(struct sgv_pool *pool)
|
||||
{
|
||||
TRACE_MEM("Decrementing sgv pool %p ref (new value %d)",
|
||||
@@ -1567,6 +1658,14 @@ void sgv_pool_put(struct sgv_pool *pool)
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_put);
|
||||
|
||||
/**
|
||||
* sgv_pool_del - deletes the corresponding SGV pool
|
||||
* @pool: the cache to delete.
|
||||
*
|
||||
* Description:
|
||||
* 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_del(struct sgv_pool *pool)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -30,6 +30,9 @@ struct trans_tbl_ent {
|
||||
unsigned short pg_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* SGV pool object
|
||||
*/
|
||||
struct sgv_pool_obj {
|
||||
int cache_num;
|
||||
int pages;
|
||||
@@ -50,11 +53,17 @@ struct sgv_pool_obj {
|
||||
struct scatterlist sg_entries_data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* SGV pool statistics accounting structure
|
||||
*/
|
||||
struct sgv_pool_cache_acc {
|
||||
atomic_t total_alloc, hit_alloc;
|
||||
atomic_t merged;
|
||||
};
|
||||
|
||||
/*
|
||||
* SGV pool allocation functions
|
||||
*/
|
||||
struct sgv_pool_alloc_fns {
|
||||
struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask,
|
||||
void *priv);
|
||||
@@ -62,6 +71,9 @@ struct sgv_pool_alloc_fns {
|
||||
void *priv);
|
||||
};
|
||||
|
||||
/*
|
||||
* SGV pool
|
||||
*/
|
||||
struct sgv_pool {
|
||||
enum sgv_clustering_types clustering_type;
|
||||
int single_alloc_pages;
|
||||
|
||||
@@ -35,6 +35,7 @@ static struct kobject *scst_devices_kobj;
|
||||
static struct kobject *scst_sgv_kobj;
|
||||
static struct kobject *scst_handlers_kobj;
|
||||
|
||||
/* Regular SCST sysfs operations */
|
||||
struct sysfs_ops scst_sysfs_ops;
|
||||
EXPORT_SYMBOL(scst_sysfs_ops);
|
||||
|
||||
@@ -2301,7 +2302,7 @@ static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
|
||||
goto out_free_up;
|
||||
}
|
||||
|
||||
list_for_each_entry(a, &tgt->acg_list, acg_list_entry) {
|
||||
list_for_each_entry(a, &tgt->tgt_acg_list, acg_list_entry) {
|
||||
if (strcmp(a->acg_name, p) == 0) {
|
||||
TRACE_DBG("group (acg) %p %s found",
|
||||
a, a->acg_name);
|
||||
@@ -3803,6 +3804,14 @@ static struct scst_sysfs_user_info *scst_sysfs_user_find_info(uint32_t cookie)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_sysfs_user_get_info() - get user_info
|
||||
*
|
||||
* Finds the user_info based on cookie and mark it as received the reply by
|
||||
* setting for it flag info_being_executed.
|
||||
*
|
||||
* Returns found entry or NULL.
|
||||
*/
|
||||
struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie)
|
||||
{
|
||||
struct scst_sysfs_user_info *res = NULL;
|
||||
@@ -3824,6 +3833,18 @@ struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_sysfs_user_get_info);
|
||||
|
||||
/**
|
||||
** Helper functionality to help target drivers and dev handlers support
|
||||
** sending events to user space and wait for their completion in a safe
|
||||
** manner. See samples how to use it in iscsi-scst or scst_user.
|
||||
**/
|
||||
|
||||
/**
|
||||
* scst_sysfs_user_add_info() - create and add user_info in the global list
|
||||
*
|
||||
* Creates an info structure and adds it in the info_list.
|
||||
* Returns 0 and out_info on success, error code otherwise.
|
||||
*/
|
||||
int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -3860,6 +3881,9 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_sysfs_user_add_info);
|
||||
|
||||
/**
|
||||
* scst_sysfs_user_del_info - delete and frees user_info
|
||||
*/
|
||||
void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
@@ -3878,6 +3902,11 @@ void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_sysfs_user_del_info);
|
||||
|
||||
/*
|
||||
* Returns true if the reply received and being processed by another part of
|
||||
* the kernel, false otherwise. Also removes the user_info from the list to
|
||||
* fix for the user space that it missed the timeout.
|
||||
*/
|
||||
static bool scst_sysfs_user_info_executing(struct scst_sysfs_user_info *info)
|
||||
{
|
||||
bool res;
|
||||
@@ -3899,6 +3928,16 @@ static bool scst_sysfs_user_info_executing(struct scst_sysfs_user_info *info)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_wait_info_completion() - wait an user space event's completion
|
||||
*
|
||||
* Waits for the info request been completed by user space at most timeout
|
||||
* jiffies. If the reply received before timeout and being processed by
|
||||
* another part of the kernel, i.e. scst_sysfs_user_info_executing()
|
||||
* returned true, waits for it to complete indefinitely.
|
||||
*
|
||||
* Returns status of the request completion.
|
||||
*/
|
||||
int scst_wait_info_completion(struct scst_sysfs_user_info *info,
|
||||
unsigned long timeout)
|
||||
{
|
||||
|
||||
@@ -65,9 +65,21 @@ static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
|
||||
tasklet_schedule(&t->tasklet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same sess
|
||||
/**
|
||||
* scst_rx_cmd() - create new command
|
||||
* @sess: SCST session
|
||||
* @lun: LUN for the command
|
||||
* @lun_len: length of the LUN in bytes
|
||||
* @cdb: CDB of the command
|
||||
* @cdb_len: length of the CDB in bytes
|
||||
* @atomic: true, if current context is atomic
|
||||
*
|
||||
* Description:
|
||||
* Creates new SCST command. Returns new command on success or
|
||||
* NULL otherwise.
|
||||
*
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same session.
|
||||
*/
|
||||
struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len,
|
||||
@@ -202,6 +214,29 @@ out_redirect:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_cmd_init_done() - the command's initialization done
|
||||
* @cmd: SCST command
|
||||
* @pref_context: preferred command execution context
|
||||
*
|
||||
* Description:
|
||||
* Notifies SCST that the driver finished its part of the command
|
||||
* initialization, and the command is ready for execution.
|
||||
* The second argument sets preferred command execition context.
|
||||
* See SCST_CONTEXT_* constants for details.
|
||||
*
|
||||
* !!IMPORTANT!!
|
||||
*
|
||||
* If cmd->set_sn_on_restart_cmd not set, this function, as well as
|
||||
* scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be
|
||||
* called simultaneously for the same session (more precisely,
|
||||
* for the same session/LUN, i.e. tgt_dev), i.e. they must be
|
||||
* somehow externally serialized. This is needed to have lock free fast
|
||||
* path in scst_cmd_set_sn(). For majority of targets those functions are
|
||||
* naturally serialized by the single source of commands. Only iSCSI
|
||||
* immediate commands with multiple connections per session seems to be an
|
||||
* exception. For it, some mutex/lock shall be used for the serialization.
|
||||
*/
|
||||
void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context)
|
||||
{
|
||||
@@ -846,6 +881,22 @@ static int scst_preprocessing_done(struct scst_cmd *cmd)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_restart_cmd() - restart execution of the command
|
||||
* @cmd: SCST commands
|
||||
* @status: completion status
|
||||
* @pref_context: preferred command execition context
|
||||
*
|
||||
* Description:
|
||||
* Notifies SCST that the driver finished its part of the command's
|
||||
* preprocessing and it is ready for further processing.
|
||||
*
|
||||
* The second argument sets completion status
|
||||
* (see SCST_PREPROCESS_STATUS_* constants for details)
|
||||
*
|
||||
* See also comment for scst_cmd_init_done() for the serialization
|
||||
* requirements.
|
||||
*/
|
||||
void scst_restart_cmd(struct scst_cmd *cmd, int status,
|
||||
enum scst_exec_context pref_context)
|
||||
{
|
||||
@@ -1089,6 +1140,19 @@ static void scst_process_redirect_cmd(struct scst_cmd *cmd,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_rx_data() - the command's data received
|
||||
* @cmd: SCST commands
|
||||
* @status: data receiving completion status
|
||||
* @pref_context: preferred command execition context
|
||||
*
|
||||
* Description:
|
||||
* Notifies SCST that the driver received all the necessary data
|
||||
* and the command is ready for further processing.
|
||||
*
|
||||
* The second argument sets data receiving completion status
|
||||
* (see SCST_RX_STATUS_* constants for details)
|
||||
*/
|
||||
void scst_rx_data(struct scst_cmd *cmd, int status,
|
||||
enum scst_exec_context pref_context)
|
||||
{
|
||||
@@ -1818,7 +1882,20 @@ out_done:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No locks, no IRQ or IRQ-disabled context allowed */
|
||||
/**
|
||||
* scst_check_local_events() - check if there are any local SCSI events
|
||||
*
|
||||
* Description:
|
||||
* Checks if the command can be executed or there are local events,
|
||||
* like reservatons, pending UAs, etc. Returns < 0 if command must be
|
||||
* aborted, > 0 if there is an event and command should be immediately
|
||||
* completed, or 0 otherwise.
|
||||
*
|
||||
* !! Dev handlers implementing exec() callback must call this function there
|
||||
* !! just before the actual command's execution!
|
||||
*
|
||||
* On call no locks, no IRQ or IRQ-disabled context allowed.
|
||||
*/
|
||||
int scst_check_local_events(struct scst_cmd *cmd)
|
||||
{
|
||||
int res, rc;
|
||||
@@ -3072,6 +3149,18 @@ out_error:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_tgt_cmd_done() - the command's processing done
|
||||
* @cmd: SCST command
|
||||
* @pref_context: preferred command execution context
|
||||
*
|
||||
* Description:
|
||||
* Notifies SCST that the driver sent the response and the command
|
||||
* can be freed now. Don't forget to set the delivery status, if it
|
||||
* isn't success, using scst_set_delivery_status() before calling
|
||||
* this function. The third argument sets preferred command execition
|
||||
* context (see SCST_CONTEXT_* constants for details)
|
||||
*/
|
||||
void scst_tgt_cmd_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context)
|
||||
{
|
||||
@@ -3539,7 +3628,16 @@ int scst_init_thread(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called with no locks held */
|
||||
/**
|
||||
* scst_process_active_cmd() - process active command
|
||||
*
|
||||
* Description:
|
||||
* Main SCST commands processing routing. Must be used only by dev handlers.
|
||||
*
|
||||
* Argument atomic is true, if function called in atomic context.
|
||||
*
|
||||
* Must be called with no locks held.
|
||||
*/
|
||||
void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
{
|
||||
int res;
|
||||
@@ -3702,6 +3800,13 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_process_active_cmd);
|
||||
|
||||
/**
|
||||
* scst_post_parse_process_active_cmd() - process command after parse
|
||||
*
|
||||
* SCST commands processing routine, which should be called by dev handler
|
||||
* after its parse() callback returned SCST_CMD_STATE_STOP. Arguments are
|
||||
* the same as for scst_process_active_cmd().
|
||||
*/
|
||||
void scst_post_parse_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
{
|
||||
scst_set_parse_time(cmd);
|
||||
@@ -3989,7 +4094,14 @@ out:
|
||||
return mcmd->cmd_finish_wait_count;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
/**
|
||||
* scst_prepare_async_mcmd() - prepare async management command
|
||||
*
|
||||
* Notifies SCST that management command is going to be async, i.e.
|
||||
* will be completed in another context.
|
||||
*
|
||||
* No SCST locks supposed to be held on entrance.
|
||||
*/
|
||||
void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -4009,7 +4121,14 @@ void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_prepare_async_mcmd);
|
||||
|
||||
/* No locks */
|
||||
/**
|
||||
* scst_async_mcmd_completed() - async management command completed
|
||||
*
|
||||
* Notifies SCST that async management command, prepared by
|
||||
* scst_prepare_async_mcmd(), completed.
|
||||
*
|
||||
* No SCST locks supposed to be held on entrance.
|
||||
*/
|
||||
void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -5316,9 +5435,16 @@ out_unlock:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same sess
|
||||
/**
|
||||
* scst_rx_mgmt_fn() - create new management command and send it for execution
|
||||
*
|
||||
* Description:
|
||||
* Creates new management command and sends it for execution.
|
||||
*
|
||||
* Returns 0 for success, error code otherwise.
|
||||
*
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same sess.
|
||||
*/
|
||||
int scst_rx_mgmt_fn(struct scst_session *sess,
|
||||
const struct scst_rx_mgmt_params *params)
|
||||
@@ -5498,7 +5624,7 @@ static struct scst_acg *scst_find_tgt_acg_by_name_wild(struct scst_tgt *tgt,
|
||||
if (initiator_name == NULL)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(acg, &tgt->acg_list, acg_list_entry) {
|
||||
list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
|
||||
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
|
||||
if (wildcmp(n->name, initiator_name)) {
|
||||
TRACE_DBG("Access control group %s found",
|
||||
@@ -5622,6 +5748,48 @@ restart:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_register_session() - register session
|
||||
* @tgt: target
|
||||
* @atomic: true, if the function called in the atomic context. If false,
|
||||
* this function will block until the session registration is
|
||||
* completed.
|
||||
* @initiator_name: remote initiator's name, any NULL-terminated string,
|
||||
* e.g. iSCSI name, which used as the key to found appropriate
|
||||
* access control group. Could be NULL, then the default
|
||||
* target's LUNs are used.
|
||||
* @data: any target driver supplied data
|
||||
* @result_fn: pointer to the function that will be asynchronously called
|
||||
* when session initialization finishes.
|
||||
* Can be NULL. Parameters:
|
||||
* - sess - session
|
||||
* - data - target driver supplied to scst_register_session()
|
||||
* data
|
||||
* - result - session initialization result, 0 on success or
|
||||
* appropriate error code otherwise
|
||||
*
|
||||
* Description:
|
||||
* Registers new session. Returns new session on success or NULL otherwise.
|
||||
*
|
||||
* Note: A session creation and initialization is a complex task,
|
||||
* which requires sleeping state, so it can't be fully done
|
||||
* in interrupt context. Therefore the "bottom half" of it, if
|
||||
* scst_register_session() is called from atomic context, will be
|
||||
* done in SCST thread context. In this case scst_register_session()
|
||||
* will return not completely initialized session, but the target
|
||||
* driver can supply commands to this session via scst_rx_cmd().
|
||||
* Those commands processing will be delayed inside SCST until
|
||||
* the session initialization is finished, then their processing
|
||||
* will be restarted. The target driver will be notified about
|
||||
* finish of the session initialization by function result_fn().
|
||||
* On success the target driver could do nothing, but if the
|
||||
* initialization fails, the target driver must ensure that
|
||||
* no more new commands being sent or will be sent to SCST after
|
||||
* result_fn() returns. All already sent to SCST commands for
|
||||
* failed session will be returned in xmit_response() with BUSY status.
|
||||
* In case of failure the driver shall call scst_unregister_session()
|
||||
* inside result_fn(), it will NOT be called automatically.
|
||||
*/
|
||||
struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
|
||||
const char *initiator_name, void *data,
|
||||
void (*result_fn) (struct scst_session *sess, void *data, int result))
|
||||
@@ -5666,9 +5834,38 @@ out_free:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_register_session);
|
||||
|
||||
/*
|
||||
* Must not be called in parallel with scst_rx_cmd() or
|
||||
* scst_rx_mgmt_fn_*() for the same sess
|
||||
/**
|
||||
* scst_unregister_session() - unregister session
|
||||
* @sess: session to be unregistered
|
||||
* @wait: if true, instructs to wait until all commands, which
|
||||
* currently is being executed and belonged to the session,
|
||||
* finished. Otherwise, target driver should be prepared to
|
||||
* receive xmit_response() for the session's command after
|
||||
* scst_unregister_session() returns.
|
||||
* @unreg_done_fn: pointer to the function that will be asynchronously called
|
||||
* when the last session's command finishes and
|
||||
* the session is about to be completely freed. Can be NULL.
|
||||
* Parameter:
|
||||
* - sess - session
|
||||
*
|
||||
* Unregisters session.
|
||||
*
|
||||
* Notes:
|
||||
* - All outstanding commands will be finished regularly. After
|
||||
* scst_unregister_session() returned, no new commands must be sent to
|
||||
* SCST via scst_rx_cmd().
|
||||
*
|
||||
* - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is
|
||||
* called in paralell with scst_unregister_session().
|
||||
*
|
||||
* - Can be called before result_fn() of scst_register_session() called,
|
||||
* i.e. during the session registration/initialization.
|
||||
*
|
||||
* - It is highly recommended to call scst_unregister_session() as soon as it
|
||||
* gets clear that session will be unregistered and not to wait until all
|
||||
* related commands finished. This function provides the wait functionality,
|
||||
* but it also starts recovering stuck commands, if there are any.
|
||||
* Otherwise, your target driver could wait for those commands forever.
|
||||
*/
|
||||
void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess))
|
||||
@@ -5867,6 +6064,13 @@ static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_find_cmd() - find command by custom comparison function
|
||||
*
|
||||
* Finds a command based on user supplied data and comparision
|
||||
* callback function, that should return true, if the command is found.
|
||||
* Returns the command on success or NULL otherwise
|
||||
*/
|
||||
struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
|
||||
int (*cmp_fn) (struct scst_cmd *cmd,
|
||||
void *data))
|
||||
@@ -5907,6 +6111,13 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_find_cmd);
|
||||
|
||||
/**
|
||||
* scst_find_cmd_by_tag() - find command by tag
|
||||
*
|
||||
* Finds a command based on the supplied tag comparing it with one
|
||||
* that previously set by scst_cmd_set_tag(). Returns the found command on
|
||||
* success or NULL otherwise
|
||||
*/
|
||||
struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess,
|
||||
uint64_t tag)
|
||||
{
|
||||
@@ -5918,23 +6129,3 @@ struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess,
|
||||
return cmd;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_find_cmd_by_tag);
|
||||
|
||||
void *scst_cmd_get_tgt_priv_lock(struct scst_cmd *cmd)
|
||||
{
|
||||
void *res;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&scst_main_lock, flags);
|
||||
res = cmd->tgt_priv;
|
||||
spin_unlock_irqrestore(&scst_main_lock, flags);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cmd_get_tgt_priv_lock);
|
||||
|
||||
void scst_cmd_set_tgt_priv_lock(struct scst_cmd *cmd, void *val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&scst_main_lock, flags);
|
||||
cmd->tgt_priv = val;
|
||||
spin_unlock_irqrestore(&scst_main_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cmd_set_tgt_priv_lock);
|
||||
|
||||
Reference in New Issue
Block a user