A bunch of small fixes and cleanups before 0.9.5

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@36 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2006-11-30 16:24:09 +00:00
parent 7e8e976d2b
commit e0e00e0e8e
7 changed files with 275 additions and 273 deletions
+2
View File
@@ -10,6 +10,8 @@ Summary of changes between versions 0.9.4 and 0.9.5
kernel, but pass-through modules (scst_disk, scst_tape, etc.) are not
supported).
- Fixed problems with big amount of LUNs (500+).
- Timer-based retries for targets after SCST_TGT_RES_QUEUE_FULL status
implemented.
+4 -4
View File
@@ -255,16 +255,16 @@ following files and directories under /proc/scsi_tgt:
- "del_group GROUP" to /proc/scsi_tgt/scsi_tgt deletes group "GROUP"
- "add H:C:I:L lun [RO]" to /proc/scsi_tgt/groups/GROUP/devices adds
- "add H:C:I:L lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with host:channel:id:lun as LUN "lun" in group "GROUP". Optionally,
the device could be marked as read only.
- "del H:C:I:L" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
host:channel:id:lun from group "GROUP"
- "add V_NAME lun [RO]" to /proc/scsi_tgt/groups/GROUP/devices adds device with
virtual name "V_NAME" as LUN "lun" in group "GROUP". Optionally, the device
could be marked as read only.
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with virtual name "V_NAME" as LUN "lun" in group "GROUP".
Optionally, the device could be marked as read only.
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
virtual name "V_NAME" from group "GROUP"
+3 -6
View File
@@ -2274,13 +2274,10 @@ static int fileio_proc_update_size(int size, off_t offset, int length,
if (size > 0) {
p->len += size;
p->pos = p->begin + p->len;
if (p->pos < offset) {
if (p->pos <= offset) {
p->len = 0;
p->begin = p->pos;
}
if (p->pos > offset + length) {
p->begin = p->pbegin;
p->len = p->plen;
} else if (p->pos >= offset + length) {
res = 1;
goto out;
} else
@@ -2620,7 +2617,7 @@ stop_output:
pu.len -= (offset - pu.begin);
if (pu.len > length)
pu.len = length;
res = pu.len;
res = max(0, pu.len);
goto out_up;
out_free_vpath:
+123 -1
View File
@@ -692,6 +692,128 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name)
return res;
}
struct scst_cmd *scst_create_prepare_internal_cmd(
struct scst_cmd *orig_cmd, int bufsize)
{
struct scst_cmd *res;
int gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL;
TRACE_ENTRY();
res = scst_alloc_cmd(gfp_mask);
if (unlikely(res == NULL)) {
goto out;
}
res->sess = orig_cmd->sess;
res->state = SCST_CMD_STATE_SEND_TO_MIDLEV;
res->atomic = scst_cmd_atomic(orig_cmd);
res->internal = 1;
res->tgtt = orig_cmd->tgtt;
res->tgt = orig_cmd->tgt;
res->dev = orig_cmd->dev;
res->tgt_dev = orig_cmd->tgt_dev;
res->lun = orig_cmd->lun;
res->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
res->data_direction = SCST_DATA_UNKNOWN;
res->orig_cmd = orig_cmd;
res->bufflen = bufsize;
if (bufsize > 0) {
if (scst_alloc_space(res) != 0)
PRINT_ERROR("Unable to create buffer (size %d) for "
"internal cmd", bufsize);
goto out_free_res;
}
out:
TRACE_EXIT_HRES((unsigned long)res);
return res;
out_free_res:
scst_destroy_cmd(res);
res = NULL;
goto out;
}
void scst_free_internal_cmd(struct scst_cmd *cmd)
{
TRACE_ENTRY();
if (cmd->bufflen > 0)
scst_release_space(cmd);
scst_destroy_cmd(cmd);
TRACE_EXIT();
return;
}
int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
{
int res = SCST_CMD_STATE_RES_RESTART;
#define sbuf_size 252
static const unsigned char request_sense[6] =
{ REQUEST_SENSE, 0, 0, 0, sbuf_size, 0 };
struct scst_cmd *rs_cmd;
TRACE_ENTRY();
rs_cmd = scst_create_prepare_internal_cmd(orig_cmd, sbuf_size);
if (rs_cmd != 0)
goto out_error;
memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
rs_cmd->cdb_len = sizeof(request_sense);
rs_cmd->data_direction = SCST_DATA_READ;
spin_lock_irq(&scst_list_lock);
list_add(&rs_cmd->cmd_list_entry, &scst_active_cmd_list);
spin_unlock_irq(&scst_list_lock);
out:
TRACE_EXIT_RES(res);
return res;
out_error:
res = -1;
goto out;
#undef sbuf_size
}
struct scst_cmd *scst_complete_request_sense(struct scst_cmd *cmd)
{
struct scst_cmd *orig_cmd = cmd->orig_cmd;
uint8_t *buf;
int len;
TRACE_ENTRY();
BUG_ON(orig_cmd);
len = scst_get_buf_first(cmd, &buf);
if ((cmd->status == 0) && SCST_SENSE_VALID(buf) &&
(!SCST_NO_SENSE(buf)))
{
TRACE_BUFF_FLAG(TRACE_SCSI, "REQUEST SENSE returned",
buf, len);
memcpy(orig_cmd->sense_buffer, buf,
(sizeof(orig_cmd->sense_buffer) > len) ?
len : sizeof(orig_cmd->sense_buffer));
} else {
PRINT_ERROR_PR("%s", "Unable to get the sense via "
"REQUEST SENSE, returning HARDWARE ERROR");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
}
scst_put_buf(cmd, buf);
scst_free_internal_cmd(cmd);
TRACE_EXIT_HRES((unsigned long)orig_cmd);
return orig_cmd;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
static void scst_req_done(struct scsi_cmnd *scsi_cmd)
{
@@ -1561,7 +1683,7 @@ lun_t scst_unpack_lun(const uint8_t *lun, int len)
address_method = (*lun) >> 6; /* high 2 bits of byte 0 */
switch (address_method) {
case 0: /* peripheral device addressing method */
#if 0 /* At least QLA2300 Linux ini uses it as the flat space addressing method */
#if 0 /* Looks like it's legal to use it as flat space addressing method as well */
if (*lun) {
PRINT_ERROR_PR("Illegal BUS INDENTIFIER in LUN "
"peripheral device addressing method 0x%02x, "
+6
View File
@@ -237,6 +237,12 @@ int scst_acg_remove_dev(struct scst_acg *acg, struct scst_device *dev);
int scst_acg_add_name(struct scst_acg *acg, const char *name);
int scst_acg_remove_name(struct scst_acg *acg, const char *name);
struct scst_cmd *scst_create_prepare_internal_cmd(
struct scst_cmd *orig_cmd, int bufsize);
void scst_free_internal_cmd(struct scst_cmd *cmd);
int scst_prepare_request_sense(struct scst_cmd *orig_cmd);
struct scst_cmd *scst_complete_request_sense(struct scst_cmd *cmd);
int scst_assign_dev_handler(struct scst_device *dev,
struct scst_dev_type *handler);
+52 -56
View File
@@ -228,11 +228,10 @@ int scst_proc_read_tlb(const struct scst_proc_log *tbl, char *buffer,
if (*size > 0) {
*len += *size;
*pos = *begin + *len;
if (*pos < offset) {
if (*pos <= offset) {
*len = 0;
*begin = *pos;
}
if (*pos > offset + length)
} else if (*pos >= offset + length)
goto out_end;
} else
goto out_end;
@@ -278,11 +277,10 @@ int scst_proc_log_entry_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
} else if (pos >= offset + length)
goto stop_output;
} else
goto stop_output;
@@ -292,7 +290,7 @@ stop_output:
len -= (offset - begin);
if (len > length)
len = length;
res = len;
res = max(0, len);
TRACE_EXIT_RES(res);
return res;
}
@@ -739,13 +737,10 @@ static int scst_proc_update_size(int size, off_t offset, int length,
if (size > 0) {
p->len += size;
p->pos = p->begin + p->len;
if (p->pos < offset) {
if (p->pos <= offset) {
p->len = 0;
p->begin = p->pos;
}
if (p->pos > offset + length) {
p->begin = p->pbegin;
p->len = p->plen;
} else if (p->pos >= offset + length) {
res = 1;
goto out;
} else
@@ -836,7 +831,7 @@ stop_output:
st.len -= (offset - st.begin);
if (st.len > length)
st.len = length;
res = st.len;
res = max(0, st.len);
TRACE_EXIT_RES(res);
return res;
@@ -1006,6 +1001,8 @@ static int scst_scsi_tgt_proc_info(char *buffer, char **start,
TRACE_ENTRY();
//TRACE(TRACE_SPECIAL, "offset=%ld, length=%d", offset, length);
if (down_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out;
@@ -1014,14 +1011,17 @@ static int scst_scsi_tgt_proc_info(char *buffer, char **start,
size = scnprintf(buffer + len, length - len, "%-60s%s\n",
"Device (host:ch:id:lun or name)",
"Device handler");
//TRACE(TRACE_SPECIAL, "size=%d, pos=%ld, begin=%ld, len=%d, buf %s",
// size, pos, begin, len, buffer+len);
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
} else if (pos >= offset + length)
goto stop_output;
} else
goto stop_output;
@@ -1030,31 +1030,35 @@ static int scst_scsi_tgt_proc_info(char *buffer, char **start,
pplen = plen = len;
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
if (dev->virt_id == 0) {
char conv[12];
size = scnprintf(buffer + len, length - len,
"%d:%d:%d:%-54d%s\n",
"%d:%d:%d:",
dev->scsi_dev->host->host_no,
dev->scsi_dev->channel,
dev->scsi_dev->id,
dev->scsi_dev->lun,
dev->handler ? dev->handler->name :
"-");
dev->scsi_dev->id);
sprintf(conv, "%%-%dd%%s\n", 60-size);
size += scnprintf(buffer + len + size, length - len - size,
conv, dev->scsi_dev->lun,
dev->handler ? dev->handler->name : "-");
} else {
size = scnprintf(buffer + len, length - len,
"%-60s%s\n",
dev->virt_name, dev->handler->name);
}
//printk("size=%d, pbegin=%ld, plen=%d, ppbegin=%ld, pplen=%d, buf %s",
// size, pbegin, plen, ppbegin, pplen, buffer+len);
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length) {
begin = pbegin;
len = plen;
//TRACE(TRACE_SPECIAL, "pos=%ld, begin=%ld, len=%d", pos, begin, len);
if (pos >= offset + length)
goto stop_output;
}
} else {
begin = ppbegin;
len = pplen;
@@ -1073,7 +1077,9 @@ stop_output:
len -= (offset - begin);
if (len > length)
len = length;
res = len;
res = max(0, len);
//TRACE(TRACE_SPECIAL, "res=%d, start=%ld, len=%d, begin=%ld, eof=%d", res, offset-begin, len, begin, *eof);
up(&scst_mutex);
@@ -1822,11 +1828,10 @@ static int scst_proc_groups_devices_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
} else if (pos >= offset + length)
goto stop_output;
} else
goto stop_output;
@@ -1835,11 +1840,15 @@ static int scst_proc_groups_devices_read(char *buffer, char **start,
pplen = plen = len;
list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
if (acg_dev->dev->virt_id == 0) {
char conv[20];
size = scnprintf(buffer + len, length - len,
"%d:%d:%d:%-54d%4d%12s\n",
"%d:%d:%d:",
acg_dev->dev->scsi_dev->host->host_no,
acg_dev->dev->scsi_dev->channel,
acg_dev->dev->scsi_dev->id,
acg_dev->dev->scsi_dev->id);
sprintf(conv, "%%-%dd%%4d%%12s\n", 60-size);
size += scnprintf(buffer + len + size,
length - len - size, conv,
acg_dev->dev->scsi_dev->lun,
acg_dev->lun,
acg_dev->rd_only_flag ? "RO" : "");
@@ -1852,15 +1861,11 @@ static int scst_proc_groups_devices_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length) {
begin = pbegin;
len = plen;
} else if (pos >= offset + length)
goto stop_output;
}
} else {
begin = ppbegin;
len = pplen;
@@ -1879,7 +1884,7 @@ stop_output:
len -= (offset - begin);
if (len > length)
len = length;
res = len;
res = max(0, len);
up(&scst_mutex);
@@ -2099,11 +2104,10 @@ static int scst_proc_sessions_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
} else if (pos >= offset + length)
goto stop_output;
} else
goto stop_output;
@@ -2121,15 +2125,11 @@ static int scst_proc_sessions_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length) {
begin = pbegin;
len = plen;
} else if (pos >= offset + length)
goto stop_output;
}
} else {
begin = ppbegin;
len = pplen;
@@ -2149,7 +2149,7 @@ stop_output:
len -= (offset - begin);
if (len > length)
len = length;
res = len;
res = max(0, len);
up(&scst_mutex);
@@ -2183,15 +2183,11 @@ static int scst_proc_groups_names_read(char *buffer, char **start,
if (size > 0) {
len += size;
pos = begin + len;
if (pos < offset) {
if (pos <= offset) {
len = 0;
begin = pos;
}
if (pos > offset + length) {
begin = pbegin;
len = plen;
} else if (pos >= offset + length)
goto stop_output;
}
} else {
begin = ppbegin;
len = pplen;
@@ -2210,7 +2206,7 @@ stop_output:
len -= (offset - begin);
if (len > length)
len = length;
res = len;
res = max(0, len);
up(&scst_mutex);
+85 -206
View File
@@ -1141,15 +1141,6 @@ static void scst_cmd_done(void *data, char *sense, int result, int resid)
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;
@@ -1180,8 +1171,8 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
if (next_state == SCST_CMD_STATE_DEFAULT)
next_state = SCST_CMD_STATE_DEV_DONE;
if (next_state == SCST_CMD_STATE_DEV_DONE) {
#if defined(DEBUG) || defined(TRACING)
if (next_state == SCST_CMD_STATE_DEV_DONE) {
if (cmd->sg) {
int i;
struct scatterlist *sg = cmd->sg;
@@ -1194,8 +1185,8 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
sg[i].length);
}
}
#endif
}
#endif
#ifdef EXTRACHECKS
@@ -1244,7 +1235,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
cmd->host_status = DID_OK;
cmd->driver_status = 0;
if (cmd->cdb[2] != 0) {
if ((cmd->cdb[2] != 0) && (cmd->cdb[2] != 2)) {
PRINT_ERROR_PR("Unsupported SELECT REPORT value %x in REPORT "
"LUNS command", cmd->cdb[2]);
goto out_err;
@@ -1267,7 +1258,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
if (!overflow) {
if (offs >= buffer_size) {
scst_put_buf(cmd, buffer);
buffer_size = scst_get_buf_first(cmd, &buffer);
buffer_size = scst_get_buf_next(cmd, &buffer);
if (buffer_size > 0) {
memset(buffer, 0, buffer_size);
offs = 0;
@@ -1284,7 +1275,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
goto out_put_hw_err;
}
buffer[offs] = (tgt_dev->acg_dev->lun >> 8) & 0xff;
buffer[offs + 1] = tgt_dev->acg_dev->lun & 0xff;
buffer[offs+1] = tgt_dev->acg_dev->lun & 0xff;
offs += 8;
}
inc_dev_cnt:
@@ -1490,51 +1481,53 @@ static int scst_pre_exec(struct scst_cmd *cmd)
TRACE_ENTRY();
/* Reserve check before Unit Attention */
if (unlikely(test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) &&
(cmd->cdb[0] != INQUIRY) &&
(cmd->cdb[0] != REPORT_LUNS) &&
(cmd->cdb[0] != RELEASE) &&
(cmd->cdb[0] != RELEASE_10) &&
(cmd->cdb[0] != REPORT_DEVICE_IDENTIFIER) &&
(cmd->cdb[0] != ALLOW_MEDIUM_REMOVAL || (cmd->cdb[4] & 3)) &&
(cmd->cdb[0] != LOG_SENSE) && (cmd->cdb[0] != REQUEST_SENSE))
{
scst_report_reserved(cmd);
res = SCST_EXEC_COMPLETED;
goto out;
if (unlikely(test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags))) {
if ((cmd->cdb[0] != INQUIRY) && (cmd->cdb[0] != REPORT_LUNS) &&
(cmd->cdb[0] != RELEASE) && (cmd->cdb[0] != RELEASE_10) &&
(cmd->cdb[0] != REPORT_DEVICE_IDENTIFIER) &&
(cmd->cdb[0] != ALLOW_MEDIUM_REMOVAL || (cmd->cdb[4] & 3)) &&
(cmd->cdb[0] != LOG_SENSE) && (cmd->cdb[0] != REQUEST_SENSE))
{
scst_report_reserved(cmd);
res = SCST_EXEC_COMPLETED;
goto out;
}
}
/* If we had a internal bus reset, set the command error unit attention */
if ((cmd->dev->scsi_dev != NULL) &&
unlikely(cmd->dev->scsi_dev->was_reset) &&
scst_is_ua_command(cmd))
{
struct scst_device *dev = cmd->dev;
int done = 0;
/* Prevent more than 1 cmd to be triggered by was_reset */
spin_lock_bh(&dev->dev_lock);
barrier(); /* to reread was_reset */
if (dev->scsi_dev->was_reset) {
TRACE(TRACE_MGMT, "was_reset is %d", 1);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_reset_UA));
/* It looks like it is safe to clear was_reset here */
dev->scsi_dev->was_reset = 0;
smp_mb();
done = 1;
}
spin_unlock_bh(&dev->dev_lock);
unlikely(cmd->dev->scsi_dev->was_reset)) {
if (scst_is_ua_command(cmd))
{
struct scst_device *dev = cmd->dev;
int done = 0;
/* Prevent more than 1 cmd to be triggered by was_reset */
spin_lock_bh(&dev->dev_lock);
barrier(); /* to reread was_reset */
if (dev->scsi_dev->was_reset) {
TRACE(TRACE_MGMT, "was_reset is %d", 1);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_reset_UA));
/* It looks like it is safe to clear was_reset here */
dev->scsi_dev->was_reset = 0;
smp_mb();
done = 1;
}
spin_unlock_bh(&dev->dev_lock);
if (done)
goto out_done;
if (done)
goto out_done;
}
}
if (test_bit(SCST_TGT_DEV_UA_PENDING, &cmd->tgt_dev->tgt_dev_flags) &&
scst_is_ua_command(cmd))
{
rc = scst_set_pending_UA(cmd);
if (rc == 0)
goto out_done;
if (unlikely(test_bit(SCST_TGT_DEV_UA_PENDING,
&cmd->tgt_dev->tgt_dev_flags))) {
if (scst_is_ua_command(cmd))
{
rc = scst_set_pending_UA(cmd);
if (rc == 0)
goto out_done;
}
}
/* Check READ_ONLY device status */
@@ -1653,14 +1646,12 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
/* !! At this point cmd, sess & tgt_dev can be already freed !! */
TRACE_DBG("Dev handler %s exec() returned %d",
dev->handler->name, rc);
if (rc != SCST_EXEC_NOT_COMPLETED) {
if (rc == SCST_EXEC_COMPLETED)
goto out;
else if (rc == SCST_EXEC_NEED_THREAD)
goto out_clear;
else
goto out_rc_error;
}
if (rc == SCST_EXEC_COMPLETED)
goto out;
else if (rc == SCST_EXEC_NEED_THREAD)
goto out_clear;
else if (rc != SCST_EXEC_NOT_COMPLETED)
goto out_rc_error;
}
TRACE_DBG("Sending cmd %p to SCSI mid-level", cmd);
@@ -1673,10 +1664,15 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
}
#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");
goto out_busy;
if (unlikely(scst_alloc_request(cmd) != 0)) {
if (scst_cmd_atomic(cmd)) {
rc = SCST_EXEC_NEED_THREAD;
goto out_clear;
} else {
PRINT_INFO_PR("%s", "Unable to allocate request, "
"sending BUSY status");
goto out_busy;
}
}
scst_do_req(cmd->scsi_req, (void *)cmd->cdb,
@@ -1687,10 +1683,15 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
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;
scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
if (unlikely(rc != 0)) {
if (scst_cmd_atomic(cmd)) {
rc = SCST_EXEC_NEED_THREAD;
goto out_clear;
} else {
PRINT_INFO_PR("scst_exec_req() failed: %d", rc);
goto out_error;
}
}
#endif
@@ -1838,128 +1839,6 @@ out:
return res;
}
static struct scst_cmd *scst_create_prepare_internal_cmd(
struct scst_cmd *orig_cmd, int bufsize)
{
struct scst_cmd *res;
int gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL;
TRACE_ENTRY();
res = scst_alloc_cmd(gfp_mask);
if (unlikely(res == NULL)) {
goto out;
}
res->sess = orig_cmd->sess;
res->state = SCST_CMD_STATE_SEND_TO_MIDLEV;
res->atomic = scst_cmd_atomic(orig_cmd);
res->internal = 1;
res->tgtt = orig_cmd->tgtt;
res->tgt = orig_cmd->tgt;
res->dev = orig_cmd->dev;
res->tgt_dev = orig_cmd->tgt_dev;
res->lun = orig_cmd->lun;
res->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
res->data_direction = SCST_DATA_UNKNOWN;
res->orig_cmd = orig_cmd;
res->bufflen = bufsize;
if (bufsize > 0) {
if (scst_alloc_space(res) != 0)
PRINT_ERROR("Unable to create buffer (size %d) for "
"internal cmd", bufsize);
goto out_free_res;
}
out:
TRACE_EXIT_HRES((unsigned long)res);
return res;
out_free_res:
scst_destroy_cmd(res);
res = NULL;
goto out;
}
static void scst_free_internal_cmd(struct scst_cmd *cmd)
{
TRACE_ENTRY();
if (cmd->bufflen > 0)
scst_release_space(cmd);
scst_destroy_cmd(cmd);
TRACE_EXIT();
return;
}
static int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
{
int res = SCST_CMD_STATE_RES_RESTART;
#define sbuf_size 252
static const unsigned char request_sense[6] =
{ REQUEST_SENSE, 0, 0, 0, sbuf_size, 0 };
struct scst_cmd *rs_cmd;
TRACE_ENTRY();
rs_cmd = scst_create_prepare_internal_cmd(orig_cmd, sbuf_size);
if (rs_cmd != 0)
goto out_error;
memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
rs_cmd->cdb_len = sizeof(request_sense);
rs_cmd->data_direction = SCST_DATA_READ;
spin_lock_irq(&scst_list_lock);
list_add(&rs_cmd->cmd_list_entry, &scst_active_cmd_list);
spin_unlock_irq(&scst_list_lock);
out:
TRACE_EXIT_RES(res);
return res;
out_error:
res = -1;
goto out;
#undef sbuf_size
}
static struct scst_cmd *scst_complete_request_sense(struct scst_cmd *cmd)
{
struct scst_cmd *orig_cmd = cmd->orig_cmd;
uint8_t *buf;
int len;
TRACE_ENTRY();
BUG_ON(orig_cmd);
len = scst_get_buf_first(cmd, &buf);
if ((cmd->status == 0) && SCST_SENSE_VALID(buf) &&
(!SCST_NO_SENSE(buf)))
{
TRACE_BUFF_FLAG(TRACE_SCSI, "REQUEST SENSE returned",
buf, len);
memcpy(orig_cmd->sense_buffer, buf,
(sizeof(orig_cmd->sense_buffer) > len) ?
len : sizeof(orig_cmd->sense_buffer));
} else {
PRINT_ERROR_PR("%s", "Unable to get the sense via "
"REQUEST SENSE, returning HARDWARE ERROR");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
}
scst_put_buf(cmd, buf);
scst_free_internal_cmd(cmd);
TRACE_EXIT_HRES((unsigned long)orig_cmd);
return orig_cmd;
}
static int scst_done_cmd_check(struct scst_cmd *cmd, int *pres)
{
int res = 0, rc;
@@ -1967,10 +1846,10 @@ static int scst_done_cmd_check(struct scst_cmd *cmd, int *pres)
TRACE_ENTRY();
if (cmd->cdb[0] == REQUEST_SENSE) {
if (unlikely(cmd->cdb[0] == REQUEST_SENSE)) {
if (cmd->internal)
cmd = scst_complete_request_sense(cmd);
} else if (scst_check_auto_sense(cmd)) {
} else if (unlikely(scst_check_auto_sense(cmd))) {
PRINT_INFO_PR("Command finished with CHECK CONDITION, but "
"without sense data (opcode 0x%x), issuing "
"REQUEST SENSE", cmd->cdb[0]);
@@ -2238,7 +2117,7 @@ static int scst_xmit_response(struct scst_cmd *cmd)
if (cmd->sg) {
int i;
struct scatterlist *sg = cmd->sg;
TRACE(TRACE_SEND_BOT,
TRACE(TRACE_SEND_BOT,
"Xmitting %d S/G(s) at %p sg[0].page at %p",
cmd->sg_cnt, sg, (void*)sg[0].page);
for(i = 0; i < cmd->sg_cnt; ++i) {
@@ -2306,6 +2185,19 @@ out_error:
goto out;
}
void scst_tgt_cmd_done(struct scst_cmd *cmd)
{
TRACE_ENTRY();
BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT);
cmd->state = SCST_CMD_STATE_FINISHED;
scst_proccess_redirect_cmd(cmd, scst_get_context(), 1);
TRACE_EXIT();
return;
}
static int scst_finish_cmd(struct scst_cmd *cmd)
{
int res;
@@ -2343,19 +2235,6 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
return res;
}
void scst_tgt_cmd_done(struct scst_cmd *cmd)
{
TRACE_ENTRY();
BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT);
cmd->state = SCST_CMD_STATE_FINISHED;
scst_proccess_redirect_cmd(cmd, scst_get_context(), 1);
TRACE_EXIT();
return;
}
/*
* Returns 0 on success, > 0 when we need to wait for unblock,
* < 0 if there is no device (lun) or device type handler.