- 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:
Vladislav Bolkhovitin
2010-04-10 19:47:32 +00:00
parent 458e83c957
commit 0b0e104049
10 changed files with 846 additions and 593 deletions

View File

@@ -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.

View File

@@ -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, &params);
}
/*
* 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 */

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);