[Stgt-devel] [PATCH] return sense data
Pete Wyckoff
pw
Sun Feb 25 01:24:35 CET 2007
It is legal to return both data and sense data. Modify iscsi to do this.
Let target and scsi generate sense information to return through the task.
Signed-off-by: Pete Wyckoff <pw at osc.edu>
---
usr/driver.h | 2 +-
usr/iscsi/iscsid.c | 24 +++++++++++++++++++++---
usr/iscsi/iscsid.h | 3 +++
usr/target.c | 20 +++++++++++---------
usr/target.h | 2 ++
usr/tgtif.c | 3 ++-
6 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/usr/driver.h b/usr/driver.h
index 764c53a..0d9fc02 100644
--- a/usr/driver.h
+++ b/usr/driver.h
@@ -18,7 +18,7 @@ struct tgt_driver {
int (*scsi_inquiry)(struct tgt_device *, int, uint8_t *, uint8_t *,
uint8_t *, int *);
int (*cmd_end_notify)(uint64_t nid, int len, int result, int rw, uint64_t addr,
- uint64_t tag);
+ uint64_t tag, uint8_t *sense, uint8_t senselen);
int (*mgmt_end_notify)(uint64_t nid, uint64_t mid, int result);
struct backedio_template *default_bdt;
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index eefa8b1..8862523 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -753,6 +753,22 @@ static int iscsi_cmd_rsp_build(struct iscsi_task *task)
rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ dprintf("len %d senselen %d\n", task->len, task->senselen);
+
+ /* Tack on sense to response cdb. */
+ if (task->senselen) {
+ uint16_t len = task->senselen;
+ if (len > sizeof(conn->sense_buffer)-2)
+ len = sizeof(conn->sense_buffer) - 2;
+ memcpy(&conn->sense_buffer[2], task->sense, len);
+ conn->sense_buffer[0] = (len & 0xff00) >> 8;
+ conn->sense_buffer[1] = (len & 0x00ff);
+ dprintf("len+2 %d\n", len+2);
+ hton24(rsp->dlength, len+2);
+ conn->rsp.data = conn->sense_buffer;
+ conn->rsp.datasize = len+2;
+ }
+
return 0;
}
@@ -877,13 +893,13 @@ static void iscsi_free_cmd_task(struct iscsi_task *task)
}
int iscsi_scsi_cmd_done(uint64_t nid, int len, int result, int rw, uint64_t addr,
- uint64_t tag)
+ uint64_t tag, uint8_t *sense, uint8_t senselen)
{
struct iscsi_session *session;
struct iscsi_task *task;
- dprintf("%" PRIu64 " %d %d %d %" PRIx64 " %" PRIx64 "\n", nid,
- len, result, rw, addr, tag);
+ dprintf("%" PRIu64 " %d %d %d %" PRIx64 " %" PRIx64 " senselen %d\n",
+ nid, len, result, rw, addr, tag, senselen);
session = session_lookup(nid);
if (!session)
return -EINVAL;
@@ -913,6 +929,8 @@ found:
task->result = result;
task->len = len;
task->rw = rw;
+ task->sense = sense;
+ task->senselen = senselen;
list_add_tail(&task->c_list, &task->conn->tx_clist);
tgt_event_modify(task->conn->fd, EPOLLIN | EPOLLOUT);
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index c4b23d9..bc6ec39 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -103,6 +103,8 @@ struct iscsi_task {
int result;
int len;
int rw;
+ uint8_t *sense;
+ uint8_t senselen;
int offset;
int data_sn;
@@ -146,6 +148,7 @@ struct iscsi_connection {
struct iscsi_pdu req;
void *req_buffer;
struct iscsi_pdu rsp;
+ uint8_t sense_buffer[252]; /* architectural limit */
void *rsp_buffer;
unsigned char *rx_buffer;
unsigned char *tx_buffer;
diff --git a/usr/target.c b/usr/target.c
index 6cb69ce..51b5106 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -463,13 +463,15 @@ int target_cmd_queue(uint64_t nid, uint8_t *scb, int scblen, uint8_t rw,
cmd_post_perform(q, cmd);
- dprintf("%" PRIx64 " %x %" PRIx64 " %" PRIu64 " %u %d %d\n",
- tag, scb[0], cmd->uaddr, cmd->offset, cmd->len, result, cmd->async);
+ dprintf("%" PRIx64 " %x %lx %" PRIu64 " %d %d %d senselen %d\n",
+ tag, scb[0], cmd->uaddr, cmd->offset, cmd->len, result,
+ cmd->async, cmd->senselen);
set_cmd_processed(cmd);
if (!cmd->async)
tgt_drivers[target->lid]->cmd_end_notify(nid, cmd->len, result,
- cmd->rw, cmd->uaddr, tag);
+ cmd->rw, cmd->uaddr, tag,
+ cmd->sense, cmd->senselen);
} else {
set_cmd_queued(cmd);
dprintf("blocked %" PRIx64 " %x %" PRIu64 " %d\n",
@@ -490,7 +492,7 @@ void target_cmd_io_done(void *key, int result)
tgt_drivers[cmd->c_target->lid]->cmd_end_notify(cmd->cmd_nexus_id,
cmd->len, result,
cmd->rw, cmd->uaddr,
- cmd->tag);
+ cmd->tag, NULL, 0);
return;
}
@@ -498,7 +500,6 @@ static void post_cmd_done(struct tgt_cmd_queue *q)
{
struct scsi_cmd *cmd, *tmp;
int enabled, result;
- int (* notify_fn)(uint64_t, int, int, int, uint64_t, uint64_t);
list_for_each_entry_safe(cmd, tmp, &q->queue, qlist) {
enabled = cmd_enabled(q, cmd);
@@ -515,9 +516,10 @@ static void post_cmd_done(struct tgt_cmd_queue *q)
cmd_post_perform(q, cmd);
set_cmd_processed(cmd);
if (!cmd->async) {
- notify_fn = tgt_drivers[cmd->c_target->lid]->cmd_end_notify;
- notify_fn(cmd->cmd_nexus_id, cmd->len, result, cmd->rw,
- cmd->uaddr, cmd->tag);
+ tgt_drivers[cmd->c_target->lid]->cmd_end_notify(
+ cmd->cmd_nexus_id, cmd->len, result,
+ cmd->rw, cmd->uaddr, cmd->tag,
+ cmd->sense, cmd->senselen);
}
} else
break;
@@ -613,7 +615,7 @@ static int abort_cmd(struct target* target, struct mgmt_req *mreq,
} else {
__cmd_done(target, cmd);
tgt_drivers[cmd->c_target->lid]->cmd_end_notify(cmd->cmd_nexus_id, 0,
- TASK_ABORTED, 0, 0, cmd->tag);
+ TASK_ABORTED, 0, 0, cmd->tag, NULL, 0);
}
return err;
}
diff --git a/usr/target.h b/usr/target.h
index e90b094..37da8c5 100644
--- a/usr/target.h
+++ b/usr/target.h
@@ -98,6 +98,8 @@ struct scsi_cmd {
uint8_t rw;
int async;
struct mgmt_req *mreq;
+ uint8_t *sense; /* output values from target */
+ uint8_t senselen;
};
enum {
diff --git a/usr/tgtif.c b/usr/tgtif.c
index 4c22863..b87a5ac 100644
--- a/usr/tgtif.c
+++ b/usr/tgtif.c
@@ -101,7 +101,8 @@ int kspace_send_tsk_mgmt_res(uint64_t nid, uint64_t mid, int result)
}
int kspace_send_cmd_res(uint64_t nid, int len, int result,
- int rw, uint64_t addr, uint64_t tag)
+ int rw, uint64_t addr, uint64_t tag,
+ uint8_t *sense, uint8_t senselen)
{
struct tgt_event ev;
More information about the stgt
mailing list