]> err.no Git - linux-2.6/blobdiff - drivers/scsi/iscsi_tcp.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6] / drivers / scsi / iscsi_tcp.c
index 584e51024fd61bb1f792ca59efe74a0ab9afadb2..4fea3e4edaa7148803fcfa8bbe49c83a538bcb51 100644 (file)
@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
              "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-
+MODULE_VERSION("0:4.409");
 /* #define DEBUG_TCP */
 /* #define DEBUG_SCSI */
 #define DEBUG_ASSERT
@@ -129,14 +129,11 @@ iscsi_buf_left(struct iscsi_buf *ibuf)
 }
 
 static inline void
-iscsi_buf_init_hdr(struct iscsi_conn *conn, struct iscsi_buf *ibuf,
-                  char *vbuf, u8 *crc)
+iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
+                u8* crc)
 {
-       iscsi_buf_init_virt(ibuf, vbuf, sizeof(struct iscsi_hdr));
-       if (conn->hdrdgst_en) {
-               crypto_digest_digest(conn->tx_tfm, &ibuf->sg, 1, crc);
-               ibuf->sg.length += sizeof(uint32_t);
-       }
+       crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc);
+       buf->sg.length += sizeof(uint32_t);
 }
 
 static void
@@ -427,8 +424,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 
        r2t->sent = 0;
 
-       iscsi_buf_init_hdr(conn, &r2t->headbuf, (char*)hdr,
-                          (u8 *)dtask->hdrext);
+       iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
+                          sizeof(struct iscsi_hdr));
 
        r2t->dtask = dtask;
 
@@ -560,7 +557,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
        conn->data_copied = 0;
 
        /* read AHS */
-       conn->in.ahslen = hdr->hlength*(4*sizeof(__u16));
+       conn->in.ahslen = hdr->hlength * 4;
        conn->in.offset += conn->in.ahslen;
        conn->in.copy -= conn->in.ahslen;
        if (conn->in.copy < 0) {
@@ -675,34 +672,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
                        else
                                rc = ISCSI_ERR_PROTO;
                        break;
-               case ISCSI_OP_NOOP_IN:
-               case ISCSI_OP_TEXT_RSP:
-               case ISCSI_OP_LOGOUT_RSP:
-               case ISCSI_OP_ASYNC_EVENT:
-               case ISCSI_OP_REJECT:
-                       rc = iscsi_check_assign_cmdsn(session,
-                                                (struct iscsi_nopin*)hdr);
-                       if (rc)
-                               break;
-
-                       /* update ExpStatSN */
-                       conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
-                       if (!conn->in.datalen) {
-                               struct iscsi_mgmt_task *mtask;
-
-                               rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
-                                                   NULL, 0);
-                               mtask = (struct iscsi_mgmt_task *)
-                                       session->mgmt_cmds[conn->in.itt -
-                                               ISCSI_MGMT_ITT_OFFSET];
-                               if (conn->login_mtask != mtask) {
-                                       spin_lock(&session->lock);
-                                       __kfifo_put(session->mgmtpool.queue,
-                                           (void*)&mtask, sizeof(void*));
-                                       spin_unlock(&session->lock);
-                               }
-                       }
-                       break;
                default:
                        rc = ISCSI_ERR_BAD_OPCODE;
                        break;
@@ -721,6 +690,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
                switch(conn->in.opcode) {
                case ISCSI_OP_LOGIN_RSP:
                case ISCSI_OP_TEXT_RSP:
+               case ISCSI_OP_LOGOUT_RSP: 
                        rc = iscsi_check_assign_cmdsn(session,
                                                 (struct iscsi_nopin*)hdr);
                        if (rc)
@@ -754,27 +724,66 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
                                                (void*)&mtask, sizeof(void*));
                                conn->tmabort_state =
                                        ((struct iscsi_tm_rsp *)hdr)->
-                                       response == SCSI_TCP_TM_RESP_COMPLETE ?
+                                       response == ISCSI_TMF_RSP_COMPLETE ?
                                                TMABORT_SUCCESS:TMABORT_FAILED;
                                /* unblock eh_abort() */
                                wake_up(&conn->ehwait);
                        }
                        spin_unlock(&session->lock);
                        break;
+               case ISCSI_OP_NOOP_IN: 
+                       if (hdr->ttt != ISCSI_RESERVED_TAG) {
+                               rc = ISCSI_ERR_PROTO;
+                               break;
+                       }
+                       rc = iscsi_check_assign_cmdsn(session, 
+                                               (struct iscsi_nopin*)hdr);
+                       if (rc)
+                               break;
+                       conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+
+                       if (!conn->in.datalen) {
+                               struct iscsi_mgmt_task *mtask;
+
+                               rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+                                                   NULL, 0);
+                               mtask = (struct iscsi_mgmt_task *)
+                                       session->mgmt_cmds[conn->in.itt -
+                                                       ISCSI_MGMT_ITT_OFFSET];
+                               if (conn->login_mtask != mtask) {
+                                       spin_lock(&session->lock);
+                                       __kfifo_put(session->mgmtpool.queue,
+                                                 (void*)&mtask, sizeof(void*));
+                                       spin_unlock(&session->lock);
+                               }
+                       }
+                       break;
                default:
                        rc = ISCSI_ERR_BAD_OPCODE;
                        break;
                }
        } else if (conn->in.itt == ISCSI_RESERVED_TAG) {
-               if (conn->in.opcode == ISCSI_OP_NOOP_IN && !conn->in.datalen) {
-                       rc = iscsi_check_assign_cmdsn(session,
+               switch(conn->in.opcode) {
+               case ISCSI_OP_NOOP_IN:
+                       if (!conn->in.datalen) {
+                               rc = iscsi_check_assign_cmdsn(session,
                                                 (struct iscsi_nopin*)hdr);
-                       if (!rc)
-                               rc = iscsi_recv_pdu(iscsi_handle(conn),
-                                                   hdr, NULL, 0);
-               }
-               else
+                               if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
+                                       rc = iscsi_recv_pdu(iscsi_handle(conn),
+                                                           hdr, NULL, 0);
+                       } else 
+                               rc = ISCSI_ERR_PROTO;
+                       break;
+               case ISCSI_OP_REJECT:
+                       /* we need sth like iscsi_reject_rsp()*/
+               case ISCSI_OP_ASYNC_EVENT:
+                       /* we need sth like iscsi_async_event_rsp() */
                        rc = ISCSI_ERR_BAD_OPCODE;
+                       break;
+               default:
+                       rc = ISCSI_ERR_BAD_OPCODE;
+                       break;
+               }
        } else
                rc = ISCSI_ERR_BAD_ITT;
 
@@ -1064,7 +1073,6 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
 {
        int rc;
        struct iscsi_conn *conn = rd_desc->arg.data;
-       int start = skb_headlen(skb);
        int processed;
        char pad[ISCSI_PAD_LEN];
        struct scatterlist sg;
@@ -1073,7 +1081,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
         * Save current SKB and its offset in the corresponding
         * connection context.
         */
-       conn->in.copy = start - offset;
+       conn->in.copy = skb->len - offset;
        conn->in.offset = offset;
        conn->in.skb = skb;
        conn->in.len = conn->in.copy;
@@ -1494,8 +1502,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
        }
        conn->dataout_pdus_cnt++;
 
-       iscsi_buf_init_hdr(conn, &r2t->headbuf, (char*)hdr,
-                          (u8 *)dtask->hdrext);
+       iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
+                          sizeof(struct iscsi_hdr));
 
        r2t->dtask = dtask;
 
@@ -1541,8 +1549,8 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
                hdr->flags = ISCSI_FLAG_CMD_FINAL;
        }
 
-       iscsi_buf_init_hdr(conn, &ctask->headbuf, (char*)hdr,
-                          (u8 *)dtask->hdrext);
+       iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr,
+                          sizeof(struct iscsi_hdr));
 
        list_add(&dtask->item, &ctask->dataqueue);
 
@@ -1662,8 +1670,8 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
                zero_data(ctask->hdr.dlength);
        }
 
-       iscsi_buf_init_hdr(conn, &ctask->headbuf, (char*)&ctask->hdr,
-                           (u8 *)ctask->hdrext);
+       iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, 
+                           sizeof(struct iscsi_hdr));
        conn->scsicmd_pdus_cnt++;
 }
 
@@ -1692,6 +1700,11 @@ iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
                mtask->xmstate &= ~XMSTATE_IMM_HDR;
                if (mtask->data_count)
                        mtask->xmstate |= XMSTATE_IMM_DATA;
+               if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+                   conn->stop_stage != STOP_CONN_RECOVER &&
+                   conn->hdrdgst_en)
+                       iscsi_hdr_digest(conn, &mtask->headbuf,
+                                       (u8*)mtask->hdrext);
                if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) {
                        mtask->xmstate |= XMSTATE_IMM_HDR;
                        if (mtask->data_count)
@@ -1723,6 +1736,8 @@ static inline int
 handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
        ctask->xmstate &= ~XMSTATE_R_HDR;
+       if (conn->hdrdgst_en) 
+               iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
        if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
                BUG_ON(ctask->xmstate != XMSTATE_IDLE);
                return 0; /* wait for Data-In */
@@ -1735,6 +1750,8 @@ static inline int
 handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
        ctask->xmstate &= ~XMSTATE_W_HDR;
+       if (conn->hdrdgst_en) 
+               iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
        if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
                ctask->xmstate |= XMSTATE_W_HDR;
                return -EAGAIN;
@@ -1813,7 +1830,9 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
                iscsi_unsolicit_data_init(conn, ctask);
                BUG_ON(!ctask->dtask);
                dtask = ctask->dtask;
-
+               if (conn->hdrdgst_en)
+                       iscsi_hdr_digest(conn, &ctask->headbuf,
+                                       (u8*)dtask->hdrext);
                ctask->xmstate &= ~XMSTATE_UNS_INIT;
        }
        if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) {
@@ -2118,7 +2137,9 @@ unsolicit_head_again:
                                    sizeof(void*));
 solicit_head_again:
                r2t = ctask->r2t;
-
+               if (conn->hdrdgst_en)
+                       iscsi_hdr_digest(conn, &r2t->headbuf, 
+                                       (u8*)r2t->dtask->hdrext);
                if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
                        ctask->xmstate &= ~XMSTATE_SOL_DATA;
                        ctask->xmstate |= XMSTATE_SOL_HDR;
@@ -2889,14 +2910,8 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 
        memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr));
 
-       if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE ||
-           conn->stop_stage == STOP_CONN_RECOVER)
-               iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
+       iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
                                    sizeof(struct iscsi_hdr));
-       else
-               /* this will update header digest */
-               iscsi_buf_init_hdr(conn, &mtask->headbuf, (char*)&mtask->hdr,
-                                   (u8 *)mtask->hdrext);
 
        spin_unlock_bh(&session->lock);