The major TM processing cleanup in scst_user module which was possible after the recent SCST changes, to fix current problems. Also there are fixes for found during development/testing problems. Particularly:

- PRIO queue was removed from scst_user. Instead, all priority commands now queued in the head of the regular queue. The corresponding code was removed from fileio_tgt as well. It necessary, in the future the priority queue can be easily restored from this patch.

 - pre_unreg_sess() was removed from struct scst_dev_type. The corresponding code was removed from SCST core as well

 - Almost all /proc/scsi_tgt commands now can fail after timeout (90 seconds) with EBUSY

 - Fixed possible incorrect command's retry if double RESET UA is detected.

 - Many minor changes and cleanups

Also docs were updated.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@403 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2008-05-31 12:05:02 +00:00
parent ecb27e7444
commit 994b72d114
31 changed files with 895 additions and 960 deletions

View File

@@ -2,7 +2,7 @@
USER SPACE INTERFACE DESCRIPTION.
Version 0.9.6/3
Version 0.9.6/4
I. Description.
@@ -103,7 +103,6 @@ struct scst_user_opt
uint8_t parse_type;
uint8_t on_free_cmd_type;
uint8_t memory_reuse_type;
uint8_t prio_queue_type;
uint8_t partial_transfers_type;
uint32_t partial_len;
@@ -156,18 +155,6 @@ where:
* SCST_USER_MEM_REUSE_ALL - unlimited memory reuse is possible.
- prio_queue_type - defines if the user space handler need to receive
all management subcommands from a separate PRIO queue using
SCST_USER_REPLY_AND_GET_PRIO_CMD command. Management subcommands are:
SCST_USER_ATTACH_SESS, SCST_USER_DETACH_SESS and SCST_USER_TASK_MGMT.
Possible values are:
* SCST_USER_PRIO_QUEUE_SINGLE - a single queue is used for regular
and management subcommands
* SCST_USER_PRIO_QUEUE_SEPARATE - a separate PRIO queue is used for
management subcommands
- partial_transfers_type - defines if the user space handler supports
partial data transfers, when a SCSI command, which required big data
transfer, is broken on several subcommands with smaller data
@@ -312,7 +299,7 @@ SCST_USER_PARSE returns SCSI command on PARSE state of the SCST
processing. The PARSE state is intended to check validity of the
command, determine data transfer type and the necessary data buffer
size. This subcommand is returned only if SCST_USER_SET_OPTIONS
parse_type isn'e set to SCST_USER_PARSE_STANDARD. In this case the
parse_type isn't set to SCST_USER_PARSE_STANDARD. In this case the
standard SCST internal parser for this SCSI device type will do all the
job.
@@ -715,23 +702,8 @@ Possible return values are:
- SCST_MGMT_STATUS_FAILED - task management function failed
5. SCST_USER_REPLY_AND_GET_PRIO_CMD
SCST_USER_REPLY_AND_GET_PRIO_CMD is the same as
SCST_USER_REPLY_AND_GET_CMD, except that it returns management (i.e.
priority) subcommands from priority queue, if usage of a separate PRIO
was configured.
Management subcommands are: SCST_USER_ATTACH_SESS, SCST_USER_DETACH_SESS
and SCST_USER_TASK_MGMT.
PRIO queue is always blocking, because poll() doesn't support, when
different threads wait with different events mask. Only one thread is
woken up on each event and if it isn't interested in such events,
another (interested) one will not be woken up.
6. SCST_USER_REPLY_CMD
5. SCST_USER_REPLY_CMD
SCST_USER_REPLY_CMD IOCTL function allows the user space handler to
return the result of a command's execution. Its argument is defined as:
@@ -841,8 +813,8 @@ involve data transfer from target to initiator) and WRITE-type (i.e.
which involve data transfer from initiator to target) commands. So the
device is configured with parse_type SCST_USER_PARSE_STANDARD,
on_free_cmd_type SCST_USER_ON_FREE_CMD_IGNORE, memory_reuse_type
SCST_USER_MEM_REUSE_ALL, prio_queue_type SCST_USER_PRIO_QUEUE_SINGLE and
partial_transfers_type SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED.
SCST_USER_MEM_REUSE_ALL and partial_transfers_type
SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED.
Then it prepares struct scst_user_get_cmd with reply set to 0, calls
SCST_USER_REPLY_AND_GET_CMD ioctl() and waits until some initiator

View File

@@ -32,6 +32,16 @@ Installation
Basically as in README-IET, where file names are changed as specified
above.
Only vanilla kernels from kernel.org are supported, but it should work
on vendors' kernels, if you manage to successfully compile on them. The
main problem with vendor's kernels is that they often contain patches,
which will appear only in the next version of the vanilla kernel,
therefore it's quite hard to track such changes. Thus, if during
compilation for some vendor kernel your compiler complains about
redefinition of some symbol, you should either switch to vanilla kernel,
or change as necessary the corresponding to that symbol "#if
LINUX_VERSION_CODE" statement.
If during compilation you see message like "*** No rule to make target
`xxx.h', needed by `yyy.o'. Stop.", then your autogenerated
dependencies don't match your compiler configuration anymore. You should
@@ -189,5 +199,7 @@ Thanks to:
debugging
* Tomasz Chmielewski <mangoo@wpkg.org> for testing and suggestions
* Bart Van Assche <bart.vanassche@gmail.com> for a lot of help
Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net

View File

@@ -408,9 +408,27 @@ static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
long err;
u32 id;
if (cmd == REGISTER_USERD) {
switch (cmd) {
case ADD_TARGET:
case DEL_TARGET:
case ADD_SESSION:
case DEL_SESSION:
case GET_SESSION_INFO:
case ISCSI_PARAM_SET:
case ISCSI_PARAM_GET:
case ADD_CONN:
case DEL_CONN:
case GET_CONN_INFO:
break;
case REGISTER_USERD:
err = iscsi_check_version(arg);
goto out;
default:
PRINT_ERROR("Invalid ioctl cmd %x", cmd);
err = -EINVAL;
goto out;
}
if ((err = get_user(id, (u32 *) arg)) != 0)
@@ -440,7 +458,7 @@ static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
if (!target) {
PRINT_ERROR("can't find the target %u", id);
PRINT_ERROR("Can't find the target %u", id);
err = -EINVAL;
goto out_unlock;
}
@@ -481,8 +499,7 @@ static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
default:
PRINT_ERROR("invalid ioctl cmd %x", cmd);
err = -EINVAL;
sBUG();
break;
}

View File

@@ -467,7 +467,9 @@ static inline void cmnd_put(struct iscsi_cmnd *cmnd)
{
TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
atomic_read(&cmnd->ref_cnt)-1);
sBUG_ON(atomic_read(&cmnd->ref_cnt) == 0);
EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) == 0);
if (atomic_dec_and_test(&cmnd->ref_cnt))
cmnd_done(cmnd);
}

View File

@@ -119,6 +119,7 @@ static int iscsi_target_create(struct target_info *info, u32 tid)
target->scst_tgt = scst_register(&iscsi_template, target->name);
if (!target->scst_tgt) {
PRINT_ERROR("%s", "scst_register() failed");
err = -EBUSY;
goto out_free;
}

View File

@@ -83,6 +83,7 @@ static int ctrdev_open(int *max_data_seg_len)
}
reg.version = (uintptr_t)ISCSI_SCST_INTERFACE_VERSION;
err = ioctl(ctlfd, REGISTER_USERD, &reg);
if (err < 0) {
log_error("Unable to register: %s. Incompatible version of the "

View File

@@ -109,7 +109,16 @@ void text_key_add(struct connection *conn, char *key, char *value)
conn->rsp.data = conn->rsp_buffer;
}
if (conn->rsp.datasize + len > INCOMING_BUFSIZE) {
log_warning("Dropping key (%s=%s)", key, value);
/* ToDo: multi-PDU replies */
log_warning("Dropping key (%s=%s) due to INCOMING_BUFSIZE "
"limit %d and because only single PDU replies during "
"discovery session are implemented. If you have "
"a lot of targets, you can increase INCOMING_BUFSIZE, "
"but, since it will be against iSCSI RFC required "
"not-negotiated PDU limit, not all initiators might "
"work with it. Alternatively, you can decrease names "
"of your targets so they will fit to INCOMING_BUFSIZE "
"limit", key, value, INCOMING_BUFSIZE);
return;
}

View File

@@ -15,9 +15,7 @@ simultaneously, is supported as well.
This version is compatible with SCST version 0.9.5 and higher.
Tested on stable kernels from http://www.kernel.org. The original
initiator driver was taken from kernel version 2.6.17.8, but it should
also work on other versions, including 2.6.18.x and 2.6.16.x.
The original initiator driver was taken from the kernel 2.6.17.8.
See also "ToDo" file for list of known issues and unimplemented
features.
@@ -25,6 +23,16 @@ features.
Installation
------------
Only vanilla kernels from kernel.org are supported, but it should work
on vendors' kernels, if you manage to successfully compile on them. The
main problem with vendor's kernels is that they often contain patches,
which will appear only in the next version of the vanilla kernel,
therefore it's quite hard to track such changes. Thus, if during
compilation for some vendor kernel your compiler complains about
redefinition of some symbol, you should either switch to vanilla kernel,
or change as necessary the corresponding to that symbol "#if
LINUX_VERSION_CODE" statement.
At first, make sure that the link "/lib/modules/`you_kernel_version`/build"
points to the source code for your currently running kernel.

View File

@@ -42,11 +42,19 @@ of devices with different access permissions. See below for details.
This is quite stable (but still beta) version.
Tested mostly on "vanilla" 2.6.21.1 kernel from kernel.org.
Installation
------------
Only vanilla kernels from kernel.org are supported, but it should work
on vendors' kernels, if you manage to successfully compile on them. The
main problem with vendor's kernels is that they often contain patches,
which will appear only in the next version of the vanilla kernel,
therefore it's quite hard to track such changes. Thus, if during
compilation for some vendor kernel your compiler complains about
redefinition of some symbol, you should either switch to vanilla kernel,
or change as necessary the corresponding to that symbol "#if
LINUX_VERSION_CODE" statement.
At first, make sure that the link "/lib/modules/`you_kernel_version`/build"
points to the source code for your currently running kernel.
@@ -476,9 +484,23 @@ will open file /vdisks/disk1 as virtual FILEIO disk with name "disk1".
CAUTION: If you partitioned/formatted your device with block size X, *NEVER*
======== ever try to export and then mount it (even accidentally) with another
block size. Otherwise you can *instantly* damage it pretty
badly as well as all your data on it. Messages on initiator like:
"attempt to access beyond end of device" is the sign of such
damage.
badly as well as all your data on it. Messages on initiator
like: "attempt to access beyond end of device" is the sign of
such damage.
Moreover, if you want to compare how well different block sizes
work for you, you **MUST** EVERY TIME AFTER CHANGING BLOCK SIZE
**COMPLETELY** **WIPE OFF** ALL THE DATA FROM THE DEVICE. In
other words, THE **WHOLE** DEVICE **MUST** HAVE ONLY **ZEROES**
AS THE DATA AFTER YOU SWITCH TO NEW BLOCK SIZE. Switching block
sizes isn't like switching between FILEIO and BLOCKIO, after
changing block size all previously written with another block
size data MUST BE ERASED. Otherwise you will have a full set of
very weird behaviors, because blocks addressing will be
changed, but initiators in most cases will not have a
possibility to detect that old addresses written on the device
in, e.g., partition table, don't refer anymore to what they are
intended to refer.
IMPORTANT: By default for performance reasons VDISK FILEIO devices use write
========= back caching policy. This is generally safe from the consistence of
@@ -835,4 +857,6 @@ Thanks to:
* Jianxi Chen <pacers@users.sourceforge.net> for fixing problem with
devices >2TB in size
* Bart Van Assche <bart.vanassche@gmail.com> for a lot of help
Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net

View File

@@ -289,12 +289,6 @@ typedef _Bool bool;
*/
#define SCST_EXEC_NEED_THREAD 2
/*************************************************************
** Default timeout for cmd's CDB execution
** by SCSI mid-level (cmd's "timeout" field).
*************************************************************/
#define SCST_DEFAULT_TIMEOUT (30*HZ)
/*
* Set if cmd is finished and there is status/sense to be sent.
* The status should be not sent (i.e. the flag not set) if the
@@ -334,11 +328,8 @@ typedef _Bool bool;
/* Set if session is initialized and ready */
#define SCST_SESS_SPH_READY 0
/* Set if session is on calling pre_unreg_sess() phase */
#define SCST_SESS_SPH_PRE_UNREG 1
/* Set if session is shutting down */
#define SCST_SESS_SPH_SHUTDOWN 2
#define SCST_SESS_SPH_SHUTDOWN 1
/*************************************************************
** Cmd's async (atomic) flags
@@ -383,6 +374,11 @@ typedef _Bool bool;
*************************************************************/
#define SCST_PROC_ENTRY_NAME "scsi_tgt"
/*************************************************************
** Activities suspending timeout
*************************************************************/
#define SCST_SUSPENDING_TIMEOUT (90 * HZ)
/*************************************************************
** Kernel cache creation helper
*************************************************************/
@@ -773,7 +769,7 @@ struct scst_dev_type {
* - SCST_MGMT_STATUS_SUCCESS - the command is done with success,
* no firther actions required
* - The SCST_MGMT_STATUS_* error code if the command is failed and
* no firther actions required
* no further actions required
* - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the command
* should be done
*
@@ -797,15 +793,6 @@ struct scst_dev_type {
*/
int (*attach_tgt) (struct scst_tgt_dev *tgt_dev);
/*
* Called when a session, corresponding to a tgt_dev, is about to be
* unregistered and the tgt_dev - detached. Supposed to be used to
* clean out "stalled" commands, which otherwise could prevent SCST
* from entering into the suspended activity state and, so,
* unregistering the device.
*/
void (*pre_unreg_sess) (struct scst_tgt_dev *tgt_dev);
/* Called when tgt_dev (session) is detaching from the dev handler */
void (*detach_tgt) (struct scst_tgt_dev *tgt_dev);
@@ -1172,7 +1159,7 @@ struct scst_cmd {
enum scst_cmd_queue_type queue_type;
int timeout; /* CDB execution timeout */
int timeout; /* CDB execution timeout in seconds */
int retries; /* Amount of retries that will be done by SCSI mid-level */
/* SCSI data direction, one of SCST_DATA_* constants */
@@ -1226,6 +1213,9 @@ struct scst_cmd {
*/
int orig_sg_cnt, orig_sg_entry, orig_entry_len;
/* Used to retry commands in case of double UA */
int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction;
/* List corresponding mgmt cmd, if any, protected by sess_list_lock */
struct list_head mgmt_cmd_list;
@@ -2302,22 +2292,30 @@ static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd,
mcmd->tgt_priv = val;
}
/*
* Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants)
*/
/* Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants) */
static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
{
return mcmd->status;
}
/*
* Returns mgmt cmd's TM fn
*/
/* Returns mgmt cmd's TM fn */
static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
{
return mcmd->fn;
}
/*
* Called by dev handler's task_mgmt_fn() to notify SCST core that mcmd
* is going to complete asynchronously.
*/
void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd);
/*
* Called by dev handler to notify SCST core that async. mcmd is completed
* with status "status".
*/
void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
static inline struct page *sg_page(struct scatterlist *sg)
@@ -2450,11 +2448,16 @@ static inline int scst_get_buf_count(struct scst_cmd *cmd)
/*
* Suspends and resumes any activity.
* scst_suspend_activity() doesn't return until there are any
* active commands (state after SCST_CMD_STATE_INIT). New arriving
* commands stay in that state until scst_resume_activity() is called.
* 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.
*/
void scst_suspend_activity(void);
int scst_suspend_activity(bool interruptible);
void scst_resume_activity(void);
/*

View File

@@ -280,4 +280,36 @@ static inline int scst_is_ua_sense(const uint8_t *sense)
#define POSITION_LEN_SHORT 20
#define POSITION_LEN_LONG 32
/*************************************************************
** Various timeouts
*************************************************************/
#define SCST_DEFAULT_TIMEOUT (60 * HZ)
#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ)
#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ)
#define SCST_GENERIC_PROCESSOR_TIMEOUT (3 * HZ)
#define SCST_GENERIC_PROCESSOR_LONG_TIMEOUT (14000 * HZ)
#define SCST_GENERIC_TAPE_SMALL_TIMEOUT (3 * HZ)
#define SCST_GENERIC_TAPE_REG_TIMEOUT (900 * HZ)
#define SCST_GENERIC_TAPE_LONG_TIMEOUT (14000 * HZ)
#define SCST_GENERIC_MODISK_SMALL_TIMEOUT (3 * HZ)
#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ)
#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ)
#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ)
#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ)
#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ)
#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ)
#define SCST_GENERIC_RAID_LONG_TIMEOUT (14000 * HZ)
#define SCST_GENERIC_CDROM_SMALL_TIMEOUT (3 * HZ)
#define SCST_GENERIC_CDROM_REG_TIMEOUT (900 * HZ)
#define SCST_GENERIC_CDROM_LONG_TIMEOUT (14000 * HZ)
#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ)
#endif /* __SCST_CONST_H */

View File

@@ -242,6 +242,15 @@ do { \
PRINT(NO_FLAG, "%s" format, __tflag, args); \
} while (0)
#define PRINT_WARNING(format, args...) \
do { \
if (strcmp(INFO_FLAG, LOG_FLAG)) \
{ \
PRINT_LOG_FLAG(LOG_FLAG, "***WARNING*** " format, args); \
} \
PRINT_LOG_FLAG(INFO_FLAG, "***WARNING*** " format, args); \
} while (0)
#define PRINT_ERROR(format, args...) \
do { \
if (strcmp(ERROR_FLAG, LOG_FLAG)) { \
@@ -341,6 +350,12 @@ do { \
PRINT(INFO_FLAG, "%s: " format, LOG_PREFIX, args); \
} while (0)
#define PRINT_WARNING(format, args...) \
do { \
PRINT(INFO_FLAG, "%s: ***WARNING*** " \
format, LOG_PREFIX, args); \
} while (0)
#define PRINT_ERROR(format, args...) \
do { \
PRINT(ERROR_FLAG, "%s: ***ERROR*** " \
@@ -360,6 +375,12 @@ do { \
PRINT(INFO_FLAG, format, args); \
} while (0)
#define PRINT_WARNING(format, args...) \
do { \
PRINT(INFO_FLAG, "***WARNING*** " \
format, args); \
} while (0)
#define PRINT_ERROR(format, args...) \
do { \
PRINT(ERROR_FLAG, "***ERROR*** " \

View File

@@ -49,10 +49,6 @@
#define SCST_USER_MEM_REUSE_ALL 3
#define SCST_USER_MAX_MEM_REUSE_OPT SCST_USER_MEM_REUSE_ALL
#define SCST_USER_PRIO_QUEUE_SINGLE 0
#define SCST_USER_PRIO_QUEUE_SEPARATE 1
#define SCST_USER_MAX_PRIO_QUEUE_OPT SCST_USER_PRIO_QUEUE_SEPARATE
#define SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED 0
#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED_ORDERED 1
#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED 2
@@ -77,20 +73,10 @@
#define UCMD_STATE_ATTACH_SESS 0x20
#define UCMD_STATE_DETACH_SESS 0x21
/* Must be changed under cmd_lists.cmd_list_lock */
#define UCMD_STATE_SENT_MASK 0x10000
#define UCMD_STATE_RECV_MASK 0x20000
#define UCMD_STATE_JAMMED_MASK 0x40000
#define UCMD_STATE_MASK (UCMD_STATE_SENT_MASK | \
UCMD_STATE_RECV_MASK | \
UCMD_STATE_JAMMED_MASK)
struct scst_user_opt {
uint8_t parse_type;
uint8_t on_free_cmd_type;
uint8_t memory_reuse_type;
uint8_t prio_queue_type;
uint8_t partial_transfers_type;
int32_t partial_len;
@@ -125,7 +111,7 @@ struct scst_user_scsi_cmd_parse {
uint8_t cdb[SCST_MAX_CDB_SIZE];
int32_t cdb_len;
uint32_t timeout;
int32_t timeout;
int32_t bufflen;
uint8_t queue_type;
@@ -165,7 +151,7 @@ struct scst_user_scsi_cmd_exec {
uint8_t queue_type;
uint8_t data_direction;
uint8_t partial;
uint32_t timeout;
int32_t timeout;
uint32_t sn;
@@ -249,8 +235,7 @@ struct scst_user_reply_cmd {
#define SCST_USER_SET_OPTIONS _IOW('u', 3, struct scst_user_opt)
#define SCST_USER_GET_OPTIONS _IOR('u', 4, struct scst_user_opt)
#define SCST_USER_REPLY_AND_GET_CMD _IOWR('u', 5, struct scst_user_get_cmd)
#define SCST_USER_REPLY_AND_GET_PRIO_CMD _IOWR('u', 6, struct scst_user_get_cmd)
#define SCST_USER_REPLY_CMD _IOW('u', 7, struct scst_user_reply_cmd)
#define SCST_USER_REPLY_CMD _IOW('u', 6, struct scst_user_reply_cmd)
/* Values for scst_user_get_cmd.subcode */
#define SCST_USER_ATTACH_SESS _IOR('s', UCMD_STATE_ATTACH_SESS, struct scst_user_sess)

View File

@@ -38,10 +38,6 @@
.dev_done = cdrom_done, \
}
#define CDROM_SMALL_TIMEOUT (3 * HZ)
#define CDROM_REG_TIMEOUT (900 * HZ)
#define CDROM_LONG_TIMEOUT (14000 * HZ)
#define CDROM_DEF_BLOCK_SHIFT 11
struct cdrom_params {
@@ -114,7 +110,7 @@ int cdrom_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
CDROM_REG_TIMEOUT, 3, 0);
SCST_GENERIC_CDROM_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -218,13 +214,6 @@ int cdrom_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = CDROM_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = CDROM_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = CDROM_LONG_TIMEOUT;
return res;
}

View File

@@ -38,8 +38,6 @@
}
#define CHANGER_RETRIES 2
#define CHANGER_TIMEOUT (3 * HZ)
#define CHANGER_LONG_TIMEOUT (14000 * HZ)
#define READ_CAP_LEN 8
int changer_attach(struct scst_device *);
@@ -85,8 +83,8 @@ int changer_attach(struct scst_device *dev)
retries = SCST_DEV_UA_RETRIES;
do {
TRACE_DBG("%s", "Doing TEST_UNIT_READY");
res = scsi_test_unit_ready(dev->scsi_dev, CHANGER_TIMEOUT,
CHANGER_RETRIES
res = scsi_test_unit_ready(dev->scsi_dev,
SCST_GENERIC_CHANGER_TIMEOUT, CHANGER_RETRIES
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
);
#else
@@ -149,11 +147,6 @@ int changer_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = CHANGER_LONG_TIMEOUT;
else
cmd->timeout = CHANGER_TIMEOUT;
return res;
}

View File

@@ -57,10 +57,6 @@
.exec = disk_exec, \
}
#define DISK_SMALL_TIMEOUT (3 * HZ)
#define DISK_REG_TIMEOUT (60 * HZ)
#define DISK_LONG_TIMEOUT (3600 * HZ)
#define DISK_DEF_BLOCK_SHIFT 9
struct disk_params {
@@ -190,7 +186,7 @@ int disk_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
DISK_REG_TIMEOUT, 3, 0);
SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -291,13 +287,6 @@ int disk_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = DISK_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = DISK_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = DISK_LONG_TIMEOUT;
return res;
}

View File

@@ -57,10 +57,6 @@
.exec = modisk_exec, \
}
#define MODISK_SMALL_TIMEOUT (3 * HZ)
#define MODISK_REG_TIMEOUT (900 * HZ)
#define MODISK_LONG_TIMEOUT (14000 * HZ)
#define MODISK_DEF_BLOCK_SHIFT 10
struct modisk_params {
@@ -201,7 +197,7 @@ int modisk_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
MODISK_REG_TIMEOUT, 3, 0);
SCST_GENERIC_MODISK_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -308,13 +304,6 @@ int modisk_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = MODISK_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = MODISK_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = MODISK_LONG_TIMEOUT;
return res;
}

View File

@@ -38,8 +38,6 @@
}
#define PROCESSOR_RETRIES 2
#define PROCESSOR_TIMEOUT (3 * HZ)
#define PROCESSOR_LONG_TIMEOUT (14000 * HZ)
#define READ_CAP_LEN 8
int processor_attach(struct scst_device *);
@@ -85,8 +83,8 @@ int processor_attach(struct scst_device *dev)
retries = SCST_DEV_UA_RETRIES;
do {
TRACE_DBG("%s", "Doing TEST_UNIT_READY");
res = scsi_test_unit_ready(dev->scsi_dev, PROCESSOR_TIMEOUT,
PROCESSOR_RETRIES
res = scsi_test_unit_ready(dev->scsi_dev,
SCST_GENERIC_PROCESSOR_TIMEOUT, PROCESSOR_RETRIES
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
);
#else
@@ -149,10 +147,6 @@ int processor_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = PROCESSOR_LONG_TIMEOUT;
else
cmd->timeout = PROCESSOR_TIMEOUT;
return res;
}

View File

@@ -38,8 +38,6 @@
}
#define RAID_RETRIES 2
#define RAID_TIMEOUT (3 * HZ)
#define RAID_LONG_TIMEOUT (14000 * HZ)
#define READ_CAP_LEN 8
int raid_attach(struct scst_device *);
@@ -85,8 +83,8 @@ int raid_attach(struct scst_device *dev)
retries = SCST_DEV_UA_RETRIES;
do {
TRACE_DBG("%s", "Doing TEST_UNIT_READY");
res = scsi_test_unit_ready(dev->scsi_dev, RAID_TIMEOUT,
RAID_RETRIES
res = scsi_test_unit_ready(dev->scsi_dev,
SCST_GENERIC_RAID_TIMEOUT, RAID_RETRIES
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
);
#else
@@ -149,10 +147,6 @@ int raid_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = RAID_LONG_TIMEOUT;
else
cmd->timeout = RAID_TIMEOUT;
return res;
}

View File

@@ -59,10 +59,6 @@
#define TAPE_RETRIES 2
#define TAPE_SMALL_TIMEOUT (3 * HZ)
#define TAPE_REG_TIMEOUT (900 * HZ)
#define TAPE_LONG_TIMEOUT (14000 * HZ)
#define TAPE_DEF_BLOCK_SIZE 512
/* The fixed bit in READ/WRITE/VERIFY */
@@ -181,8 +177,8 @@ int tape_attach(struct scst_device *dev)
retries = SCST_DEV_UA_RETRIES;
do {
TRACE_DBG("%s", "Doing TEST_UNIT_READY");
res = scsi_test_unit_ready(dev->scsi_dev, TAPE_SMALL_TIMEOUT,
TAPE_RETRIES
res = scsi_test_unit_ready(dev->scsi_dev,
SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
);
#else
@@ -201,7 +197,7 @@ int tape_attach(struct scst_device *dev)
((dev->scsi_dev->lun << 5) & 0xe0) : 0),
0 /* Mode Page 0 */,
buffer, buffer_size,
TAPE_SMALL_TIMEOUT, TAPE_RETRIES,
SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES,
&data, NULL);
TRACE_DBG("MODE_SENSE done: %x", res);
@@ -301,13 +297,6 @@ int tape_parse(struct scst_cmd *cmd)
cmd->retries = SCST_PASSTHROUGH_RETRIES;
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = TAPE_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = TAPE_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = TAPE_LONG_TIMEOUT;
return res;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1956,7 +1956,7 @@ static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
unsigned long, loff_t);
ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
{
struct kiocb kiocb;
@@ -3115,7 +3115,9 @@ static int vcdrom_change(char *p, char *name)
virt_dev->file_name = fn;
}
scst_suspend_activity();
res = scst_suspend_activity(true);
if (res != 0)
goto out_free;
if (virt_dev->prevent_allow_medium_removal) {
PRINT_ERROR("Prevent medium removal for "

View File

@@ -34,6 +34,13 @@ static inline int get_current_tid(void)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
return current->pid;
#else
if (in_interrupt()) {
/*
* Unfortunately, task_pid_vnr() isn't IRQ-safe, so otherwise
* it can oops. ToDo.
*/
return 0;
}
return task_pid_vnr(current);
#endif
}

View File

@@ -95,9 +95,12 @@ void scst_set_cmd_error_status(struct scst_cmd *cmd, int status)
cmd->status = status;
cmd->host_status = DID_OK;
cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len;
cmd->dbl_ua_orig_data_direction = cmd->data_direction;
cmd->data_direction = SCST_DATA_NONE;
cmd->is_send_status = 1;
cmd->resp_data_len = 0;
cmd->is_send_status = 1;
cmd->completed = 1;
@@ -1065,7 +1068,7 @@ static void scst_send_release(struct scst_device *dev)
TRACE(TRACE_DEBUG | TRACE_SCSI, "Sending RELEASE req %p to SCSI "
"mid-level", req);
scst_do_req(req, req->sr_cmnd, (void *)req->sr_buffer, req->sr_bufflen,
scst_req_done, SCST_DEFAULT_TIMEOUT, 3);
scst_req_done, 15, 3);
out:
TRACE_EXIT();
@@ -1100,7 +1103,7 @@ static void scst_send_release(struct scst_device *dev)
TRACE(TRACE_DEBUG | TRACE_SCSI, "%s", "Sending RELEASE req to "
"SCSI mid-level");
rc = scsi_execute(scsi_dev, cdb, SCST_DATA_NONE, NULL, 0,
sense, SCST_DEFAULT_TIMEOUT, 0, 0);
sense, 15, 0, 0);
TRACE_DBG("MODE_SENSE done: %x", rc);
if (scsi_status_is_good(rc)) {
@@ -1320,6 +1323,8 @@ struct scst_cmd *scst_alloc_cmd(int gfp_mask)
cmd->data_len = -1;
cmd->is_send_status = 1;
cmd->resp_data_len = -1;
cmd->dbl_ua_orig_resp_data_len = -1;
cmd->dbl_ua_orig_data_direction = SCST_DATA_UNKNOWN;
out:
TRACE_EXIT();
@@ -1996,7 +2001,7 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len = cmd->bufflen << get_block_shift(cmd);
cmd->bufflen = 0;
goto out;
goto set_timeout;
} else
cmd->data_len = 0;
break;
@@ -2013,7 +2018,14 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
cmd->bufflen = cmd->bufflen << get_block_shift(cmd);
}
out:
set_timeout:
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = SCST_GENERIC_DISK_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_DISK_LONG_TIMEOUT;
TRACE_DBG("res %d, bufflen %d, data_len %d, direct %d",
res, cmd->bufflen, cmd->data_len, cmd->data_direction);
@@ -2047,7 +2059,7 @@ int scst_cdrom_generic_parse(struct scst_cmd *cmd,
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len = cmd->bufflen << get_block_shift(cmd);
cmd->bufflen = 0;
goto out;
goto set_timeout;
}
break;
default:
@@ -2058,7 +2070,14 @@ int scst_cdrom_generic_parse(struct scst_cmd *cmd,
if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = cmd->bufflen << get_block_shift(cmd);
out:
set_timeout:
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = SCST_GENERIC_CDROM_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = SCST_GENERIC_CDROM_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_CDROM_LONG_TIMEOUT;
TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
cmd->data_direction);
@@ -2092,7 +2111,7 @@ int scst_modisk_generic_parse(struct scst_cmd *cmd,
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len = cmd->bufflen << get_block_shift(cmd);
cmd->bufflen = 0;
goto out;
goto set_timeout;
}
break;
default:
@@ -2103,7 +2122,14 @@ int scst_modisk_generic_parse(struct scst_cmd *cmd,
if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = cmd->bufflen << get_block_shift(cmd);
out:
set_timeout:
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = SCST_GENERIC_MODISK_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = SCST_GENERIC_MODISK_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_MODISK_LONG_TIMEOUT;
TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
cmd->data_direction);
@@ -2145,6 +2171,13 @@ int scst_tape_generic_parse(struct scst_cmd *cmd,
if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1])
cmd->bufflen = cmd->bufflen * get_block_size(cmd);
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
cmd->timeout = SCST_GENERIC_TAPE_REG_TIMEOUT;
else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
cmd->timeout = SCST_GENERIC_TAPE_SMALL_TIMEOUT;
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_TAPE_LONG_TIMEOUT;
TRACE_EXIT_RES(res);
return res;
}
@@ -2180,21 +2213,42 @@ static int scst_null_parse(struct scst_cmd *cmd)
int scst_changer_generic_parse(struct scst_cmd *cmd,
int (*nothing)(struct scst_cmd *cmd))
{
return scst_null_parse(cmd);
int res = scst_null_parse(cmd);
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_CHANGER_LONG_TIMEOUT;
else
cmd->timeout = SCST_GENERIC_CHANGER_TIMEOUT;
return res;
}
EXPORT_SYMBOL(scst_changer_generic_parse);
int scst_processor_generic_parse(struct scst_cmd *cmd,
int (*nothing)(struct scst_cmd *cmd))
{
return scst_null_parse(cmd);
int res = scst_null_parse(cmd);
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_PROCESSOR_LONG_TIMEOUT;
else
cmd->timeout = SCST_GENERIC_PROCESSOR_TIMEOUT;
return res;
}
EXPORT_SYMBOL(scst_processor_generic_parse);
int scst_raid_generic_parse(struct scst_cmd *cmd,
int (*nothing)(struct scst_cmd *cmd))
{
return scst_null_parse(cmd);
int res = scst_null_parse(cmd);
if (cmd->op_flags & SCST_LONG_TIMEOUT)
cmd->timeout = SCST_GENERIC_RAID_LONG_TIMEOUT;
else
cmd->timeout = SCST_GENERIC_RAID_TIMEOUT;
return res;
}
EXPORT_SYMBOL(scst_raid_generic_parse);
@@ -2364,8 +2418,7 @@ int scst_obtain_device_parameters(struct scst_device *dev)
TRACE(TRACE_SCSI, "%s", "Doing internal MODE_SENSE");
res = scsi_execute(dev->scsi_dev, cmd, SCST_DATA_READ, buffer,
sizeof(buffer), sense_buffer, SCST_DEFAULT_TIMEOUT,
0, 0);
sizeof(buffer), sense_buffer, 15, 0, 0);
TRACE_DBG("MODE_SENSE done: %x", res);

View File

@@ -151,6 +151,8 @@ struct scst_dev_type scst_null_devtype = {
.name = "none",
};
static void __scst_resume_activity(void);
int __scst_register_target_template(struct scst_tgt_template *vtt,
const char *version)
{
@@ -299,12 +301,14 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
const char *target_name)
{
struct scst_tgt *tgt;
int rc = 0;
TRACE_ENTRY();
tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
if (tgt == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed");
rc = -ENOMEM;
goto out_err;
}
@@ -319,8 +323,14 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
tgt->retry_timer.data = (unsigned long)tgt;
tgt->retry_timer.function = scst_tgt_retry_timer_fn;
scst_suspend_activity();
mutex_lock(&scst_mutex);
rc = scst_suspend_activity(true);
if (rc != 0)
goto out_free_tgt_err;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
rc = -EINTR;
goto out_resume_free;
}
if (target_name != NULL) {
int len = strlen(target_name) + 1 +
@@ -330,13 +340,15 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
if (tgt->default_group_name == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of default "
"group name failed");
goto out_free_err;
rc = -ENOMEM;
goto out_unlock_resume;
}
sprintf(tgt->default_group_name, "%s_%s", SCST_DEFAULT_ACG_NAME,
target_name);
}
if (scst_build_proc_target_entries(tgt) < 0)
rc = scst_build_proc_target_entries(tgt);
if (rc < 0)
goto out_free_name;
else
list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list);
@@ -354,16 +366,19 @@ out:
out_free_name:
kfree(tgt->default_group_name);
out_free_err:
out_unlock_resume:
mutex_unlock(&scst_mutex);
out_resume_free:
scst_resume_activity();
out_free_tgt_err:
kfree(tgt);
tgt = NULL;
out_err:
PRINT_ERROR("Failed to register target %s for template %s",
target_name, vtt->name);
PRINT_ERROR("Failed to register target %s for template %s (error %d)",
target_name, vtt->name, rc);
goto out;
}
EXPORT_SYMBOL(scst_register);
@@ -398,7 +413,7 @@ void scst_unregister(struct scst_tgt *tgt)
wait_event(tgt->unreg_waitQ, test_sess_list(tgt));
TRACE_DBG("%s", "wait_event() returned");
scst_suspend_activity();
scst_suspend_activity(false);
mutex_lock(&scst_mutex);
list_del(&tgt->tgt_list_entry);
@@ -422,11 +437,44 @@ void scst_unregister(struct scst_tgt *tgt)
}
EXPORT_SYMBOL(scst_unregister);
void scst_suspend_activity(void)
static int scst_susp_wait(bool interruptible)
{
int res = 0;
TRACE_ENTRY();
mutex_lock(&scst_suspend_mutex);
if (interruptible) {
res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ,
(atomic_read(&scst_cmd_count) == 0),
SCST_SUSPENDING_TIMEOUT);
if (res <= 0) {
__scst_resume_activity();
if (res == 0)
res = -EBUSY;
} else
res = 0;
} else
wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0);
TRACE_MGMT_DBG("wait_event() returned %d", res);
TRACE_EXIT_RES(res);
return res;
}
int scst_suspend_activity(bool interruptible)
{
int res = 0;
TRACE_ENTRY();
if (interruptible) {
if (mutex_lock_interruptible(&scst_suspend_mutex) != 0) {
res = -EINTR;
goto out;
}
} else
mutex_lock(&scst_suspend_mutex);
TRACE_MGMT_DBG("suspend_count %d", suspend_count);
suspend_count++;
@@ -437,39 +485,63 @@ void scst_suspend_activity(void)
set_bit(SCST_FLAG_SUSPENDED, &scst_flags);
smp_mb__after_set_bit();
TRACE_MGMT_DBG("Waiting for %d active commands to complete",
atomic_read(&scst_cmd_count));
wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0);
TRACE_MGMT_DBG("%s", "wait_event() returned");
/*
* See comment in scst_user.c::dev_user_task_mgmt_fn() for more
* information about scst_user behavior.
*
* ToDo: make the global suspending unneeded (Switch to per-device
* reference counting? That would mean to switch off from lockless
* implementation of scst_translate_lun().. )
*/
PRINT_INFO("Waiting for %d active commands to complete... This might "
"take few minutes for disks or few hours for tapes, if you "
"use long executed commands, like REWIND or FORMAT. In case, "
"if you have a hung user space device (i.e. made using "
"scst_user module) not responding to any commands, if might "
"take virtually forever until the corresponding user space "
"program recovers and starts responding or gets killed.",
atomic_read(&scst_cmd_count));
res = scst_susp_wait(interruptible);
if (res != 0)
goto out_clear;
clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
smp_mb__after_clear_bit();
TRACE_MGMT_DBG("Waiting for %d active commands finally to complete",
atomic_read(&scst_cmd_count));
wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0);
TRACE_MGMT_DBG("%s", "wait_event() returned");
atomic_read(&scst_cmd_count));
res = scst_susp_wait(interruptible);
if (res != 0)
goto out_clear;
PRINT_INFO("%s", "All active commands completed");
out_up:
mutex_unlock(&scst_suspend_mutex);
TRACE_EXIT();
return;
out:
TRACE_EXIT_RES(res);
return res;
out_clear:
clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
smp_mb__after_clear_bit();
goto out_up;
}
EXPORT_SYMBOL(scst_suspend_activity);
void scst_resume_activity(void)
static void __scst_resume_activity(void)
{
struct scst_cmd_lists *l;
TRACE_ENTRY();
mutex_lock(&scst_suspend_mutex);
suspend_count--;
TRACE_MGMT_DBG("suspend_count %d left", suspend_count);
if (suspend_count > 0)
goto out_up;
goto out;
clear_bit(SCST_FLAG_SUSPENDED, &scst_flags);
smp_mb__after_clear_bit();
@@ -491,7 +563,17 @@ void scst_resume_activity(void)
spin_unlock_irq(&scst_mcmd_lock);
wake_up_all(&scst_mgmt_cmd_list_waitQ);
out_up:
out:
TRACE_EXIT();
return;
}
void scst_resume_activity(void)
{
TRACE_ENTRY();
mutex_lock(&scst_suspend_mutex);
__scst_resume_activity();
mutex_unlock(&scst_suspend_mutex);
TRACE_EXIT();
@@ -507,8 +589,14 @@ static int scst_register_device(struct scsi_device *scsidp)
TRACE_ENTRY();
scst_suspend_activity();
mutex_lock(&scst_mutex);
res = scst_suspend_activity(true);
if (res != 0)
goto out_err;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_resume;
}
res = scst_alloc_device(GFP_KERNEL, &dev);
if (res != 0)
@@ -538,8 +626,11 @@ static int scst_register_device(struct scsi_device *scsidp)
out_up:
mutex_unlock(&scst_mutex);
out_resume:
scst_resume_activity();
out_err:
if (res == 0) {
PRINT_INFO("Attached SCSI target mid-level at "
"scsi%d, channel %d, id %d, lun %d, type %d",
@@ -571,7 +662,7 @@ static void scst_unregister_device(struct scsi_device *scsidp)
TRACE_ENTRY();
scst_suspend_activity();
scst_suspend_activity(false);
mutex_lock(&scst_mutex);
list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
@@ -663,7 +754,10 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
if (res != 0)
goto out;
scst_suspend_activity();
res = scst_suspend_activity(true);
if (res != 0)
goto out;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_resume;
@@ -720,7 +814,7 @@ void scst_unregister_virtual_device(int id)
TRACE_ENTRY();
scst_suspend_activity();
scst_suspend_activity(false);
mutex_lock(&scst_mutex);
list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
@@ -791,7 +885,10 @@ int __scst_register_dev_driver(struct scst_dev_type *dev_type,
}
#endif
scst_suspend_activity();
res = scst_suspend_activity(true);
if (res != 0)
goto out_error;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_err_res;
@@ -855,7 +952,7 @@ void scst_unregister_dev_driver(struct scst_dev_type *dev_type)
TRACE_ENTRY();
scst_suspend_activity();
scst_suspend_activity(false);
mutex_lock(&scst_mutex);
list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {

View File

@@ -120,7 +120,6 @@ extern unsigned long scst_trace_flag;
#define SCST_MAX_DEV_COMMANDS 256
#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ)
#define SCST_CMD_MEM_TIMEOUT (120*HZ)
static inline int scst_get_context(void)
{
@@ -527,6 +526,7 @@ static inline void scst_check_restore_sg_buff(struct scst_cmd *cmd)
cmd->orig_sg_cnt);
cmd->sg[cmd->orig_sg_entry].length = cmd->orig_entry_len;
cmd->sg_cnt = cmd->orig_sg_cnt;
cmd->sg_buff_modified = 0;
}
}

View File

@@ -1209,7 +1209,7 @@ out:
static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file, const char __user *buf,
size_t length, loff_t *off)
{
int res = length, rc = 0, action;
int res, rc = 0, action;
char *buffer, *p;
struct scst_acg *a, *acg = NULL;
@@ -1262,13 +1262,17 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file, const char __user
goto out_free;
}
scst_suspend_activity();
res = scst_suspend_activity(true);
if (res != 0)
goto out_free;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_free_resume;
}
res = length;
switch (action) {
case SCST_PROC_ACTION_ADD_GROUP:
case SCST_PROC_ACTION_DEL_GROUP:
@@ -1426,7 +1430,7 @@ out_synt_err:
static ssize_t scst_proc_groups_devices_write(struct file *file, const char __user *buf,
size_t length, loff_t *off)
{
int res = length, action, virt = 0, rc, read_only = 0;
int res, action, virt = 0, rc, read_only = 0;
char *buffer, *p, *e = NULL;
unsigned int host, channel = 0, id = 0, lun = 0, virt_lun;
struct scst_acg *acg = (struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
@@ -1481,13 +1485,17 @@ static ssize_t scst_proc_groups_devices_write(struct file *file, const char __us
goto out_free;
}
scst_suspend_activity();
res = scst_suspend_activity(true);
if (res != 0)
goto out_free;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_free_resume;
}
res = length;
switch (action) {
case SCST_PROC_ACTION_ADD:
case SCST_PROC_ACTION_DEL:
@@ -1565,7 +1573,7 @@ static ssize_t scst_proc_groups_devices_write(struct file *file, const char __us
}
if (acg_dev) {
acg_dev = acg_dev_tmp;
PRINT_ERROR("virt lun %d exist in group %s",
PRINT_ERROR("virt lun %d already exists in group %s",
virt_lun, acg->acg_name);
res = -EINVAL;
goto out_free_up;

View File

@@ -540,16 +540,26 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
}
}
if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
TRACE(TRACE_MINOR, "Warning: expected transfer length "
"%d for opcode 0x%02x (handler %s, target %s) "
"doesn't match decoded value %d. Faulty "
"initiator (e.g. VMware is known to be such) or "
"scst_scsi_op_table should be updated?",
cmd->expected_transfer_len, cmd->cdb[0],
dev->handler->name, cmd->tgtt->name,
cmd->bufflen);
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB", cmd->cdb,
cmd->cdb_len);
static int repd;
if (repd < 100) {
/*
* Intentionally unlocked. Few messages more
* or less don't matter.
*/
repd++;
TRACE(TRACE_MINOR, "Warning: expected transfer "
"length %d for opcode 0x%02x (handler "
"%s, target %s) doesn't match decoded "
"value %d. Faulty initiator (e.g. "
"VMware is known to be such) or "
"scst_scsi_op_table should be updated?",
cmd->expected_transfer_len, cmd->cdb[0],
dev->handler->name, cmd->tgtt->name,
cmd->bufflen);
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
cmd->cdb, cmd->cdb_len);
}
}
#endif
}
@@ -2079,6 +2089,12 @@ static int scst_check_sense(struct scst_cmd *cmd)
cmd->driver_status = 0;
mempool_free(cmd->sense, scst_sense_mempool);
cmd->sense = NULL;
sBUG_ON(cmd->dbl_ua_orig_resp_data_len < 0);
sBUG_ON(cmd->sg_buff_modified);
cmd->data_direction =
cmd->dbl_ua_orig_data_direction;
cmd->resp_data_len =
cmd->dbl_ua_orig_resp_data_len;
cmd->retry = 1;
cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV;
res = 1;
@@ -2226,7 +2242,8 @@ static int scst_done_cmd_check(struct scst_cmd *cmd, int *pres)
#ifdef EXTRACHECKS
if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) {
PRINT_INFO("NormACA set for device: "
"lun=%Ld, type 0x%02x",
"lun=%Ld, type 0x%02x. Clear it, "
"since it's unsupported.",
(long long unsigned int)cmd->lun,
buffer[0]);
}
@@ -3425,11 +3442,82 @@ void scst_done_cmd_mgmt(struct scst_cmd *cmd)
return;
}
/* Called under scst_mcmd_lock and IRQs disabled */
static int __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake)
{
TRACE_ENTRY();
mcmd->cmd_finish_wait_count--;
if (mcmd->cmd_finish_wait_count > 0) {
TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
"skipping", mcmd->cmd_finish_wait_count);
goto out;
}
if (mcmd->completed) {
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
"list", mcmd);
list_add_tail(&mcmd->mgmt_cmd_list_entry,
&scst_active_mgmt_cmd_list);
*wake = true;
}
out:
TRACE_EXIT_RES(mcmd->cmd_finish_wait_count);
return mcmd->cmd_finish_wait_count;
}
/* No locks */
void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd)
{
unsigned long flags;
TRACE_ENTRY();
TRACE_MGMT_DBG("Preparing mcmd %p for async execution", mcmd);
spin_lock_irqsave(&scst_mcmd_lock, flags);
mcmd->cmd_finish_wait_count++;
spin_unlock_irqrestore(&scst_mcmd_lock, flags);
TRACE_EXIT();
return;
}
EXPORT_SYMBOL(scst_prepare_async_mcmd);
/* No locks */
void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status)
{
unsigned long flags;
bool wake = false;
TRACE_ENTRY();
TRACE_MGMT_DBG("Async mcmd %p completed (status %d)", mcmd, status);
spin_lock_irqsave(&scst_mcmd_lock, flags);
if (status != SCST_MGMT_STATUS_SUCCESS)
mcmd->status = status;
__scst_dec_finish_wait_count(mcmd, &wake);
spin_unlock_irqrestore(&scst_mcmd_lock, flags);
if (wake)
wake_up(&scst_mgmt_cmd_list_waitQ);
TRACE_EXIT();
return;
}
EXPORT_SYMBOL(scst_async_mcmd_completed);
/* No locks */
static void scst_finish_cmd_mgmt(struct scst_cmd *cmd)
{
struct scst_mgmt_cmd_stub *mstb, *t;
bool wake = 0;
bool wake = false;
unsigned long flags;
TRACE_ENTRY();
@@ -3452,21 +3540,11 @@ static void scst_finish_cmd_mgmt(struct scst_cmd *cmd)
if (cmd->completed)
mcmd->completed_cmd_count++;
mcmd->cmd_finish_wait_count--;
if (mcmd->cmd_finish_wait_count > 0) {
if (__scst_dec_finish_wait_count(mcmd, &wake) > 0) {
TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
"skipping", mcmd->cmd_finish_wait_count);
continue;
}
if (mcmd->completed) {
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
"list", mcmd);
list_add_tail(&mcmd->mgmt_cmd_list_entry,
&scst_active_mgmt_cmd_list);
wake = 1;
}
}
spin_unlock_irqrestore(&scst_mcmd_lock, flags);
@@ -3513,10 +3591,7 @@ static inline int scst_is_strict_mgmt_fn(int mgmt_fn)
}
}
/*
* Might be called under sess_list_lock and IRQ off + BHs also off
* Returns -1 if command is being executed (ABORT failed), 0 otherwise
*/
/* Might be called under sess_list_lock and IRQ off + BHs also off */
void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
int other_ini, int call_dev_task_mgmt_fn)
{
@@ -3547,7 +3622,6 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
spin_unlock_irqrestore(&other_ini_lock, flags);
/*
* To sync with cmd->finished/done set in
* scst_finish_cmd()/scst_pre_xmit_response()
@@ -3587,12 +3661,15 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
&cmd->mgmt_cmd_list);
/*
* Delay the response until the command's finish in
* order to guarantee that "no further responses from
* the task are sent to the SCSI initiator port" after
* response from the TM function is sent (SAM). Plus,
* we must wait here to be sure that we won't receive
* double commands with the same tag.
* Delay the response until the command's finish in order to
* guarantee that "no further responses from the task are sent
* to the SCSI initiator port" after response from the TM
* function is sent (SAM). Plus, we must wait here to be sure
* that we won't receive double commands with the same tag.
* Moreover, if we don't wait here, we might have a possibility
* for data corruption, when aborted and reported as completed
* command actually gets executed *after* new commands sent
* after this TM command completed.
*/
TRACE_MGMT_DBG("cmd %p (tag %llu) being executed/xmitted "
"(state %d, proc time %ld sec.), deferring ABORT...",
@@ -4853,6 +4930,7 @@ static int scst_init_session(struct scst_session *sess)
#ifdef CONFIG_LOCKDEP
if (res == 0) {
/* ToDo: make it on-stack */
sess->shutdown_compl = kmalloc(sizeof(*sess->shutdown_compl),
GFP_KERNEL);
if (sess->shutdown_compl == NULL)
@@ -4984,7 +5062,7 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
rc, sess);
}
sess->shut_phase = SCST_SESS_SPH_PRE_UNREG;
sess->shut_phase = SCST_SESS_SPH_SHUTDOWN;
spin_lock_irqsave(&scst_mgmt_lock, flags);
@@ -4995,12 +5073,9 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
sess->shutdown_compl = NULL;
#endif
TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess);
list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list);
spin_unlock_irqrestore(&scst_mgmt_lock, flags);
wake_up(&scst_mgmt_waitQ);
scst_sess_put(sess);
if (wait) {
TRACE_DBG("Waiting for session %p to complete", sess);
@@ -5016,41 +5091,6 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
}
EXPORT_SYMBOL(scst_unregister_session_ex);
static void scst_pre_unreg_sess(struct scst_session *sess)
{
int i;
struct scst_tgt_dev *tgt_dev;
TRACE_ENTRY();
tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1);
mutex_lock(&scst_mutex);
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
struct list_head *sess_tgt_dev_list_head =
&sess->sess_tgt_dev_list_hash[i];
list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
sess_tgt_dev_list_entry) {
struct scst_dev_type *handler = tgt_dev->dev->handler;
if (handler && handler->pre_unreg_sess) {
TRACE_DBG("Calling dev handler's pre_unreg_sess(%p)",
tgt_dev);
handler->pre_unreg_sess(tgt_dev);
TRACE_DBG("%s", "Dev handler's pre_unreg_sess() "
"returned");
}
}
}
mutex_unlock(&scst_mutex);
sess->shut_phase = SCST_SESS_SPH_SHUTDOWN;
scst_sess_put(sess);
TRACE_EXIT();
return;
}
static inline int test_mgmt_list(void)
{
int res = !list_empty(&scst_sess_init_list) ||
@@ -5120,9 +5160,6 @@ int scst_mgmt_thread(void *arg)
spin_unlock_irq(&scst_mgmt_lock);
switch (sess->shut_phase) {
case SCST_SESS_SPH_PRE_UNREG:
scst_pre_unreg_sess(sess);
break;
case SCST_SESS_SPH_SHUTDOWN:
sBUG_ON(atomic_read(&sess->refcnt) != 0);
scst_free_session_callback(sess);

View File

@@ -210,7 +210,7 @@ static int do_exec(struct vdisk_cmd *vcmd)
#endif
#ifdef DEBUG_TM_IGNORE
if (dev->debug_tm_ignore && (random() % 200000) == 75) {
if (dev->debug_tm_ignore && (random() % 10000) == 75) {
TRACE_MGMT_DBG("Ignore cmd op %x (h=%d)", cdb[0],
vcmd->cmd->cmd_h);
res = 150;
@@ -726,7 +726,11 @@ void *main_loop(void *arg)
default:
PRINT_ERROR("SCST_USER_REPLY_AND_GET_CMD failed: "
"%s (%d)", strerror(res), res);
#if 1
continue;
#else
goto out_close;
#endif
}
again_poll:
res = poll(&pl, 1, 2000);
@@ -746,7 +750,11 @@ again_poll:
goto again_poll;
default:
PRINT_ERROR("poll() failed: %s", strerror(res));
#if 1
goto again_poll;
#else
goto out_close;
#endif
}
}
}
@@ -791,8 +799,6 @@ again_poll:
break;
case SCST_USER_TASK_MGMT:
if (dev->prio_thr)
goto err;
res = do_tm(&vcmd);
#if DEBUG_TM_FN_IGNORE
if (dev->debug_tm_ignore) {
@@ -803,13 +809,10 @@ again_poll:
case SCST_USER_ATTACH_SESS:
case SCST_USER_DETACH_SESS:
if (dev->prio_thr)
goto err;
res = do_sess(&vcmd);
break;
default:
err:
PRINT_ERROR("Unknown or wrong cmd subcode %x",
cmd.subcode);
goto out_close;
@@ -832,78 +835,6 @@ out:
return (void *)(long)res;
}
void *prio_loop(void *arg)
{
int res = 0;
struct vdisk_dev *dev = (struct vdisk_dev *)arg;
struct scst_user_get_cmd cmd;
struct scst_user_reply_cmd reply;
struct vdisk_cmd vcmd = { -1, &cmd, dev, &reply, {0}};
int scst_usr_fd = dev->scst_usr_fd;
TRACE_ENTRY();
cmd.preply = 0;
while(1) {
res = ioctl(scst_usr_fd, SCST_USER_REPLY_AND_GET_PRIO_CMD, &cmd);
if (res != 0) {
res = errno;
switch(res) {
case ESRCH:
case EBUSY:
case EINTR:
case EAGAIN:
TRACE_MGMT_DBG("SCST_USER_REPLY_AND_GET_PRIO_CMD returned "
"%d (%s)", res, strerror(res));
cmd.preply = 0;
continue;
default:
PRINT_ERROR("SCST_USER_REPLY_AND_GET_PRIO_CMD failed: "
"%s (%d)", strerror(res), res);
goto out_close;
}
}
TRACE_BUFFER("Received cmd", &cmd, sizeof(cmd));
switch(cmd.subcode) {
case SCST_USER_TASK_MGMT:
res = do_tm(&vcmd);
#if DEBUG_TM_FN_IGNORE
if (dev->debug_tm_ignore) {
sleep(15);
}
#endif
break;
case SCST_USER_ATTACH_SESS:
case SCST_USER_DETACH_SESS:
res = do_sess(&vcmd);
break;
default:
PRINT_ERROR("Unknown or wrong prio cmd subcode %x",
cmd.subcode);
goto out_close;
}
if (res != 0)
goto out_close;
cmd.preply = (unsigned long)&reply;
TRACE_BUFFER("Sending reply", &reply, sizeof(reply));
}
out_close:
close(vcmd.fd);
PRINT_INFO("Prio thread %d exited (res=%d)", gettid(), res);
TRACE_EXIT_RES(res);
return (void *)(long)res;
}
static void exec_inquiry(struct vdisk_cmd *vcmd)
{
struct vdisk_dev *dev = vcmd->dev;

View File

@@ -72,7 +72,6 @@ struct vdisk_dev {
unsigned int nullio:1;
unsigned int cdrom_empty:1;
unsigned int non_blocking:1;
unsigned int prio_thr:1;
#if defined(DEBUG_TM_IGNORE) || defined(DEBUG_TM_IGNORE_ALL)
unsigned int debug_tm_ignore:1;
#if defined(DEBUG_TM_IGNORE_ALL)
@@ -118,4 +117,3 @@ struct vdisk_cmd
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
void *main_loop(void *arg);
void *prio_loop(void *arg);

View File

@@ -80,7 +80,6 @@ static struct option const long_options[] =
{"parse", required_argument, 0, 'p'},
{"on_free", required_argument, 0, 'f'},
{"mem_reuse", required_argument, 0, 'm'},
{"prio_thread", no_argument, 0, 's'},
{"non_blocking", no_argument, 0, 'l'},
#if defined(DEBUG) || defined(TRACING)
{"debug", required_argument, 0, 'd'},
@@ -110,7 +109,6 @@ static void usage(void)
"(default) or \"call\"\n");
printf(" -m, --mem_reuse=type Memory reuse type, one of \"all\" "
"(default), \"read\", \"write\" or \"none\"\n");
printf(" -s, --prio_thread Use separate thread for mgmt (prio) commands\n");
printf(" -l, --non_blocking Use non-blocking operations\n");
#if defined(DEBUG) || defined(TRACING)
printf(" -d, --debug=level Debug tracing level\n");
@@ -178,7 +176,7 @@ int main(int argc, char **argv)
dev.type = TYPE_DISK;
dev.alloc_fn = align_alloc;
while ((ch = getopt_long(argc, argv, "+b:e:tronsglcp:f:m:d:vh", long_options,
while ((ch = getopt_long(argc, argv, "+b:e:tronglcp:f:m:d:vh", long_options,
&longindex)) >= 0) {
switch (ch) {
case 'b':
@@ -245,9 +243,6 @@ int main(int argc, char **argv)
else
goto out_usage;
break;
case 's':
dev.prio_thr = 1;
break;
case 'l':
dev.non_blocking = 1;
break;
@@ -352,10 +347,6 @@ int main(int argc, char **argv)
dev.alloc_fn = malloc;
}
if (dev.prio_thr) {
PRINT_INFO(" %s", "Using separate prio thread");
}
#if defined(DEBUG_TM_IGNORE) || defined(DEBUG_TM_IGNORE_ALL)
if (dev.debug_tm_ignore) {
PRINT_INFO(" %s", "DEBUG_TM_IGNORE");
@@ -385,10 +376,6 @@ int main(int argc, char **argv)
desc.opt.parse_type = parse_type;
desc.opt.on_free_cmd_type = on_free_cmd_type;
desc.opt.memory_reuse_type = memory_reuse_type;
if (dev.prio_thr)
desc.opt.prio_queue_type = SCST_USER_PRIO_QUEUE_SEPARATE;
else
desc.opt.prio_queue_type = SCST_USER_PRIO_QUEUE_SINGLE;
desc.opt.tst = SCST_CONTR_MODE_SEP_TASK_SETS;
desc.opt.queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
@@ -415,10 +402,6 @@ int main(int argc, char **argv)
opt.parse_type = parse_type;
opt.on_free_cmd_type = on_free_cmd_type;
opt.memory_reuse_type = memory_reuse_type;
if (dev.prio_thr)
opt.prio_queue_type = SCST_USER_PRIO_QUEUE_SEPARATE;
else
opt.prio_queue_type = SCST_USER_PRIO_QUEUE_SINGLE;
res = ioctl(dev.scst_usr_fd, SCST_USER_SET_OPTIONS, &opt);
if (res != 0) {
@@ -438,9 +421,9 @@ int main(int argc, char **argv)
{
pthread_t thread[threads];
pthread_t prio;
int i, j, rc;
void *rc1;
for(i = 0; i < threads; i++) {
rc = pthread_create(&thread[i], NULL, main_loop, &dev);
if (rc != 0) {
@@ -451,16 +434,6 @@ int main(int argc, char **argv)
}
}
if (dev.prio_thr) {
rc = pthread_create(&prio, NULL, prio_loop, &dev);
if (rc != 0) {
res = errno;
PRINT_ERROR("Prio pthread_create() failed: %s",
strerror(res));
dev.prio_thr = 0;
}
}
j = i;
for(i = 0; i < j; i++) {
rc = pthread_join(thread[i], &rc1);
@@ -475,19 +448,6 @@ int main(int argc, char **argv)
} else
PRINT_INFO("Thread %d exited", i);
}
if (dev.prio_thr) {
rc = pthread_join(prio, &rc1);
if (rc != 0) {
res = errno;
PRINT_ERROR("Prio pthread_join() failed: %s",
strerror(res));
} else if (rc1 != NULL) {
res = (long)rc1;
PRINT_INFO("Prio thread %d exited, res %lx", i,
(long)rc1);
} else
PRINT_INFO("Prio thread %d exited", i);
}
}
pthread_mutex_destroy(&dev.dev_mutex);