diff options
-rw-r--r-- | drivers/scsi/libiscsi.c | 47 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 5 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 3 |
3 files changed, 40 insertions, 15 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c1bb74052aed..6c4034b1561c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -222,12 +222,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
222 | struct scsi_cmnd *sc = task->sc; | 222 | struct scsi_cmnd *sc = task->sc; |
223 | struct iscsi_cmd *hdr; | 223 | struct iscsi_cmd *hdr; |
224 | unsigned hdrlength, cmd_len; | 224 | unsigned hdrlength, cmd_len; |
225 | itt_t itt; | ||
225 | int rc; | 226 | int rc; |
226 | 227 | ||
227 | rc = conn->session->tt->alloc_pdu(task); | 228 | rc = conn->session->tt->alloc_pdu(task); |
228 | if (rc) | 229 | if (rc) |
229 | return rc; | 230 | return rc; |
230 | hdr = (struct iscsi_cmd *) task->hdr; | 231 | hdr = (struct iscsi_cmd *) task->hdr; |
232 | itt = hdr->itt; | ||
231 | memset(hdr, 0, sizeof(*hdr)); | 233 | memset(hdr, 0, sizeof(*hdr)); |
232 | 234 | ||
233 | task->hdr_len = 0; | 235 | task->hdr_len = 0; |
@@ -238,7 +240,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
238 | hdr->flags = ISCSI_ATTR_SIMPLE; | 240 | hdr->flags = ISCSI_ATTR_SIMPLE; |
239 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | 241 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); |
240 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); | 242 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); |
241 | hdr->itt = task->hdr_itt = build_itt(task->itt, session->age); | 243 | if (session->tt->parse_pdu_itt) |
244 | hdr->itt = task->hdr_itt = itt; | ||
245 | else | ||
246 | hdr->itt = task->hdr_itt = build_itt(task->itt, | ||
247 | task->conn->session->age); | ||
242 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | 248 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); |
243 | session->cmdsn++; | 249 | session->cmdsn++; |
244 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 250 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
@@ -457,7 +463,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
457 | */ | 463 | */ |
458 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 464 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
459 | if (hdr->itt != RESERVED_ITT) { | 465 | if (hdr->itt != RESERVED_ITT) { |
460 | hdr->itt = build_itt(task->itt, session->age); | ||
461 | /* | 466 | /* |
462 | * TODO: We always use immediate, so we never hit this. | 467 | * TODO: We always use immediate, so we never hit this. |
463 | * If we start to send tmfs or nops as non-immediate then | 468 | * If we start to send tmfs or nops as non-immediate then |
@@ -490,6 +495,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
490 | { | 495 | { |
491 | struct iscsi_session *session = conn->session; | 496 | struct iscsi_session *session = conn->session; |
492 | struct iscsi_task *task; | 497 | struct iscsi_task *task; |
498 | itt_t itt; | ||
493 | 499 | ||
494 | if (session->state == ISCSI_STATE_TERMINATE) | 500 | if (session->state == ISCSI_STATE_TERMINATE) |
495 | return NULL; | 501 | return NULL; |
@@ -531,9 +537,18 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
531 | "pdu for mgmt task.\n"); | 537 | "pdu for mgmt task.\n"); |
532 | goto requeue_task; | 538 | goto requeue_task; |
533 | } | 539 | } |
540 | itt = task->hdr->itt; | ||
534 | task->hdr_len = sizeof(struct iscsi_hdr); | 541 | task->hdr_len = sizeof(struct iscsi_hdr); |
535 | |||
536 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | 542 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
543 | |||
544 | if (hdr->itt != RESERVED_ITT) { | ||
545 | if (session->tt->parse_pdu_itt) | ||
546 | task->hdr->itt = itt; | ||
547 | else | ||
548 | task->hdr->itt = build_itt(task->itt, | ||
549 | task->conn->session->age); | ||
550 | } | ||
551 | |||
537 | INIT_LIST_HEAD(&task->running); | 552 | INIT_LIST_HEAD(&task->running); |
538 | list_add_tail(&task->running, &conn->mgmtqueue); | 553 | list_add_tail(&task->running, &conn->mgmtqueue); |
539 | 554 | ||
@@ -745,7 +760,6 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
745 | { | 760 | { |
746 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; | 761 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; |
747 | struct iscsi_hdr rejected_pdu; | 762 | struct iscsi_hdr rejected_pdu; |
748 | uint32_t itt; | ||
749 | 763 | ||
750 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; | 764 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; |
751 | 765 | ||
@@ -755,10 +769,9 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
755 | 769 | ||
756 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { | 770 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { |
757 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | 771 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); |
758 | itt = get_itt(rejected_pdu.itt); | ||
759 | iscsi_conn_printk(KERN_ERR, conn, | 772 | iscsi_conn_printk(KERN_ERR, conn, |
760 | "itt 0x%x had pdu (op 0x%x) rejected " | 773 | "pdu (op 0x%x) rejected " |
761 | "due to DataDigest error.\n", itt, | 774 | "due to DataDigest error.\n", |
762 | rejected_pdu.opcode); | 775 | rejected_pdu.opcode); |
763 | } | 776 | } |
764 | } | 777 | } |
@@ -778,12 +791,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
778 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | 791 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
779 | { | 792 | { |
780 | struct iscsi_session *session = conn->session; | 793 | struct iscsi_session *session = conn->session; |
781 | uint32_t i; | 794 | int i; |
782 | 795 | ||
783 | if (itt == RESERVED_ITT) | 796 | if (itt == RESERVED_ITT) |
784 | return NULL; | 797 | return NULL; |
785 | 798 | ||
786 | i = get_itt(itt); | 799 | if (session->tt->parse_pdu_itt) |
800 | session->tt->parse_pdu_itt(conn, itt, &i, NULL); | ||
801 | else | ||
802 | i = get_itt(itt); | ||
787 | if (i >= session->cmds_max) | 803 | if (i >= session->cmds_max) |
788 | return NULL; | 804 | return NULL; |
789 | 805 | ||
@@ -958,20 +974,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu); | |||
958 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) | 974 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) |
959 | { | 975 | { |
960 | struct iscsi_session *session = conn->session; | 976 | struct iscsi_session *session = conn->session; |
961 | uint32_t i; | 977 | int age = 0, i = 0; |
962 | 978 | ||
963 | if (itt == RESERVED_ITT) | 979 | if (itt == RESERVED_ITT) |
964 | return 0; | 980 | return 0; |
965 | 981 | ||
966 | if (((__force u32)itt & ISCSI_AGE_MASK) != | 982 | if (session->tt->parse_pdu_itt) |
967 | (session->age << ISCSI_AGE_SHIFT)) { | 983 | session->tt->parse_pdu_itt(conn, itt, &i, &age); |
984 | else { | ||
985 | i = get_itt(itt); | ||
986 | age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK; | ||
987 | } | ||
988 | |||
989 | if (age != session->age) { | ||
968 | iscsi_conn_printk(KERN_ERR, conn, | 990 | iscsi_conn_printk(KERN_ERR, conn, |
969 | "received itt %x expected session age (%x)\n", | 991 | "received itt %x expected session age (%x)\n", |
970 | (__force u32)itt, session->age); | 992 | (__force u32)itt, session->age); |
971 | return ISCSI_ERR_BAD_ITT; | 993 | return ISCSI_ERR_BAD_ITT; |
972 | } | 994 | } |
973 | 995 | ||
974 | i = get_itt(itt); | ||
975 | if (i >= session->cmds_max) { | 996 | if (i >= session->cmds_max) { |
976 | iscsi_conn_printk(KERN_ERR, conn, | 997 | iscsi_conn_printk(KERN_ERR, conn, |
977 | "received invalid itt index %u (max cmds " | 998 | "received invalid itt index %u (max cmds " |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 51500573c0b8..7360e1916e75 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
31 | #include <scsi/iscsi_proto.h> | 31 | #include <scsi/iscsi_proto.h> |
32 | #include <scsi/iscsi_if.h> | 32 | #include <scsi/iscsi_if.h> |
33 | #include <scsi/scsi_transport_iscsi.h> | ||
33 | 34 | ||
34 | struct scsi_transport_template; | 35 | struct scsi_transport_template; |
35 | struct scsi_host_template; | 36 | struct scsi_host_template; |
@@ -70,12 +71,12 @@ enum { | |||
70 | /* Connection suspend "bit" */ | 71 | /* Connection suspend "bit" */ |
71 | #define ISCSI_SUSPEND_BIT 1 | 72 | #define ISCSI_SUSPEND_BIT 1 |
72 | 73 | ||
73 | #define ISCSI_ITT_MASK (0x1fff) | 74 | #define ISCSI_ITT_MASK 0x1fff |
74 | #define ISCSI_TOTAL_CMDS_MAX 4096 | 75 | #define ISCSI_TOTAL_CMDS_MAX 4096 |
75 | /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ | 76 | /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ |
76 | #define ISCSI_TOTAL_CMDS_MIN 16 | 77 | #define ISCSI_TOTAL_CMDS_MIN 16 |
77 | #define ISCSI_AGE_SHIFT 28 | 78 | #define ISCSI_AGE_SHIFT 28 |
78 | #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) | 79 | #define ISCSI_AGE_MASK 0xf |
79 | 80 | ||
80 | #define ISCSI_ADDRESS_BUF_LEN 64 | 81 | #define ISCSI_ADDRESS_BUF_LEN 64 |
81 | 82 | ||
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index c928234c018f..e13cb20f1eae 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -122,6 +122,9 @@ struct iscsi_transport { | |||
122 | int (*xmit_pdu) (struct iscsi_task *task); | 122 | int (*xmit_pdu) (struct iscsi_task *task); |
123 | int (*init_pdu) (struct iscsi_task *task, unsigned int offset, | 123 | int (*init_pdu) (struct iscsi_task *task, unsigned int offset, |
124 | unsigned int count); | 124 | unsigned int count); |
125 | void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt, | ||
126 | int *index, int *age); | ||
127 | |||
125 | void (*session_recovery_timedout) (struct iscsi_cls_session *session); | 128 | void (*session_recovery_timedout) (struct iscsi_cls_session *session); |
126 | struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, | 129 | struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, |
127 | int non_blocking); | 130 | int non_blocking); |