mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-30 02:10:18 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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, ®);
|
||||
if (err < 0) {
|
||||
log_error("Unable to register: %s. Incompatible version of the "
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
34
scst/README
34
scst/README
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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*** " \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 "
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user