aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-21 15:54:04 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 08:22:18 -0500
commit0af967f5d4f2dd1e00618d34ac988037d37a6c3b (patch)
tree08297980d1b6dab820d22c12c7fe1c54602f2486 /drivers/scsi
parent[SCSI] iser: fix handling of scsi cmnds during recovery. (diff)
downloadlinux-dev-0af967f5d4f2dd1e00618d34ac988037d37a6c3b.tar.xz
linux-dev-0af967f5d4f2dd1e00618d34ac988037d37a6c3b.zip
[SCSI] libiscsi, iscsi_tcp, iser: add session cmds array accessor
Currently to get a ctask from the session cmd array, you have to know to use the itt modifier. To make this easier on LLDs and so in the future we can easilly kill the session array and use the host shared map instead, this patch adds a nice wrapper to strip the itt into a session->cmds index and return a ctask. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c13
-rw-r--r--drivers/scsi/libiscsi.c60
2 files changed, 52 insertions, 21 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index dfaf9fa57340..f2a08f7ed902 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -740,7 +740,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
struct iscsi_session *session = conn->session;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_cmd_task *ctask;
- uint32_t itt;
/* verify PDU length */
tcp_conn->in.datalen = ntoh24(hdr->dlength);
@@ -758,7 +757,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
opcode = hdr->opcode & ISCSI_OPCODE_MASK;
/* verify itt (itt encoding: age+cid+itt) */
- rc = iscsi_verify_itt(conn, hdr, &itt);
+ rc = iscsi_verify_itt(conn, hdr->itt);
if (rc)
return rc;
@@ -767,7 +766,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
switch(opcode) {
case ISCSI_OP_SCSI_DATA_IN:
- ctask = session->cmds[itt];
+ ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+ if (!ctask)
+ return ISCSI_ERR_BAD_ITT;
+
spin_lock(&conn->session->lock);
rc = iscsi_data_rsp(conn, ctask);
spin_unlock(&conn->session->lock);
@@ -810,7 +812,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
break;
case ISCSI_OP_R2T:
- ctask = session->cmds[itt];
+ ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+ if (!ctask)
+ return ISCSI_ERR_BAD_ITT;
+
if (ahslen)
rc = ISCSI_ERR_AHSLEN;
else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 79bc49fd7f12..4bc63c4b3c10 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -640,6 +640,10 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
uint32_t itt;
conn->last_recv = jiffies;
+ rc = iscsi_verify_itt(conn, hdr->itt);
+ if (rc)
+ return rc;
+
if (hdr->itt != RESERVED_ITT)
itt = get_itt(hdr->itt);
else
@@ -776,27 +780,22 @@ int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
-/* verify itt (itt encoding: age+cid+itt) */
-int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
- uint32_t *ret_itt)
+int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
{
struct iscsi_session *session = conn->session;
struct iscsi_cmd_task *ctask;
- uint32_t itt;
- if (hdr->itt != RESERVED_ITT) {
- if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
- (session->age << ISCSI_AGE_SHIFT)) {
- iscsi_conn_printk(KERN_ERR, conn,
- "received itt %x expected session "
- "age (%x)\n", (__force u32)hdr->itt,
- session->age & ISCSI_AGE_MASK);
- return ISCSI_ERR_BAD_ITT;
- }
+ if (itt == RESERVED_ITT)
+ return 0;
- itt = get_itt(hdr->itt);
- } else
- itt = ~0U;
+ if (((__force u32)itt & ISCSI_AGE_MASK) !=
+ (session->age << ISCSI_AGE_SHIFT)) {
+ iscsi_conn_printk(KERN_ERR, conn,
+ "received itt %x expected session age (%x)\n",
+ (__force u32)itt,
+ session->age & ISCSI_AGE_MASK);
+ return ISCSI_ERR_BAD_ITT;
+ }
if (itt < session->cmds_max) {
ctask = session->cmds[itt];
@@ -817,11 +816,38 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
}
- *ret_itt = itt;
return 0;
}
EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+struct iscsi_cmd_task *
+iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+{
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd_task *ctask;
+ uint32_t i;
+
+ if (iscsi_verify_itt(conn, itt))
+ return NULL;
+
+ if (itt == RESERVED_ITT)
+ return NULL;
+
+ i = get_itt(itt);
+ if (i >= session->cmds_max)
+ return NULL;
+
+ ctask = session->cmds[i];
+ if (!ctask->sc)
+ return NULL;
+
+ if (ctask->sc->SCp.phase != session->age)
+ return NULL;
+
+ return ctask;
+}
+EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
+
void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
{
struct iscsi_session *session = conn->session;