- Now during connection and session reinstatements only SCSI commands are delayed until the corresponding reinstatement finished.

- TEST UNIT READY made HEAD OF QUEUE to let target don't look dead under high load
 - Docs updated



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@774 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-04-14 17:29:23 +00:00
parent e7d30d796a
commit 7b30ca41cb
11 changed files with 177 additions and 92 deletions

View File

@@ -72,16 +72,17 @@ original IET behavior, when for data transmission:
- For in-kernel allocated memory (scst_vdisk and pass-through
handlers) usage of SGV cache on transmit path (READ-type commands)
will be disabled. The performance hit will be not big, but performance
will still remain better, than for IET, because SGV cache will remain
used on receive path while IET doesn't have such feature.
will be disabled, but data will still be sent in zero-copy manner.
The performance hit will be not big, but performance will still
remain better, than for IET, because SGV cache will remain used on
receive path while IET doesn't have such feature.
- For user space allocated memory (scst_user handler) all transmitted
data will be additionally copied into temporary TCP buffers. The
performance hit will be quite noticeable.
Note, that if your network hardware does not support TX offload
functions of has them disabled, then TCP zero-copy transmit functions on
functions or has them disabled, then TCP zero-copy transmit functions on
your system will not be used by Linux networking in any case, so
put_page_callback patch will not be able to improve performance for you.
You can check your network hardware offload capabilities by command
@@ -131,6 +132,9 @@ and the SCST core as it logically should be: the target driver is
responsible for handling targets and their parameters, SCST core is
responsible for handling backstorage.
It is recommended to use TEST UNIT READY ("tur") command to check if
iSCSI-SCST target is alive.
IMPORTANT: All LUN information (access control) MUST be configured
========= BEFORE iscsi-scstd started!

View File

@@ -32,16 +32,17 @@ original IET behavior, when for data transmission:
- For in-kernel allocated memory (scst_vdisk and pass-through
handlers) usage of SGV cache on transmit path (READ-type commands)
will be disabled. The performance hit will be not big, but performance
will still remain better, than for IET, because SGV cache will remain
used on receive path while IET doesn't have such feature.
will be disabled, but data will still be sent in zero-copy manner.
The performance hit will be not big, but performance will still
remain better, than for IET, because SGV cache will remain used on
receive path while IET doesn't have such feature.
- For user space allocated memory (scst_user handler) all transmitted
data will be additionally copied into temporary TCP buffers. The
performance hit will be quite noticeable.
Note, that if your network hardware does not support TX offload
functions of has them disabled, then TCP zero-copy transmit functions on
functions or has them disabled, then TCP zero-copy transmit functions on
your system will not be used by Linux networking in any case, so
put_page_callback patch will not be able to improve performance for you.
You can check your network hardware offload capabilities by command
@@ -66,6 +67,9 @@ and the SCST core as it logically should be: the target driver is
responsible for handling targets and their parameters, SCST core is
responsible for handling backstorage.
It is recommended to use TEST UNIT READY ("tur") command to check if
iSCSI-SCST target is alive.
IMPORTANT: All LUN information (access control) MUST be configured
========= BEFORE iscsi-scstd started!

View File

@@ -56,7 +56,7 @@ static void print_conn_state(char *p, size_t size, struct iscsi_conn *conn)
break;
}
if (conn->conn_reinstating)
if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags))
snprintf(p, size, "%s", "reinstating ");
else if (!printed)
snprintf(p, size, "%s", "established idle ");
@@ -132,8 +132,6 @@ static void iscsi_make_conn_rd_active(struct iscsi_conn *conn)
{
TRACE_ENTRY();
EXTRACHECKS_BUG_ON(conn->conn_reinstating);
spin_lock_bh(&iscsi_rd_lock);
TRACE_DBG("conn %p, rd_state %x, rd_data_ready %d", conn,
@@ -184,8 +182,7 @@ void __mark_conn_closed(struct iscsi_conn *conn, int flags)
conn->deleting = 1;
spin_unlock_bh(&iscsi_rd_lock);
if (!conn->conn_reinstating)
iscsi_make_conn_rd_active(conn);
iscsi_make_conn_rd_active(conn);
}
void mark_conn_closed(struct iscsi_conn *conn)
@@ -274,7 +271,7 @@ static void conn_rsp_timer_fn(unsigned long arg)
if (!list_empty(&conn->written_list)) {
struct iscsi_cmnd *wr_cmd = list_entry(conn->written_list.next,
struct iscsi_cmnd, write_list_entry);
struct iscsi_cmnd, written_list_entry);
if (unlikely(time_after_eq(jiffies, wr_cmd->write_timeout))) {
if (!conn->closing) {
@@ -302,16 +299,34 @@ static void conn_rsp_timer_fn(unsigned long arg)
return;
}
void __iscsi_socket_bind(struct iscsi_conn *conn)
/* target_mutex supposed to be locked */
void conn_reinst_finished(struct iscsi_conn *conn)
{
struct iscsi_cmnd *cmnd, *t;
TRACE_ENTRY();
clear_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
list_for_each_entry_safe(cmnd, t, &conn->reinst_pending_cmd_list,
reinst_pending_cmd_list_entry) {
TRACE_MGMT_DBG("Restarting reinst pending cmnd %p",
cmnd);
list_del(&cmnd->reinst_pending_cmd_list_entry);
iscsi_restart_cmnd(cmnd);
}
TRACE_EXIT();
return;
}
static void conn_activate(struct iscsi_conn *conn)
{
TRACE_MGMT_DBG("Enabling conn %p", conn);
/* Catch double bind */
sBUG_ON(conn->sock->sk->sk_state_change == iscsi_state_change);
/* Let's reset this flag in one place */
conn->conn_reinstating = 0;
write_lock_bh(&conn->sock->sk->sk_callback_lock);
conn->old_state_change = conn->sock->sk->sk_state_change;
@@ -340,7 +355,7 @@ void __iscsi_socket_bind(struct iscsi_conn *conn)
* pointer. This seems to work fine, and this approach is also used in some
* other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c).
*/
static int iscsi_socket_bind(struct iscsi_conn *conn, bool reinstating)
static int conn_setup_sock(struct iscsi_conn *conn)
{
int res = 0;
int opt = 1;
@@ -369,17 +384,6 @@ static int iscsi_socket_bind(struct iscsi_conn *conn, bool reinstating)
(void __force __user *)&opt, sizeof(opt));
set_fs(oldfs);
if (!reinstating) {
/*
* We will delay full conn serving until all commands in
* replacing connections are done to prevent them from
* spoil our data by writing to them too late.
*/
__iscsi_socket_bind(conn);
} else
TRACE_MGMT_DBG("conn %p is reinstating, delaying enabling it",
conn);
out:
return res;
}
@@ -399,9 +403,10 @@ int conn_free(struct iscsi_conn *conn)
sBUG_ON(!list_empty(&conn->write_list));
sBUG_ON(!list_empty(&conn->written_list));
sBUG_ON(conn->conn_reinst_successor != NULL);
sBUG_ON(!conn->conn_shutting_down);
sBUG_ON(!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags));
if (conn->conn_reinstating) {
/* Just in case if new conn gets freed before the old one */
if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags)) {
struct iscsi_conn *c;
TRACE_MGMT_DBG("Freeing being reinstated conn %p", conn);
list_for_each_entry(c, &conn->session->conn_list,
@@ -428,14 +433,11 @@ int conn_free(struct iscsi_conn *conn)
/* target_mutex supposed to be locked */
static int iscsi_conn_alloc(struct iscsi_session *session,
struct iscsi_kern_conn_info *info, bool reinstating,
struct iscsi_conn **new_conn)
struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn)
{
struct iscsi_conn *conn;
int res = 0;
reinstating |= session->sess_reinstating;
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn) {
res = -ENOMEM;
@@ -454,7 +456,8 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
atomic_set(&conn->conn_ref_cnt, 0);
conn->session = session;
conn->conn_reinstating = reinstating;
if (session->sess_reinstating)
__set_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
conn->cid = info->cid;
conn->stat_sn = info->stat_sn;
conn->exp_stat_sn = info->exp_stat_sn;
@@ -475,10 +478,11 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
INIT_LIST_HEAD(&conn->written_list);
setup_timer(&conn->rsp_timer, conn_rsp_timer_fn, (unsigned long)conn);
init_completion(&conn->ready_to_free);
INIT_LIST_HEAD(&conn->reinst_pending_cmd_list);
conn->file = fget(info->fd);
res = iscsi_socket_bind(conn, reinstating);
res = conn_setup_sock(conn);
if (res != 0)
goto out_err_free2;
@@ -510,7 +514,8 @@ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
bool reinstatement = false;
conn = conn_lookup(session, info->cid);
if ((conn != NULL) && !conn->conn_shutting_down) {
if ((conn != NULL) &&
!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
/* conn reinstatement */
reinstatement = true;
} else if (!list_empty(&session->conn_list)) {
@@ -518,7 +523,7 @@ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
goto out;
}
err = iscsi_conn_alloc(session, info, reinstatement, &new_conn);
err = iscsi_conn_alloc(session, info, &new_conn);
if (err != 0)
goto out;
@@ -526,10 +531,12 @@ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
TRACE_MGMT_DBG("Reinstating conn (old %p, new %p)", conn,
new_conn);
conn->conn_reinst_successor = new_conn;
new_conn->conn_reinstating = 1;
__set_bit(ISCSI_CONN_REINSTATING, &new_conn->conn_aflags);
__mark_conn_closed(conn, 0);
}
conn_activate(new_conn);
out:
return err;
}

View File

@@ -114,13 +114,45 @@ static inline int cmnd_read_size(struct iscsi_cmnd *cmnd)
return 0;
}
static inline void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
{
EXTRACHECKS_BUG_ON(cmnd->data_waiting);
if (unlikely(test_bit(ISCSI_CONN_REINSTATING,
&cmnd->conn->conn_aflags))) {
struct iscsi_target *target = cmnd->conn->session->target;
bool get_out;
mutex_lock(&target->target_mutex);
get_out = test_bit(ISCSI_CONN_REINSTATING,
&cmnd->conn->conn_aflags);
/* Let's don't look dead */
if (scst_cmd_get_cdb(cmnd->scst_cmd)[0] == TEST_UNIT_READY)
get_out = false;
if (!get_out)
goto unlock_cont;
TRACE_MGMT_DBG("Pending cmnd %p, because conn %p is "
"reinstated", cmnd, cmnd->conn);
cmnd->scst_state = ISCSI_CMD_STATE_REINST_PENDING;
list_add_tail(&cmnd->reinst_pending_cmd_list_entry,
&cmnd->conn->reinst_pending_cmd_list);
unlock_cont:
mutex_unlock(&target->target_mutex);
if (get_out)
goto out;
}
cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
scst_restart_cmd(cmnd->scst_cmd, SCST_PREPROCESS_STATUS_SUCCESS,
SCST_CONTEXT_THREAD);
out:
return;
}
@@ -226,6 +258,7 @@ static void cmnd_free(struct iscsi_cmnd *cmnd)
return;
}
/* Might be called unded some lock and on SIRQ */
void cmnd_done(struct iscsi_cmnd *cmnd)
{
TRACE_DBG("%p", cmnd);
@@ -243,7 +276,7 @@ void cmnd_done(struct iscsi_cmnd *cmnd)
TRACE_DBG("Deleting cmd %p from conn %p written_list", cmnd,
conn);
spin_lock_bh(&conn->write_list_lock);
list_del(&cmnd->write_list_entry);
list_del(&cmnd->written_list_entry);
cmnd->on_written_list = 0;
spin_unlock_bh(&conn->write_list_lock);
}
@@ -2973,7 +3006,7 @@ static int iscsi_scsi_aen(struct scst_aen *aen)
found = false;
list_for_each_entry_reverse(conn, &sess->conn_list, conn_list_entry) {
if (!conn->conn_shutting_down &&
if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags) &&
(conn->conn_reinst_successor == NULL)) {
found = true;
break;

View File

@@ -147,6 +147,10 @@ struct iscsi_conn {
u32 stat_sn;
u32 exp_stat_sn;
#define ISCSI_CONN_REINSTATING 1
#define ISCSI_CONN_SHUTTINGDOWN 2
unsigned long conn_aflags;
spinlock_t cmd_list_lock; /* BH lock */
/* Protected by cmd_list_lock */
@@ -227,8 +231,7 @@ struct iscsi_conn {
/* All protected by target_mutex, where necessary */
struct iscsi_conn *conn_reinst_successor;
unsigned int conn_reinstating:1;
unsigned int conn_shutting_down:1;
struct list_head reinst_pending_cmd_list;
struct completion ready_to_free;
@@ -257,14 +260,17 @@ typedef void (iscsi_show_info_t)(struct seq_file *seq,
/* The command returned from preprocessing_done() */
#define ISCSI_CMD_STATE_AFTER_PREPROC 2
/* The command is waiting for session or connection reinstatement finished */
#define ISCSI_CMD_STATE_REINST_PENDING 3
/* scst_restart_cmd() called and SCST processing it */
#define ISCSI_CMD_STATE_RESTARTED 3
#define ISCSI_CMD_STATE_RESTARTED 4
/* SCST done processing */
#define ISCSI_CMD_STATE_PROCESSED 4
#define ISCSI_CMD_STATE_PROCESSED 5
/* AEN processing */
#define ISCSI_CMD_STATE_AEN 5
#define ISCSI_CMD_STATE_AEN 6
/** Command's reject reasons **/
#define ISCSI_REJECT_SCSI_CMD 1
@@ -320,7 +326,12 @@ struct iscsi_cmnd {
union {
struct list_head pending_list_entry;
struct list_head reinst_pending_cmd_list_entry;
};
union {
struct list_head write_list_entry;
struct list_head written_list_entry;
};
/* Both modified only from single write thread */
@@ -410,10 +421,11 @@ extern void req_cmnd_release_force(struct iscsi_cmnd *req, int flags);
extern void rsp_cmnd_release(struct iscsi_cmnd *);
extern void cmnd_done(struct iscsi_cmnd *cmnd);
extern void conn_abort(struct iscsi_conn *conn);
extern void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd);
/* conn.c */
extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
extern void __iscsi_socket_bind(struct iscsi_conn *);
extern void conn_reinst_finished(struct iscsi_conn *);
extern int conn_add(struct iscsi_session *, struct iscsi_kern_conn_info *);
extern int conn_del(struct iscsi_session *, struct iscsi_kern_conn_info *);
extern int conn_free(struct iscsi_conn *);
@@ -454,7 +466,7 @@ extern void iscsi_procfs_exit(void);
/* session.c */
extern const struct file_operations session_seq_fops;
extern struct iscsi_session *session_lookup(struct iscsi_target *, u64);
extern void sess_enable_reinstated_sess(struct iscsi_session *);
extern void sess_reinst_finished(struct iscsi_session *);
extern int session_add(struct iscsi_target *, struct iscsi_kern_session_info *);
extern int session_del(struct iscsi_target *, u64);
extern int session_free(struct iscsi_session *session, bool del);

View File

@@ -339,11 +339,12 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd)
mutex_lock(&sess->target->target_mutex);
if (conn->conn_reinst_successor != NULL) {
sBUG_ON(!conn->conn_reinst_successor->conn_reinstating);
__iscsi_socket_bind(conn->conn_reinst_successor);
/* We will check for conn_reinst_successor later */
sBUG_ON(!test_bit(ISCSI_CONN_REINSTATING,
&conn->conn_reinst_successor->conn_aflags));
conn_reinst_finished(conn->conn_reinst_successor);
conn->conn_reinst_successor = NULL;
} else if (sess->sess_reinst_successor != NULL) {
sess_enable_reinstated_sess(sess->sess_reinst_successor);
sess_reinst_finished(sess->sess_reinst_successor);
sess->sess_reinst_successor = NULL;
}
mutex_unlock(&sess->target->target_mutex);
@@ -394,12 +395,12 @@ static void close_conn(struct iscsi_conn *conn)
mutex_lock(&session->target->target_mutex);
conn->conn_shutting_down = 1;
set_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags);
reinst = (conn->conn_reinst_successor != NULL);
session->sess_shutting_down = 1;
list_for_each_entry(c, &session->conn_list, conn_list_entry) {
if (!c->conn_shutting_down) {
if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &c->conn_aflags)) {
session->sess_shutting_down = 0;
break;
}
@@ -542,12 +543,8 @@ static void close_conn(struct iscsi_conn *conn)
conn);
event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0);
sBUG_ON(conn->conn_reinstating);
sBUG_ON(session->sess_reinstating);
mutex_lock(&target->target_mutex);
conn->conn_reinst_successor = NULL;
conn_free(conn);
if (list_empty(&session->conn_list)) {
@@ -1098,7 +1095,8 @@ static int write_data(struct iscsi_conn *conn)
spin_lock_bh(&conn->write_list_lock);
ref_cmd->on_written_list = 1;
ref_cmd->write_timeout = jiffies + ISCSI_RSP_TIMEOUT;
list_add_tail(&ref_cmd->write_list_entry, &conn->written_list);
list_add_tail(&ref_cmd->written_list_entry,
&conn->written_list);
spin_unlock_bh(&conn->write_list_lock);
}

View File

@@ -107,7 +107,7 @@ err:
}
/* target_mutex supposed to be locked */
void sess_enable_reinstated_sess(struct iscsi_session *sess)
void sess_reinst_finished(struct iscsi_session *sess)
{
struct iscsi_conn *c;
@@ -118,7 +118,7 @@ void sess_enable_reinstated_sess(struct iscsi_session *sess)
sBUG_ON(!sess->sess_reinstating);
list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
__iscsi_socket_bind(c);
conn_reinst_finished(c);
}
sess->sess_reinstating = 0;
@@ -239,7 +239,7 @@ int session_free(struct iscsi_session *session, bool del)
sBUG_ON(!list_empty(&session->cmnd_hash[i]));
if (session->sess_reinst_successor != NULL)
sess_enable_reinstated_sess(session->sess_reinst_successor);
sess_reinst_finished(session->sess_reinst_successor);
if (session->sess_reinstating) {
struct iscsi_session *s;

View File

@@ -184,6 +184,7 @@ out:
return err;
}
/* target_mutex supposed to be locked */
void target_del_session(struct iscsi_target *target,
struct iscsi_session *session, int flags)
{

View File

@@ -57,20 +57,29 @@ 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.
Then, since in the mainstream kernels scsi_do_req()/scsi_execute_async()
work in LIFO order, instead of expected and required FIFO, SCST needs a
new functions scsi_do_req_fifo()/scsi_execute_async_fifo() to be added
in the kernel. Patch scst_exec_req_fifo.patch from "kernel" directory
does that. If it doesn't apply to your kernel, apply it manually, it
only adds one of those functions and nothing more. You may not patch the
kernel if you don't need pass-through support or CONFIG_SCST_STRICT_SERIALIZING is
defined during the compilation (see description below).
Then you should consider to apply necessary kernel patches. SCST has the
following patches for the kernel in the "kernel" subdirectory. All of
them are optional, so, if you don't need the corresponding
functionality, you may not apply them.
Then, to get the maximum performance you should apply export_alloc_io_context
patch. This patch simply makes alloc_io_context() function be available
for modules, not only for built-in in kernel code.
1. scst_exec_req_fifo-2.6.X.patch. This patch is necessary for
pass-through dev handlers, because in the mainstream kernels
scsi_do_req()/scsi_execute_async() work in LIFO order, instead of
expected and required FIFO. So SCST needs new functions
scsi_do_req_fifo() or scsi_execute_async_fifo() to be added in the
kernel. This patch does that. You may not patch the kernel if you don't
need pass-through support. Alternatively, you can define
CONFIG_SCST_STRICT_SERIALIZING compile option during the compilation
(see description below).
To compile SCST type 'make scst'. It will build SCST itself and its
2. io_context-2.6.X.patch. This patch exports some IO context management
functions from the kernel. For performance reasons SCST queues commands
using a pool of IO threads. It is considerably better for performance
(>30% increase on sequential reads) if threads in a pool have the same
IO context. This patch allows that. If you don't apply this patch, you
will loose this performance benefit.
Then, to compile SCST type 'make scst'. It will build SCST itself and its
device handlers. To install them type 'make scst_install'. The driver
modules will be installed in '/lib/modules/`you_kernel_version`/extra'.
In addition, scst.h, scst_debug.h as well as Module.symvers or
@@ -139,6 +148,13 @@ IMPORTANT: In the current version simultaneous access to local SCSI devices
To uninstall, type 'make scst_uninstall'.
Usage in failover mode
----------------------
It is recommended to use TEST UNIT READY ("tur") command to check if
SCST target is alive.
Device handlers
---------------
@@ -236,9 +252,9 @@ in/out in Makefile:
cases. The current SCSI core in Linux doesn't allow to abort all
commands reliably if they sent asynchronously to a stateful device.
Turned off by default, turn it on if you use stateful device(s) and
need as much error recovery reliability as possible. As a side
effect, no kernel patching is necessary for pass-through device
handlers (scst_disk, etc.).
need as much error recovery reliability as possible. As a side effect
of CONFIG_SCST_STRICT_SERIALIZING, no kernel patching is necessary
for pass-through device handlers (scst_disk, etc.).
- CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ - if defined, it will be
allowed to submit pass-through commands to real SCSI devices via the SCSI

View File

@@ -83,6 +83,14 @@ IMPORTANT: In the current version simultaneous access to local SCSI devices
devices READ/WRITE commands using direct disk handler look to
be safe.
Usage in failover mode
----------------------
It is recommended to use TEST UNIT READY ("tur") command to check if
SCST target is alive.
Device handlers
---------------
@@ -179,9 +187,9 @@ your favorit kernel configuration Makefile target, e.g. "make xconfig":
cases. The current SCSI core in Linux doesn't allow to abort all
commands reliably if they sent asynchronously to a stateful device.
Turned off by default, turn it on if you use stateful device(s) and
need as much error recovery reliability as possible. As a side
effect, no kernel patching is necessary for pass-through device
handlers (scst_disk, etc.)
need as much error recovery reliability as possible. As a side effect
of CONFIG_SCST_STRICT_SERIALIZING, no kernel patching is necessary
for pass-through device handlers (scst_disk, etc.).
- CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ - if defined, it will be
allowed to submit pass-through commands to real SCSI devices via the SCSI

View File

@@ -415,19 +415,21 @@ void scst_process_reset(struct scst_device *dev,
static inline int scst_is_ua_command(struct scst_cmd *cmd)
{
return cmd->cdb[0] != INQUIRY
&& cmd->cdb[0] != REQUEST_SENSE
&& cmd->cdb[0] != REPORT_LUNS;
return (cmd->cdb[0] != INQUIRY) &&
(cmd->cdb[0] != REQUEST_SENSE) &&
(cmd->cdb[0] != REPORT_LUNS);
}
static inline int scst_is_implicit_hq(struct scst_cmd *cmd)
{
return cmd->cdb[0] == INQUIRY
|| cmd->cdb[0] == REPORT_LUNS
|| (cmd->dev->type == TYPE_DISK
&& (cmd->cdb[0] == READ_CAPACITY
|| (cmd->cdb[0] == SERVICE_ACTION_IN
&& (cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16)));
return (cmd->cdb[0] == INQUIRY) ||
(cmd->cdb[0] == REPORT_LUNS) ||
((cmd->dev->type == TYPE_DISK) &&
((cmd->cdb[0] == READ_CAPACITY) ||
((cmd->cdb[0] == SERVICE_ACTION_IN) &&
((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16)))) ||
/* Let's don't look dead under high load */
(cmd->cdb[0] == TEST_UNIT_READY);
}
/*