Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 161108
b: refs/heads/master
c: 8afa143
h: refs/heads/master
v: v3
  • Loading branch information
Mike Christie authored and James Bottomley committed Sep 5, 2009
1 parent f0a4cf1 commit 022c2f4
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d3305f3407fa3e9452079ec6cc8379067456e4aa
refs/heads/master: 8afa1439fcff58da8f28c1d083046f229f6ab3de
106 changes: 87 additions & 19 deletions trunk/drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,27 +857,102 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
}
}

static int iscsi_nop_out_rsp(struct iscsi_task *task,
struct iscsi_nopin *nop, char *data, int datalen)
{
struct iscsi_conn *conn = task->conn;
int rc = 0;

if (conn->ping_task != task) {
/*
* If this is not in response to one of our
* nops then it must be from userspace.
*/
if (iscsi_recv_pdu(conn->cls_conn, (struct iscsi_hdr *)nop,
data, datalen))
rc = ISCSI_ERR_CONN_FAILED;
} else
mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
return rc;
}

static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
char *data, int datalen)
{
struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
struct iscsi_hdr rejected_pdu;
int opcode, rc = 0;

conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;

if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) {
if (ntoh24(reject->dlength) > datalen)
return ISCSI_ERR_PROTO;
if (ntoh24(reject->dlength) > datalen ||
ntoh24(reject->dlength) < sizeof(struct iscsi_hdr)) {
iscsi_conn_printk(KERN_ERR, conn, "Cannot handle rejected "
"pdu. Invalid data length (pdu dlength "
"%u, datalen %d\n", ntoh24(reject->dlength),
datalen);
return ISCSI_ERR_PROTO;
}
memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
opcode = rejected_pdu.opcode & ISCSI_OPCODE_MASK;

if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
iscsi_conn_printk(KERN_ERR, conn,
"pdu (op 0x%x) rejected "
"due to DataDigest error.\n",
rejected_pdu.opcode);
switch (reject->reason) {
case ISCSI_REASON_DATA_DIGEST_ERROR:
iscsi_conn_printk(KERN_ERR, conn,
"pdu (op 0x%x itt 0x%x) rejected "
"due to DataDigest error.\n",
rejected_pdu.itt, opcode);
break;
case ISCSI_REASON_IMM_CMD_REJECT:
iscsi_conn_printk(KERN_ERR, conn,
"pdu (op 0x%x itt 0x%x) rejected. Too many "
"immediate commands.\n",
rejected_pdu.itt, opcode);
/*
* We only send one TMF at a time so if the target could not
* handle it, then it should get fixed (RFC mandates that
* a target can handle one immediate TMF per conn).
*
* For nops-outs, we could have sent more than one if
* the target is sending us lots of nop-ins
*/
if (opcode != ISCSI_OP_NOOP_OUT)
return 0;

if (rejected_pdu.itt == cpu_to_be32(ISCSI_RESERVED_TAG))
/*
* nop-out in response to target's nop-out rejected.
* Just resend.
*/
iscsi_send_nopout(conn,
(struct iscsi_nopin*)&rejected_pdu);
else {
struct iscsi_task *task;
/*
* Our nop as ping got dropped. We know the target
* and transport are ok so just clean up
*/
task = iscsi_itt_to_task(conn, rejected_pdu.itt);
if (!task) {
iscsi_conn_printk(KERN_ERR, conn,
"Invalid pdu reject. Could "
"not lookup rejected task.\n");
rc = ISCSI_ERR_BAD_ITT;
} else
rc = iscsi_nop_out_rsp(task,
(struct iscsi_nopin*)&rejected_pdu,
NULL, 0);
}
break;
default:
iscsi_conn_printk(KERN_ERR, conn,
"pdu (op 0x%x itt 0x%x) rejected. Reason "
"code 0x%x\n", rejected_pdu.itt,
rejected_pdu.opcode, reject->reason);
break;
}
return 0;
return rc;
}

/**
Expand Down Expand Up @@ -1038,15 +1113,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;

if (conn->ping_task != task)
/*
* If this is not in response to one of our
* nops then it must be from userspace.
*/
goto recv_pdu;

mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)hdr,
data, datalen);
break;
default:
rc = ISCSI_ERR_BAD_OPCODE;
Expand Down

0 comments on commit 022c2f4

Please sign in to comment.