mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 21:26:31 +00:00
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:
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
@@ -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, "
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user