mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 13:16:34 +00:00
1. Added support of 2.6.18 kernels
2. FILEIO_ONLY added git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@14 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -4,6 +4,12 @@ Summary of changes between versions 0.9.4 and 0.9.5
|
||||
- Fixed many found task management related problems, especially in the
|
||||
RESETs area. DEBUG_TM compilation option added (see README).
|
||||
|
||||
- Updated to work on kernels version 2.6.18+.
|
||||
|
||||
- FILEIO_ONLY added. If it's defined, there is no need to patch the
|
||||
kernel, but pass-through modules (scst_disk, scst_tape, etc.) are not
|
||||
supported).
|
||||
|
||||
- Timer-based retries for targets after SCST_TGT_RES_QUEUE_FULL status
|
||||
implemented.
|
||||
|
||||
|
||||
+15
-4
@@ -134,6 +134,11 @@ Compilation options
|
||||
There are the following compilation options, that could be commented
|
||||
in/out in Makefile:
|
||||
|
||||
- FILEIO_ONLY - if defined, the pass-through device handlers
|
||||
(scst_disk, scst_tape) will not work, but SCST will not require the
|
||||
kernel patching. Defined by default to ease new people try SCST on
|
||||
their kernels.
|
||||
|
||||
- DEBUG - turns on some debugging code, including some logging. Makes
|
||||
the driver considerably bigger and slower, producing large amount of
|
||||
log data.
|
||||
@@ -424,12 +429,18 @@ IMPORTANT: Some of those options enabled by default, i.e. SCST is optimized
|
||||
|
||||
IMPORTANT: If you use on initiator some versions of Windows (at least W2K)
|
||||
========= you can't get good write performance for FILEIO devices with
|
||||
default 512 bytes block sizes. You could get about 10% of
|
||||
the expected one. This is because of "unusual" write access
|
||||
default 512 bytes block sizes. You could get about 10% of the
|
||||
expected one. This is because of "unusual" write access
|
||||
pattern, with which Windows'es write data and which is
|
||||
(simplifying) incompatible with how Linux page cache works.
|
||||
(simplifying) incompatible with how Linux page cache works,
|
||||
so for each write the corresponding block must be read first.
|
||||
With 4096 bytes block sizes for FILEIO devices the write
|
||||
performance will be as expected.
|
||||
performance will be as expected. Actually, any system on
|
||||
initiator, not only Windows, will benefit from block size
|
||||
max(PAGE_SIZE, BLOCK_SIZE_ON_UNDERLYING_FS), where PAGE_SIZE
|
||||
is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size on
|
||||
the underlying FS, on which the device file located, or 0, if
|
||||
a device node is used. Both values are on the target.
|
||||
|
||||
Just for reference: we had with 0.9.2 and "old" Qlogic driver on 2.4.2x
|
||||
kernel, where we did carefull performance study, aggregate throuhput
|
||||
|
||||
@@ -1026,7 +1026,9 @@ struct scst_cmd
|
||||
|
||||
struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
struct scsi_request *scsi_req; /* SCSI request */
|
||||
#endif
|
||||
|
||||
/* List entry for tgt_dev's SN related lists */
|
||||
struct list_head sn_cmd_list_entry;
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
--- linux-2.6.18.1-scst-dbg/drivers/scsi/scsi_lib.c_scst 2006-09-20 07:42:06.000000000 +0400
|
||||
+++ linux-2.6.18.1-scst-dbg/drivers/scsi/scsi_lib.c 2006-10-25 20:52:58.000000000 +0400
|
||||
@@ -367,7 +367,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
- * scsi_execute_async - insert request
|
||||
+ * __scsi_execute_async - insert request
|
||||
* @sdev: scsi device
|
||||
* @cmd: scsi command
|
||||
* @cmd_len: length of scsi cdb
|
||||
@@ -378,11 +378,14 @@
|
||||
* @timeout: request timeout in seconds
|
||||
* @retries: number of times to retry request
|
||||
* @flags: or into request flags
|
||||
+ * @at_head: insert request at head or tail of queue
|
||||
**/
|
||||
-int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
|
||||
+static inline int __scsi_execute_async(struct scsi_device *sdev,
|
||||
+ const unsigned char *cmd,
|
||||
int cmd_len, int data_direction, void *buffer, unsigned bufflen,
|
||||
int use_sg, int timeout, int retries, void *privdata,
|
||||
- void (*done)(void *, char *, int, int), gfp_t gfp)
|
||||
+ void (*done)(void *, char *, int, int), gfp_t gfp,
|
||||
+ int at_head)
|
||||
{
|
||||
struct request *req;
|
||||
struct scsi_io_context *sioc;
|
||||
@@ -418,7 +421,7 @@
|
||||
sioc->data = privdata;
|
||||
sioc->done = done;
|
||||
|
||||
- blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async);
|
||||
+ blk_execute_rq_nowait(req->q, NULL, req, at_head, scsi_end_async);
|
||||
return 0;
|
||||
|
||||
free_req:
|
||||
@@ -427,8 +430,53 @@
|
||||
kfree(sioc);
|
||||
return DRIVER_ERROR << 24;
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * scsi_execute_async - insert request
|
||||
+ * @sdev: scsi device
|
||||
+ * @cmd: scsi command
|
||||
+ * @cmd_len: length of scsi cdb
|
||||
+ * @data_direction: data direction
|
||||
+ * @buffer: data buffer (this can be a kernel buffer or scatterlist)
|
||||
+ * @bufflen: len of buffer
|
||||
+ * @use_sg: if buffer is a scatterlist this is the number of elements
|
||||
+ * @timeout: request timeout in seconds
|
||||
+ * @retries: number of times to retry request
|
||||
+ * @flags: or into request flags
|
||||
+ **/
|
||||
+int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
|
||||
+ int cmd_len, int data_direction, void *buffer, unsigned bufflen,
|
||||
+ int use_sg, int timeout, int retries, void *privdata,
|
||||
+ void (*done)(void *, char *, int, int), gfp_t gfp)
|
||||
+{
|
||||
+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer,
|
||||
+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 1);
|
||||
+}
|
||||
EXPORT_SYMBOL_GPL(scsi_execute_async);
|
||||
|
||||
+/**
|
||||
+ * scsi_execute_async_fifi - insert request at tail, in FIFO order
|
||||
+ * @sdev: scsi device
|
||||
+ * @cmd: scsi command
|
||||
+ * @cmd_len: length of scsi cdb
|
||||
+ * @data_direction: data direction
|
||||
+ * @buffer: data buffer (this can be a kernel buffer or scatterlist)
|
||||
+ * @bufflen: len of buffer
|
||||
+ * @use_sg: if buffer is a scatterlist this is the number of elements
|
||||
+ * @timeout: request timeout in seconds
|
||||
+ * @retries: number of times to retry request
|
||||
+ * @flags: or into request flags
|
||||
+ **/
|
||||
+int scsi_execute_async_fifo(struct scsi_device *sdev, const unsigned char *cmd,
|
||||
+ int cmd_len, int data_direction, void *buffer, unsigned bufflen,
|
||||
+ int use_sg, int timeout, int retries, void *privdata,
|
||||
+ void (*done)(void *, char *, int, int), gfp_t gfp)
|
||||
+{
|
||||
+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer,
|
||||
+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 0);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(scsi_execute_async_fifo);
|
||||
+
|
||||
/*
|
||||
* Function: scsi_init_cmd_errh()
|
||||
*
|
||||
--- linux-2.6.18.1-scst-dbg/include/scsi/scsi_device.h_scst 2006-09-20 07:42:06.000000000 +0400
|
||||
+++ linux-2.6.18.1-scst-dbg/include/scsi/scsi_device.h 2006-10-25 20:09:23.000000000 +0400
|
||||
@@ -297,6 +297,12 @@
|
||||
int timeout, int retries, void *privdata,
|
||||
void (*done)(void *, char *, int, int),
|
||||
gfp_t gfp);
|
||||
+extern int scsi_execute_async_fifo(struct scsi_device *sdev,
|
||||
+ const unsigned char *cmd, int cmd_len, int data_direction,
|
||||
+ void *buffer, unsigned bufflen, int use_sg,
|
||||
+ int timeout, int retries, void *privdata,
|
||||
+ void (*done)(void *, char *, int, int),
|
||||
+ gfp_t gfp);
|
||||
|
||||
static inline void scsi_device_reprobe(struct scsi_device *sdev)
|
||||
{
|
||||
+2
-1
@@ -75,7 +75,8 @@ EXTRA_CFLAGS += -I$(INC_DIR)
|
||||
|
||||
#EXTRA_CFLAGS += -DSTRICT_SERIALIZING
|
||||
|
||||
EXTRA_CFLAGS += -DEXTRACHECKS
|
||||
EXTRA_CFLAGS += -DEXTRACHECKS
|
||||
#EXTRA_CFLAGS += -DFILEIO_ONLY
|
||||
|
||||
#EXTRA_CFLAGS += -fno-inline
|
||||
|
||||
|
||||
+26
-2
@@ -631,6 +631,16 @@ int scst_register_dev_driver(struct scst_dev_type *dev_type)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef FILEIO_ONLY
|
||||
if (dev_type->exec == NULL) {
|
||||
PRINT_ERROR_PR("Pass-through dev handlers (handler %s) not "
|
||||
"supported. Recompile SCST with undefined FILEIO_ONLY",
|
||||
dev_type->name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (down_interruptible(&scst_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
@@ -950,11 +960,22 @@ static int __init init_scst(void)
|
||||
{
|
||||
int res = 0, i;
|
||||
struct scst_cmd *cmd;
|
||||
struct scsi_request *req;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
BUILD_BUG_ON(sizeof(cmd->sense_buffer) != sizeof(req->sr_sense_buffer));
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
{
|
||||
struct scsi_request *req;
|
||||
BUILD_BUG_ON(sizeof(cmd->sense_buffer) !=
|
||||
sizeof(req->sr_sense_buffer));
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct scsi_sense_hdr *shdr;
|
||||
BUILD_BUG_ON((sizeof(cmd->sense_buffer) < sizeof(*shdr)) &&
|
||||
(sizeof(cmd->sense_buffer) >= SCSI_SENSE_BUFFERSIZE));
|
||||
}
|
||||
#endif
|
||||
|
||||
scst_num_cpus = get_cpus_count();
|
||||
|
||||
@@ -1130,6 +1151,9 @@ out_destroy_mgmt_cache:
|
||||
|
||||
static void __exit exit_scst(void)
|
||||
{
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static /* To hide the lockdep's warning about non-static key */
|
||||
#endif
|
||||
DECLARE_MUTEX_LOCKED(shm);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
+39
-1
@@ -711,6 +711,7 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name)
|
||||
return res;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
static void scst_req_done(struct scsi_cmnd *scsi_cmd)
|
||||
{
|
||||
struct scsi_request *req;
|
||||
@@ -776,6 +777,41 @@ out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */
|
||||
static void scst_send_release(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
struct scsi_device *scsi_dev;
|
||||
unsigned char cdb[6];
|
||||
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (tgt_dev->acg_dev->dev->scsi_dev == NULL)
|
||||
goto out;
|
||||
|
||||
scsi_dev = tgt_dev->acg_dev->dev->scsi_dev;
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = RELEASE;
|
||||
cdb[1] = (scsi_dev->scsi_level <= SCSI_2) ?
|
||||
((scsi_dev->lun << 5) & 0xe0) : 0;
|
||||
|
||||
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,
|
||||
3, GFP_KERNEL);
|
||||
if (rc) {
|
||||
PRINT_INFO_PR("scsi_execute() failed: %d", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */
|
||||
|
||||
struct scst_session *scst_alloc_session(struct scst_tgt *tgt, int gfp_mask,
|
||||
const char *initiator_name)
|
||||
@@ -944,7 +980,7 @@ void scst_free_cmd(struct scst_cmd *cmd)
|
||||
|
||||
BUG_ON(cmd->blocking);
|
||||
|
||||
#ifdef EXTRACHECKS
|
||||
#if defined(EXTRACHECKS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
|
||||
if (cmd->scsi_req) {
|
||||
PRINT_ERROR_PR("%s: %s", __FUNCTION__, "Cmd with unfreed "
|
||||
"scsi_req!");
|
||||
@@ -1114,6 +1150,7 @@ void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd, int del)
|
||||
return;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
int scst_alloc_request(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -1154,6 +1191,7 @@ void scst_release_request(struct scst_cmd *cmd)
|
||||
scsi_release_request(cmd->scsi_req);
|
||||
cmd->scsi_req = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int scst_alloc_space(struct scst_cmd *cmd)
|
||||
{
|
||||
|
||||
+29
-4
@@ -24,9 +24,12 @@
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_driver.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_request.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
#include <scsi/scsi_request.h>
|
||||
#endif
|
||||
|
||||
#define SCST_MAJOR 177
|
||||
|
||||
#define TRACE_RETRY 0x80000000
|
||||
@@ -250,6 +253,7 @@ static inline void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
void scst_check_retries(struct scst_tgt *tgt, int processible_env);
|
||||
void scst_tgt_retry_timer_fn(unsigned long arg);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
int scst_alloc_request(struct scst_cmd *cmd);
|
||||
void scst_release_request(struct scst_cmd *cmd);
|
||||
|
||||
@@ -257,12 +261,33 @@ static inline void scst_do_req(struct scsi_request *sreq,
|
||||
const void *cmnd, void *buffer, unsigned bufflen,
|
||||
void (*done)(struct scsi_cmnd *), int timeout, int retries)
|
||||
{
|
||||
#ifdef STRICT_SERIALIZING
|
||||
#ifdef STRICT_SERIALIZING
|
||||
scsi_do_req(sreq, cmnd, buffer, bufflen, done, timeout, retries);
|
||||
#else
|
||||
#elif defined(FILEIO_ONLY)
|
||||
BUG();
|
||||
#else
|
||||
scsi_do_req_fifo(sreq, cmnd, buffer, bufflen, done, timeout, retries);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static inline int scst_exec_req(struct scsi_device *sdev,
|
||||
const unsigned char *cmd, int cmd_len, int data_direction,
|
||||
void *buffer, unsigned bufflen, int use_sg, int timeout, int retries,
|
||||
void *privdata, void (*done)(void *, char *, int, int), gfp_t gfp)
|
||||
{
|
||||
#ifdef STRICT_SERIALIZING
|
||||
return scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer,
|
||||
bufflen, use_sg, timeout, retries, privdata, done, gfp);
|
||||
#elif defined(FILEIO_ONLY)
|
||||
BUG();
|
||||
return -1;
|
||||
#else
|
||||
return scsi_execute_async_fifo(sdev, cmd, cmd_len, data_direction,
|
||||
buffer, bufflen, use_sg, timeout, retries, privdata, done, gfp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int scst_alloc_space(struct scst_cmd *cmd);
|
||||
void scst_release_space(struct scst_cmd *cmd);
|
||||
void scst_scsi_op_list_init(void);
|
||||
|
||||
+114
-55
@@ -823,8 +823,8 @@ void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context)
|
||||
}
|
||||
|
||||
/* No locks supposed to be held */
|
||||
static void scst_check_sense(struct scst_cmd *cmd, struct scsi_request *req,
|
||||
int *next_state)
|
||||
static void scst_check_sense(struct scst_cmd *cmd, const uint8_t *rq_sense,
|
||||
int rq_sense_len, int *next_state)
|
||||
{
|
||||
int sense_valid;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
@@ -848,11 +848,15 @@ static void scst_check_sense(struct scst_cmd *cmd, struct scsi_request *req,
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
if (req != NULL) {
|
||||
sense_valid = SCST_SENSE_VALID(req->sr_sense_buffer);
|
||||
if (rq_sense != NULL) {
|
||||
sense_valid = SCST_SENSE_VALID(rq_sense);
|
||||
if (sense_valid) {
|
||||
memcpy(cmd->sense_buffer, req->sr_sense_buffer,
|
||||
sizeof(cmd->sense_buffer));
|
||||
memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
|
||||
/*
|
||||
* We checked that rq_sense_len < sizeof(cmd->sense_buffer)
|
||||
* in init_scst()
|
||||
*/
|
||||
memcpy(cmd->sense_buffer, rq_sense, rq_sense_len);
|
||||
}
|
||||
} else
|
||||
sense_valid = SCST_SENSE_VALID(cmd->sense_buffer);
|
||||
@@ -971,38 +975,60 @@ static int scst_check_auto_sense(struct scst_cmd *cmd)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void scst_do_cmd_done(struct scst_cmd *cmd,
|
||||
struct scsi_request *req, int *next_state)
|
||||
static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
|
||||
const uint8_t *rq_sense, int rq_sense_len, int *next_state)
|
||||
{
|
||||
unsigned char type;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd->status = req->sr_result & 0xff;
|
||||
cmd->masked_status = status_byte(req->sr_result);
|
||||
cmd->msg_status = msg_byte(req->sr_result);
|
||||
cmd->host_status = host_byte(req->sr_result);
|
||||
cmd->driver_status = driver_byte(req->sr_result);
|
||||
TRACE(TRACE_SCSI, "req->sr_result=%x, cmd->status=%x, "
|
||||
cmd->status = result & 0xff;
|
||||
cmd->masked_status = status_byte(result);
|
||||
cmd->msg_status = msg_byte(result);
|
||||
cmd->host_status = host_byte(result);
|
||||
cmd->driver_status = driver_byte(result);
|
||||
TRACE(TRACE_SCSI, "result=%x, cmd->status=%x, "
|
||||
"cmd->masked_status=%x, cmd->msg_status=%x, cmd->host_status=%x, "
|
||||
"cmd->driver_status=%x", req->sr_result, cmd->status,
|
||||
"cmd->driver_status=%x", result, cmd->status,
|
||||
cmd->masked_status, cmd->msg_status, cmd->host_status,
|
||||
cmd->driver_status);
|
||||
|
||||
scst_check_sense(cmd, req, next_state);
|
||||
cmd->completed = 1;
|
||||
|
||||
cmd->bufflen = req->sr_bufflen; //??
|
||||
scst_dec_on_dev_cmd(cmd);
|
||||
|
||||
/* Clear out request structure */
|
||||
req->sr_use_sg = 0;
|
||||
req->sr_sglist_len = 0;
|
||||
req->sr_bufflen = 0;
|
||||
req->sr_buffer = NULL;
|
||||
req->sr_underflow = 0;
|
||||
req->sr_request->rq_disk = NULL; /* disown request blk */ ;
|
||||
type = cmd->dev->handler->type;
|
||||
if ((cmd->cdb[0] == MODE_SENSE || cmd->cdb[0] == MODE_SENSE_10) &&
|
||||
cmd->tgt_dev->acg_dev->rd_only_flag &&
|
||||
(type == TYPE_DISK || type == TYPE_WORM || type == TYPE_MOD ||
|
||||
type == TYPE_TAPE)) {
|
||||
int32_t length;
|
||||
uint8_t *address;
|
||||
|
||||
length = scst_get_buf_first(cmd, &address);
|
||||
TRACE_DBG("length %d", length);
|
||||
if (unlikely(length <= 0)) {
|
||||
PRINT_ERROR_PR("%s: scst_get_buf_first() failed",
|
||||
__func__);
|
||||
goto next;
|
||||
}
|
||||
if (length > 2 && cmd->cdb[0] == MODE_SENSE) {
|
||||
address[2] |= 0x80; /* Write Protect*/
|
||||
}
|
||||
else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10) {
|
||||
address[3] |= 0x80; /* Write Protect*/
|
||||
}
|
||||
scst_put_buf(cmd, address);
|
||||
}
|
||||
|
||||
next:
|
||||
scst_check_sense(cmd, rq_sense, rq_sense_len, next_state);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
static inline struct scst_cmd *scst_get_cmd(struct scsi_cmnd *scsi_cmd,
|
||||
struct scsi_request **req)
|
||||
{
|
||||
@@ -1025,7 +1051,6 @@ static void scst_cmd_done(struct scsi_cmnd *scsi_cmd)
|
||||
struct scsi_request *req = NULL;
|
||||
struct scst_cmd *cmd;
|
||||
int next_state;
|
||||
unsigned char type;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -1044,35 +1069,19 @@ static void scst_cmd_done(struct scsi_cmnd *scsi_cmd)
|
||||
if (cmd == NULL)
|
||||
goto out;
|
||||
|
||||
cmd->completed = 1;
|
||||
|
||||
scst_dec_on_dev_cmd(cmd);
|
||||
|
||||
type = cmd->dev->handler->type;
|
||||
if ((cmd->cdb[0] == MODE_SENSE || cmd->cdb[0] == MODE_SENSE_10) &&
|
||||
cmd->tgt_dev->acg_dev->rd_only_flag &&
|
||||
(type == TYPE_DISK || type == TYPE_WORM || type == TYPE_MOD ||
|
||||
type == TYPE_TAPE)) {
|
||||
int32_t length;
|
||||
uint8_t *address;
|
||||
|
||||
length = scst_get_buf_first(cmd, &address);
|
||||
TRACE_DBG("length %d", length);
|
||||
if (unlikely(length <= 0)) {
|
||||
goto out;
|
||||
}
|
||||
if (length > 2 && cmd->cdb[0] == MODE_SENSE) {
|
||||
address[2] |= 0x80; /* Write Protect*/
|
||||
}
|
||||
else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10) {
|
||||
address[3] |= 0x80; /* Write Protect*/
|
||||
}
|
||||
scst_put_buf(cmd, address);
|
||||
}
|
||||
|
||||
next_state = SCST_CMD_STATE_DEV_DONE;
|
||||
scst_do_cmd_done(cmd, req->sr_result, req->sr_sense_buffer,
|
||||
sizeof(req->sr_sense_buffer), &next_state);
|
||||
|
||||
scst_do_cmd_done(cmd, req, &next_state);
|
||||
/* Clear out request structure */
|
||||
req->sr_use_sg = 0;
|
||||
req->sr_sglist_len = 0;
|
||||
req->sr_bufflen = 0;
|
||||
req->sr_buffer = NULL;
|
||||
req->sr_underflow = 0;
|
||||
req->sr_request->rq_disk = NULL; /* disown request blk */
|
||||
|
||||
cmd->bufflen = req->sr_bufflen; //??
|
||||
|
||||
scst_release_request(cmd);
|
||||
|
||||
@@ -1085,6 +1094,43 @@ out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */
|
||||
static void scst_cmd_done(void *data, char *sense, int result, int resid)
|
||||
{
|
||||
struct scst_cmd *cmd;
|
||||
int next_state;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
WARN_ON(in_irq());
|
||||
|
||||
/*
|
||||
* We don't use resid, because:
|
||||
* 1. Many low level initiator drivers don't use (set) this field
|
||||
* 2. We determine the command's buffer size directly from CDB,
|
||||
* so resid is not relevant for us, and target drivers
|
||||
* should know the residual, if necessary, by comparing expected
|
||||
* and actual transfer sizes.
|
||||
*/
|
||||
|
||||
cmd = (struct scst_cmd *)data;
|
||||
if (cmd == NULL)
|
||||
goto out;
|
||||
|
||||
next_state = SCST_CMD_STATE_DEV_DONE;
|
||||
scst_do_cmd_done(cmd, result, sense, SCSI_SENSE_BUFFERSIZE,
|
||||
&next_state);
|
||||
|
||||
cmd->state = next_state;
|
||||
cmd->non_atomic_only = 0;
|
||||
|
||||
__scst_process_active_cmd(cmd, scst_get_context(), 0);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */
|
||||
|
||||
static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
|
||||
{
|
||||
@@ -1133,7 +1179,7 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
|
||||
}
|
||||
#endif
|
||||
|
||||
scst_check_sense(cmd, NULL, &next_state);
|
||||
scst_check_sense(cmd, NULL, 0, &next_state);
|
||||
|
||||
cmd->state = next_state;
|
||||
cmd->non_atomic_only = 0;
|
||||
@@ -1557,7 +1603,8 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
|
||||
(uint64_t)cmd->lun);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
if (scst_alloc_request(cmd) != 0) {
|
||||
PRINT_INFO_PR("%s", "Unable to allocate request, "
|
||||
"sending BUSY status");
|
||||
@@ -1568,6 +1615,16 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
|
||||
(void *)cmd->scsi_req->sr_buffer,
|
||||
cmd->scsi_req->sr_bufflen, scst_cmd_done, cmd->timeout,
|
||||
cmd->retries);
|
||||
#else
|
||||
rc = scst_exec_req(cmd->dev->scsi_dev, cmd->cdb, cmd->cdb_len,
|
||||
cmd->data_direction, cmd->sg, cmd->bufflen, cmd->sg_cnt,
|
||||
cmd->timeout, cmd->retries, cmd, scst_cmd_done,
|
||||
GFP_KERNEL);
|
||||
if (rc) {
|
||||
PRINT_INFO_PR("scst_exec_req() failed: %d", rc);
|
||||
goto out_error;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = SCST_EXEC_COMPLETED;
|
||||
|
||||
@@ -1593,7 +1650,8 @@ out_error:
|
||||
rc = SCST_EXEC_COMPLETED;
|
||||
scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT);
|
||||
goto out;
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
out_busy:
|
||||
scst_set_busy(cmd);
|
||||
cmd->completed = 1;
|
||||
@@ -1601,6 +1659,7 @@ out_busy:
|
||||
rc = SCST_EXEC_COMPLETED;
|
||||
scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT);
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
out_aborted:
|
||||
rc = SCST_EXEC_COMPLETED;
|
||||
|
||||
Reference in New Issue
Block a user