aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-08-31 18:09:27 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-02 14:37:14 -0400
commit62f383003c22cd34920d0412465eddcb1223da0d (patch)
treeca5091110dbf19df3f8031a590cd11229e6081e1 /drivers/scsi/libiscsi.c
parent98a9416af08385f8497e9c1595113a81aefa5d49 (diff)
[SCSI] iscsi_tcp: fix padding, data digests, and IO at weird offsets
iscsi_tcp calculates padding by using the expected transfer length. This has the problem where if we have immediate data = no and initial R2T = yes, and the transfer length ended up needing padding then we send: 1. header 2. padding which should have gone after data 3. data Besides this bug, we also assume the target will always ask for nice transfer lengths and the first burst length will always be a nice value. As far as I can tell form the RFC this is not a requirement. It would be silly to do this, but if someone did it we will end doing bad things. Finally the last bug in that bit of code is in our handling of the recalculation of data digests when we do not send a whole iscsi_buf in one try. The bug here is that we call crypto_digest_final on a iscsi_sendpage error, then when we send the rest of the iscsi_buf, we doiscsi_data_digest_init and this causes the previous data digest to be lost. And to make matters worse, some of these bugs are replicated over and over and over again for immediate data, solicited data and unsolicited data. So the attached patch made over the iscsi git tree (see kernel.org/git for details) which I updated today to include the patches I said I merged, consolidates the sending of data, padding and digests and calculation of data digests and fixes the above bugs. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 9584cbc082fe..fb65311c81dd 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -325,6 +325,30 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
325 wake_up(&conn->ehwait); 325 wake_up(&conn->ehwait);
326} 326}
327 327
328static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
329 char *data, int datalen)
330{
331 struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
332 struct iscsi_hdr rejected_pdu;
333 uint32_t itt;
334
335 conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;
336
337 if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) {
338 if (ntoh24(reject->dlength) > datalen)
339 return ISCSI_ERR_PROTO;
340
341 if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
342 memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
343 itt = rejected_pdu.itt & ISCSI_ITT_MASK;
344 printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
345 "due to DataDigest error.\n", itt,
346 rejected_pdu.opcode);
347 }
348 }
349 return 0;
350}
351
328/** 352/**
329 * __iscsi_complete_pdu - complete pdu 353 * __iscsi_complete_pdu - complete pdu
330 * @conn: iscsi conn 354 * @conn: iscsi conn
@@ -436,6 +460,11 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
436 break; 460 break;
437 } 461 }
438 } else if (itt == ISCSI_RESERVED_TAG) { 462 } else if (itt == ISCSI_RESERVED_TAG) {
463 rc = iscsi_check_assign_cmdsn(session,
464 (struct iscsi_nopin*)hdr);
465 if (rc)
466 goto done;
467
439 switch(opcode) { 468 switch(opcode) {
440 case ISCSI_OP_NOOP_IN: 469 case ISCSI_OP_NOOP_IN:
441 if (datalen) { 470 if (datalen) {
@@ -443,11 +472,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
443 break; 472 break;
444 } 473 }
445 474
446 rc = iscsi_check_assign_cmdsn(session,
447 (struct iscsi_nopin*)hdr);
448 if (rc)
449 break;
450
451 if (hdr->ttt == ISCSI_RESERVED_TAG) 475 if (hdr->ttt == ISCSI_RESERVED_TAG)
452 break; 476 break;
453 477
@@ -455,7 +479,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
455 rc = ISCSI_ERR_CONN_FAILED; 479 rc = ISCSI_ERR_CONN_FAILED;
456 break; 480 break;
457 case ISCSI_OP_REJECT: 481 case ISCSI_OP_REJECT:
458 /* we need sth like iscsi_reject_rsp()*/ 482 rc = iscsi_handle_reject(conn, hdr, data, datalen);
483 break;
459 case ISCSI_OP_ASYNC_EVENT: 484 case ISCSI_OP_ASYNC_EVENT:
460 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; 485 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
461 /* we need sth like iscsi_async_event_rsp() */ 486 /* we need sth like iscsi_async_event_rsp() */