From: t_jeang Date: Tue, 6 Jan 2009 12:05:59 +0000 (+0000) Subject: Apply kernel parts of open-iscsi-2.0.865.13.tar.gz X-Git-Tag: git-44a1d2e5c5c935fff3a093a1bcede32912c76421 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=2162a61e6440589fe9d89e6541e33c1aa05d0fec;p=xenclient%2Fkernel.git Apply kernel parts of open-iscsi-2.0.865.13.tar.gz --- diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 86a7aeaa..7e6b9492 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include "scsi_transport_iscsi.h" #include "iscsi_tcp.h" @@ -109,8 +109,8 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc); - buf->sg.length = tcp_conn->hdr_size; + crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); + buf->sg.length += sizeof(u32); } static inline int @@ -200,7 +200,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (unlikely(!sc)) return; - tcp_ctask->xmstate = XMSTATE_VALUE_IDLE; + tcp_ctask->xmstate = XMSTATE_IDLE; tcp_ctask->r2t = NULL; } @@ -237,8 +237,12 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->exp_datasn++; tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); - if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) + if (tcp_ctask->data_offset + tcp_conn->in.datalen > sc->request_bufflen) { + debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n", + __FUNCTION__, tcp_ctask->data_offset, + tcp_conn->in.datalen, sc->request_bufflen); return ISCSI_ERR_DATA_OFFSET; + } if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) { conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; @@ -375,8 +379,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) spin_lock(&session->lock); iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); - if (!ctask->sc || ctask->mtask || - session->state != ISCSI_STATE_LOGGED_IN) { + if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " "recovery...\n", ctask->itt); spin_unlock(&session->lock); @@ -400,11 +403,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) r2t->data_length, session->max_burst); r2t->data_offset = be32_to_cpu(rhdr->data_offset); - if (r2t->data_offset + r2t->data_length > ctask->total_length) { + if (r2t->data_offset + r2t->data_length > ctask->sc->request_bufflen) { spin_unlock(&session->lock); printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at " "offset %u and total length %d\n", r2t->data_length, - r2t->data_offset, ctask->total_length); + r2t->data_offset, ctask->sc->request_bufflen); return ISCSI_ERR_DATALEN; } @@ -415,11 +418,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->exp_datasn = r2tsn + 1; __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); - list_move_tail(&ctask->running, &conn->xmitqueue); - - scsi_queue_work(session->host, &conn->xmitwork); + tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; conn->r2t_pdus_cnt++; + + iscsi_requeue_ctask(ctask); spin_unlock(&session->lock); return 0; @@ -467,7 +469,8 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) sg_init_one(&sg, (u8 *)hdr, sizeof(struct iscsi_hdr) + ahslen); - crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst); + crypto_hash_digest(&tcp_conn->rx_hash, &sg, sg.length, + (u8 *)&cdgst); rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + ahslen); if (cdgst != rdgst) { @@ -598,7 +601,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int buf_left = buf_size - (tcp_conn->data_copied + offset); - int size = min(tcp_conn->in.copy, buf_left); + unsigned size = min(tcp_conn->in.copy, buf_left); int rc; size = min(size, ctask->data_count); @@ -607,7 +610,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, size, tcp_conn->in.offset, tcp_conn->in.copied); BUG_ON(size <= 0); - BUG_ON(tcp_ctask->sent + size > ctask->total_length); + BUG_ON(tcp_ctask->sent + size > ctask->sc->request_bufflen); rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, (char*)buf + (offset + tcp_conn->data_copied), size); @@ -674,7 +677,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn, int buf_size) } static inline void -partial_sg_digest_update(struct crypto_tfm *tfm, struct scatterlist *sg, +partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg, int offset, int length) { struct scatterlist temp; @@ -682,7 +685,7 @@ partial_sg_digest_update(struct crypto_tfm *tfm, struct scatterlist *sg, memcpy(&temp, sg, sizeof(struct scatterlist)); temp.offset = offset; temp.length = length; - crypto_digest_update(tfm, &temp, 1); + crypto_hash_update(desc, &temp, length); } static void @@ -691,7 +694,7 @@ iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) struct scatterlist tmp; sg_init_one(&tmp, buf, len); - crypto_digest_update(tcp_conn->rx_tfm, &tmp, 1); + crypto_hash_update(&tcp_conn->rx_hash, &tmp, len); } static int iscsi_scsi_data_in(struct iscsi_conn *conn) @@ -745,12 +748,12 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) if (!rc) { if (conn->datadgst_en) { if (!offset) - crypto_digest_update( - tcp_conn->rx_tfm, - &sg[i], 1); + crypto_hash_update( + &tcp_conn->rx_hash, + &sg[i], sg[i].length); else partial_sg_digest_update( - tcp_conn->rx_tfm, + &tcp_conn->rx_hash, &sg[i], sg[i].offset + offset, sg[i].length - offset); @@ -764,9 +767,10 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) /* * data-in is complete, but buffer not... */ - partial_sg_digest_update(tcp_conn->rx_tfm, - &sg[i], - sg[i].offset, sg[i].length-rc); + partial_sg_digest_update(&tcp_conn->rx_hash, + &sg[i], + sg[i].offset, + sg[i].length-rc); rc = 0; break; } @@ -884,7 +888,7 @@ more: rc = iscsi_tcp_hdr_recv(conn); if (!rc && tcp_conn->in.datalen) { if (conn->datadgst_en) - crypto_digest_init(tcp_conn->rx_tfm); + crypto_hash_init(&tcp_conn->rx_hash); tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { iscsi_conn_failure(conn, rc); @@ -905,10 +909,10 @@ more: tcp_conn->in.padding); memset(pad, 0, tcp_conn->in.padding); sg_init_one(&sg, pad, tcp_conn->in.padding); - crypto_digest_update(tcp_conn->rx_tfm, - &sg, 1); + crypto_hash_update(&tcp_conn->rx_hash, + &sg, sg.length); } - crypto_digest_final(tcp_conn->rx_tfm, + crypto_hash_final(&tcp_conn->rx_hash, (u8 *) &tcp_conn->in.datadgst); debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); } @@ -1213,7 +1217,7 @@ static inline void iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, struct iscsi_tcp_cmd_task *tcp_ctask) { - crypto_digest_init(tcp_conn->tx_tfm); + crypto_hash_init(&tcp_conn->tx_hash); tcp_ctask->digest_count = 4; } @@ -1285,7 +1289,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); - set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_PAD; } /** @@ -1300,7 +1304,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); - tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT; + tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; } /** @@ -1314,10 +1318,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) * xmit. * * Management xmit state machine consists of these states: - * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header - * XMSTATE_BIT_IMM_HDR - PDU Header xmit in progress - * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress - * XMSTATE_VALUE_IDLE - management PDU is done + * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header + * XMSTATE_IMM_HDR - PDU Header xmit in progress + * XMSTATE_IMM_DATA - PDU Data xmit in progress + * XMSTATE_IDLE - management PDU is done **/ static int iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) @@ -1328,12 +1332,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", conn->id, tcp_mtask->xmstate, mtask->itt); - if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, sizeof(struct iscsi_hdr)); if (mtask->data_count) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, mtask->data_count); @@ -1346,20 +1350,21 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) (u8*)tcp_mtask->hdrext); tcp_mtask->sent = 0; - clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate); - set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; + tcp_mtask->xmstate |= XMSTATE_IMM_HDR; } - if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, mtask->data_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; } - if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { BUG_ON(!mtask->data_count); + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ @@ -1369,18 +1374,20 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, &mtask->data_count, &tcp_mtask->sent); if (rc) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; return rc; } } while (mtask->data_count); } - BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE); + BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); if (mtask->hdr->itt == RESERVED_ITT) { struct iscsi_session *session = conn->session; spin_lock_bh(&session->lock); - iscsi_free_mgmt_task(conn, mtask); + list_del(&conn->mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + sizeof(void*)); spin_unlock_bh(&session->lock); } return 0; @@ -1393,7 +1400,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; - if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { tcp_ctask->sent = 0; tcp_ctask->sg_count = 0; tcp_ctask->exp_datasn = 0; @@ -1421,26 +1428,26 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, - sizeof(struct iscsi_hdr)); + sizeof(struct iscsi_hdr)); if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)tcp_ctask->hdrext); - clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; + tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; } - if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; if (sc->sc_data_direction != DMA_TO_DEVICE) return 0; if (ctask->imm_count) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; iscsi_set_padding(tcp_ctask, ctask->imm_count); if (ctask->conn->datadgst_en) { @@ -1450,10 +1457,9 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } } - if (ctask->unsol_count) { - set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); - } + if (ctask->unsol_count) + tcp_ctask->xmstate |= + XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; } return rc; } @@ -1465,24 +1471,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int sent = 0, rc; - if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_W_PAD) { iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, tcp_ctask->pad_count); if (conn->datadgst_en) - crypto_digest_update(tcp_conn->tx_tfm, - &tcp_ctask->sendbuf.sg, 1); - } else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate)) + crypto_hash_update(&tcp_conn->tx_hash, + &tcp_ctask->sendbuf.sg, + tcp_ctask->sendbuf.sg.length); + } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) return 0; - clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); - clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_W_PAD; + tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; debug_scsi("sending %d pad bytes for itt 0x%x\n", - tcp_ctask->pad_count, ctask->itt); + tcp_ctask->pad_count, ctask->itt); rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, &sent); if (rc) { debug_scsi("padding send failed %d\n", rc); - set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; } return rc; } @@ -1501,12 +1508,12 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, tcp_ctask = ctask->dd_data; tcp_conn = conn->dd_data; - if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) { - crypto_digest_final(tcp_conn->tx_tfm, (u8*)digest); + if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { + crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); iscsi_buf_init_iov(buf, (char*)digest, 4); } - clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); - + tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; + rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (!rc) debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest, @@ -1514,7 +1521,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, else { debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", *digest, ctask->itt); - set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; } return rc; } @@ -1536,7 +1543,7 @@ iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf, rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent); *sent = *sent + buf_sent; if (buf_sent && conn->datadgst_en) - partial_sg_digest_update(tcp_conn->tx_tfm, + partial_sg_digest_update(&tcp_conn->tx_hash, &sendbuf->sg, sendbuf->sg.offset + offset, buf_sent); if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) { @@ -1562,8 +1569,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_data_task *dtask; int rc; - set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); - if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) { + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; + if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { dtask = &tcp_ctask->unsol_dtask; iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); @@ -1573,14 +1580,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)dtask->hdrext); - clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; iscsi_set_padding(tcp_ctask, ctask->data_count); } rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); if (rc) { - clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate |= XMSTATE_UNS_HDR; return rc; } @@ -1601,15 +1608,16 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc; - if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { BUG_ON(!ctask->unsol_count); + tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; send_hdr: rc = iscsi_send_unsol_hdr(conn, ctask); if (rc) return rc; } - if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; int start = tcp_ctask->sent; @@ -1619,14 +1627,14 @@ send_hdr: ctask->unsol_count -= tcp_ctask->sent - start; if (rc) return rc; - clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; /* * Done with the Data-Out. Next, check if we need * to send another unsolicited Data-Out. */ if (ctask->unsol_count) { debug_scsi("sending more uns\n"); - set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_UNS_INIT; goto send_hdr; } } @@ -1642,7 +1650,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, struct iscsi_data_task *dtask; int left, rc; - if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { if (!tcp_ctask->r2t) { spin_lock_bh(&session->lock); __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, @@ -1656,19 +1664,19 @@ send_hdr: if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)dtask->hdrext); - clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; } - if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; if (conn->datadgst_en) { iscsi_data_digest_init(conn->dd_data, tcp_ctask); @@ -1681,7 +1689,7 @@ send_hdr: r2t->sent); } - if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; @@ -1690,7 +1698,7 @@ send_hdr: &dtask->digestbuf, &dtask->digest); if (rc) return rc; - clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; /* * Done with this Data-Out. Next, check if we have @@ -1735,32 +1743,32 @@ send_hdr: * xmit stages. * *iscsi_send_cmd_hdr() - * XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate - * Header Digest - * XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress + * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate + * Header Digest + * XMSTATE_CMD_HDR_XMIT - Transmit header in progress * *iscsi_send_padding - * XMSTATE_BIT_W_PAD - Prepare and send pading - * XMSTATE_BIT_W_RESEND_PAD - retry send pading + * XMSTATE_W_PAD - Prepare and send pading + * XMSTATE_W_RESEND_PAD - retry send pading * *iscsi_send_digest - * XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest - * XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest + * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest + * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest * *iscsi_send_unsol_hdr - * XMSTATE_BIT_UNS_INIT - prepare un-solicit data header and digest - * XMSTATE_BIT_UNS_HDR - send un-solicit header + * XMSTATE_UNS_INIT - prepare un-solicit data header and digest + * XMSTATE_UNS_HDR - send un-solicit header * *iscsi_send_unsol_pdu - * XMSTATE_BIT_UNS_DATA - send un-solicit data in progress + * XMSTATE_UNS_DATA - send un-solicit data in progress * *iscsi_send_sol_pdu - * XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize - * XMSTATE_BIT_SOL_HDR - send solicit header - * XMSTATE_BIT_SOL_DATA - send solicit data + * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize + * XMSTATE_SOL_HDR - send solicit header + * XMSTATE_SOL_DATA - send solicit data * *iscsi_tcp_ctask_xmit - * XMSTATE_BIT_IMM_DATA - xmit managment data (??) + * XMSTATE_IMM_DATA - xmit managment data (??) **/ static int iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) @@ -1777,20 +1785,24 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) return 0; - if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, &tcp_ctask->sent, &ctask->imm_count, &tcp_ctask->immbuf, &tcp_ctask->immdigest); if (rc) return rc; - clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; } rc = iscsi_send_unsol_pdu(conn, ctask); if (rc) return rc; - return iscsi_send_sol_pdu(conn, ctask); + rc = iscsi_send_sol_pdu(conn, ctask); + if (rc) + return rc; + + return rc; } static struct iscsi_cls_conn * @@ -1820,26 +1832,32 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) /* initial operational parameters */ tcp_conn->hdr_size = sizeof(struct iscsi_hdr); - tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!tcp_conn->tx_tfm) { + tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + tcp_conn->tx_hash.flags = 0; + if (IS_ERR(tcp_conn->tx_hash.tfm)) { printk(KERN_ERR "Could not create connection due to crc32c " - "loading error. Make sure the crc32c module is " - "built as a module or into the kernel.\n"); + "loading error %ld. Make sure the crc32c module is " + "built as a module or into the kernel\n", + PTR_ERR(tcp_conn->tx_hash.tfm)); goto free_tcp_conn; } - tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!tcp_conn->rx_tfm) { + tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + tcp_conn->rx_hash.flags = 0; + if (IS_ERR(tcp_conn->rx_hash.tfm)) { printk(KERN_ERR "Could not create connection due to crc32c " - "loading error. Make sure the crc32c module is " - "built as a module or into the kernel.\n"); + "loading error %ld. Make sure the crc32c module is " + "built as a module or into the kernel\n", + PTR_ERR(tcp_conn->rx_hash.tfm)); goto free_tx_tfm; } return cls_conn; free_tx_tfm: - crypto_free_tfm(tcp_conn->tx_tfm); + crypto_free_hash(tcp_conn->tx_hash.tfm); free_tcp_conn: kfree(tcp_conn); tcp_conn_alloc_fail: @@ -1877,10 +1895,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) iscsi_tcp_release_conn(conn); iscsi_conn_teardown(cls_conn); - if (tcp_conn->tx_tfm) - crypto_free_tfm(tcp_conn->tx_tfm); - if (tcp_conn->rx_tfm) - crypto_free_tfm(tcp_conn->rx_tfm); + if (tcp_conn->tx_hash.tfm) + crypto_free_hash(tcp_conn->tx_hash.tfm); + if (tcp_conn->rx_hash.tfm) + crypto_free_hash(tcp_conn->rx_hash.tfm); kfree(tcp_conn); } @@ -1906,7 +1924,7 @@ static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock, struct sockaddr_in *sin; int rc = 0, len; - addr = kmalloc(sizeof(*addr), GFP_KERNEL); + addr = kmalloc(GFP_KERNEL, sizeof(*addr)); if (!addr) return -ENOMEM; @@ -2003,11 +2021,10 @@ free_socket: /* called with host lock */ static void -iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, - char *data, uint32_t data_size) +iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT; + tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; } static int @@ -2186,10 +2203,26 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) stats->custom[2].value = conn->eh_abort_cnt; } -static int iscsi_tcp_setup_tasks(struct iscsi_session *session) +static struct iscsi_cls_session * +iscsi_tcp_session_create(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint16_t cmds_max, uint16_t qdepth, + uint32_t initial_cmdsn, uint32_t *hostno) { + struct iscsi_cls_session *cls_session; + struct iscsi_session *session; + uint32_t hn; int cmd_i; + cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, + sizeof(struct iscsi_tcp_cmd_task), + sizeof(struct iscsi_tcp_mgmt_task), + initial_cmdsn, &hn); + if (!cls_session) + return NULL; + *hostno = hn; + + session = class_to_transport_session(cls_session); for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; @@ -2204,66 +2237,12 @@ static int iscsi_tcp_setup_tasks(struct iscsi_session *session) mtask->hdr = &tcp_mtask->hdr; } - if (iscsi_r2tpool_alloc(session)) - return -ENOMEM; - - return 0; -} - -/* - * iscsi_tcp_session_create2 is a KABI work around. For the new version - * we pass in the session and default device queue depth. - */ -static struct iscsi_cls_session * -iscsi_tcp_session_create2(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - uint16_t cmds_max, uint16_t qdepth, - uint32_t initial_cmdsn, uint32_t *hostno) -{ - struct iscsi_cls_session *cls_session; - uint32_t hn; - - cls_session = iscsi_session_setup2(iscsit, scsit, cmds_max, qdepth, - sizeof(struct iscsi_tcp_cmd_task), - sizeof(struct iscsi_tcp_mgmt_task), - initial_cmdsn, &hn); - if (!cls_session) - return NULL; - *hostno = hn; - - if (iscsi_tcp_setup_tasks(class_to_transport_session(cls_session))) - goto task_setup_fail; - - return cls_session; - -task_setup_fail: - iscsi_session_teardown(cls_session); - return NULL; -} - -static struct iscsi_cls_session * -iscsi_tcp_session_create(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - uint32_t initial_cmdsn, uint32_t *hostno) -{ - struct iscsi_cls_session *cls_session; - uint32_t hn; - - cls_session = iscsi_session_setup2(iscsit, scsit, ISCSI_XMIT_CMDS_MAX, - ISCSI_DEF_CMD_PER_LUN, - sizeof(struct iscsi_tcp_cmd_task), - sizeof(struct iscsi_tcp_mgmt_task), - initial_cmdsn, &hn); - if (!cls_session) - return NULL; - *hostno = hn; - - if (iscsi_tcp_setup_tasks(class_to_transport_session(cls_session))) - goto task_setup_fail; + if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) + goto r2tpool_alloc_fail; return cls_session; -task_setup_fail: +r2tpool_alloc_fail: iscsi_session_teardown(cls_session); return NULL; } @@ -2286,14 +2265,15 @@ static struct scsi_host_template iscsi_sht = { .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, .sg_tablesize = ISCSI_SG_TABLESIZE, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, + .eh_device_reset_handler= iscsi_eh_device_reset, .eh_host_reset_handler = iscsi_eh_host_reset, .use_clustering = DISABLE_CLUSTERING, - .slave_configure = iscsi_tcp_slave_configure, + .slave_configure = iscsi_tcp_slave_configure, .proc_name = "iscsi_tcp", .this_id = -1, }; @@ -2323,7 +2303,7 @@ static struct iscsi_transport iscsi_tcp_transport = { ISCSI_TARGET_NAME | ISCSI_TPGT | ISCSI_USERNAME | ISCSI_PASSWORD | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | - ISCSI_PING_TMO | ISCSI_RECV_TMO, + ISCSI_FAST_ABORT, .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME, @@ -2333,7 +2313,6 @@ static struct iscsi_transport iscsi_tcp_transport = { .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, /* session management */ .create_session = iscsi_tcp_session_create, - .create_session2 = iscsi_tcp_session_create2, .destroy_session = iscsi_tcp_session_destroy, /* connection management */ .create_conn = iscsi_tcp_conn_create, diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index b91b486b..4b86fe4d 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -22,7 +22,7 @@ #ifndef ISCSI_TCP_H #define ISCSI_TCP_H -#include +#include "libiscsi.h" /* Socket's Receive state machine */ #define IN_PROGRESS_WAIT_HEADER 0x0 @@ -32,26 +32,27 @@ #define IN_PROGRESS_PAD_RECV 0x4 /* xmit state machine */ -#define XMSTATE_VALUE_IDLE 0 -#define XMSTATE_BIT_CMD_HDR_INIT 0 -#define XMSTATE_BIT_CMD_HDR_XMIT 1 -#define XMSTATE_BIT_IMM_HDR 2 -#define XMSTATE_BIT_IMM_DATA 3 -#define XMSTATE_BIT_UNS_INIT 4 -#define XMSTATE_BIT_UNS_HDR 5 -#define XMSTATE_BIT_UNS_DATA 6 -#define XMSTATE_BIT_SOL_HDR 7 -#define XMSTATE_BIT_SOL_DATA 8 -#define XMSTATE_BIT_W_PAD 9 -#define XMSTATE_BIT_W_RESEND_PAD 10 -#define XMSTATE_BIT_W_RESEND_DATA_DIGEST 11 -#define XMSTATE_BIT_IMM_HDR_INIT 12 -#define XMSTATE_BIT_SOL_HDR_INIT 13 +#define XMSTATE_IDLE 0x0 +#define XMSTATE_CMD_HDR_INIT 0x1 +#define XMSTATE_CMD_HDR_XMIT 0x2 +#define XMSTATE_IMM_HDR 0x4 +#define XMSTATE_IMM_DATA 0x8 +#define XMSTATE_UNS_INIT 0x10 +#define XMSTATE_UNS_HDR 0x20 +#define XMSTATE_UNS_DATA 0x40 +#define XMSTATE_SOL_HDR 0x80 +#define XMSTATE_SOL_DATA 0x100 +#define XMSTATE_W_PAD 0x200 +#define XMSTATE_W_RESEND_PAD 0x400 +#define XMSTATE_W_RESEND_DATA_DIGEST 0x800 +#define XMSTATE_IMM_HDR_INIT 0x1000 +#define XMSTATE_SOL_HDR_INIT 0x2000 #define ISCSI_PAD_LEN 4 #define ISCSI_SG_TABLESIZE SG_ALL #define ISCSI_TCP_MAX_CMD_LEN 16 +struct crypto_hash; struct socket; /* Socket connection recieve helper */ @@ -95,8 +96,8 @@ struct iscsi_tcp_conn { void (*old_write_space)(struct sock *); /* data and header digests */ - struct crypto_tfm *tx_tfm; /* CRC32C (Tx) */ - struct crypto_tfm *rx_tfm; /* CRC32C (Rx) */ + struct hash_desc tx_hash; /* CRC32C (Tx) */ + struct hash_desc rx_hash; /* CRC32C (Rx) */ /* MIB custom statistics */ uint32_t sendpage_failures_cnt; @@ -121,7 +122,7 @@ struct iscsi_data_task { struct iscsi_tcp_mgmt_task { struct iscsi_hdr hdr; char hdrext[sizeof(__u32)]; /* Header-Digest */ - unsigned long xmstate; /* mgmt xmit progress */ + int xmstate; /* mgmt xmit progress */ struct iscsi_buf headbuf; /* header buffer */ struct iscsi_buf sendbuf; /* in progress buffer */ int sent; @@ -149,7 +150,7 @@ struct iscsi_tcp_cmd_task { int pad_count; /* padded bytes */ struct iscsi_buf headbuf; /* header buf (xmit) */ struct iscsi_buf sendbuf; /* in progress buffer*/ - unsigned long xmstate; /* xmit xtate machine */ + int xmstate; /* xmit xtate machine */ int sent; struct scatterlist *sg; /* per-cmd SG list */ struct scatterlist *bad_sg; /* assert statement */ diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6af7606f..0a641506 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -22,7 +22,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include -#include #include #include #include @@ -33,10 +32,10 @@ #include #include #include -#include #include -#include -#include +#include "iscsi_proto.h" +#include "scsi_transport_iscsi.h" +#include "libiscsi.h" struct iscsi_session * class_to_transport_session(struct iscsi_cls_session *cls_session) @@ -87,21 +86,13 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) * xmit thread */ if (!list_empty(&session->leadconn->xmitqueue) || - __kfifo_len(session->leadconn->mgmtqueue)) + !list_empty(&session->leadconn->mgmtqueue)) scsi_queue_work(session->host, &session->leadconn->xmitwork); } } EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); -int iscsi_check_assign_cmdsn(struct iscsi_session *session, - struct iscsi_nopin *hdr) -{ - iscsi_update_cmdsn(session, hdr); - return 0; -} -EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); - void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, struct iscsi_data *hdr) { @@ -181,19 +172,19 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) ctask->unsol_datasn = 0; if (session->imm_data_en) { - if (ctask->total_length >= session->first_burst) + if (sc->request_bufflen >= session->first_burst) ctask->imm_count = min(session->first_burst, conn->max_xmit_dlength); else - ctask->imm_count = min(ctask->total_length, + ctask->imm_count = min(sc->request_bufflen, conn->max_xmit_dlength); hton24(ctask->hdr->dlength, ctask->imm_count); } else zero_data(ctask->hdr->dlength); if (!session->initial_r2t_en) { - ctask->unsol_count = min(session->first_burst, - ctask->total_length) - ctask->imm_count; + ctask->unsol_count = min((session->first_burst), + (sc->request_bufflen)) - ctask->imm_count; ctask->unsol_offset = ctask->imm_count; } @@ -201,11 +192,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) /* No unsolicit Data-Out's */ ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; } else { - /* - * this has been moved to the iscsi_tcp mode upstream - * since it is only used there - */ - ctask->datasn = 0; hdr->flags |= ISCSI_FLAG_CMD_FINAL; zero_data(hdr->dlength); @@ -221,7 +207,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen, session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); } -EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu); /** * iscsi_complete_command - return command back to scsi-ml @@ -256,86 +241,6 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask) iscsi_complete_command(ctask); } -/** - * iscsi_free_mgmt_task - return mgmt task back to pool - * @conn: iscsi connection - * @mtask: mtask - * - * Must be called with session lock. - */ -void iscsi_free_mgmt_task(struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask) -{ - list_del_init(&mtask->running); - if (conn->login_mtask == mtask) - return; - - if (conn->ping_mtask == mtask) - conn->ping_mtask = NULL; - __kfifo_put(conn->session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); -} -EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); - -static struct iscsi_mgmt_task * -__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) -{ - struct iscsi_session *session = conn->session; - struct iscsi_mgmt_task *mtask; - - if (session->state == ISCSI_STATE_TERMINATE) - return NULL; - - if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || - hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) - /* - * Login and Text are sent serially, in - * request-followed-by-response sequence. - * Same mtask can be used. Same ITT must be used. - * Note that login_mtask is preallocated at conn_create(). - */ - mtask = conn->login_mtask; - else { - BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); - BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - - if (!__kfifo_get(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*))) - return NULL; - } - - if (data_size) { - memcpy(mtask->data, data, data_size); - mtask->data_count = data_size; - } else - mtask->data_count = 0; - - INIT_LIST_HEAD(&mtask->running); - memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); - __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - return mtask; -} - -int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - int err = 0; - - spin_lock_bh(&session->lock); - if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) { - err = -EPERM; - spin_unlock_bh(&session->lock); - return err; - } - spin_unlock_bh(&session->lock); - scsi_queue_work(session->host, &conn->xmitwork); - return 0; -} -EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); - /** * iscsi_cmd_rsp - SCSI Command Response processing * @conn: iscsi connection @@ -347,7 +252,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and * then completes the command and task. **/ -static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, +static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, struct iscsi_cmd_task *ctask, char *data, int datalen) { @@ -386,6 +291,9 @@ invalid_datalen: min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); } + if (sc->sc_data_direction == DMA_TO_DEVICE) + goto out; + if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { int res_count = be32_to_cpu(rhdr->residual_count); @@ -404,7 +312,6 @@ out: conn->scsirsp_pdus_cnt++; __iscsi_put_ctask(ctask); - return 0; } static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) @@ -414,51 +321,18 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; - if (conn->tmabort_state != TMABORT_INITIAL) + if (conn->tmf_state != TMF_QUEUED) return; if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmabort_state = TMABORT_SUCCESS; + conn->tmf_state = TMF_SUCCESS; else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmabort_state = TMABORT_NOT_FOUND; + conn->tmf_state = TMF_NOT_FOUND; else - conn->tmabort_state = TMABORT_FAILED; + conn->tmf_state = TMF_FAILED; wake_up(&conn->ehwait); } -static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) -{ - struct iscsi_nopout hdr; - struct iscsi_mgmt_task *mtask; - - if (!rhdr && conn->ping_mtask) - return; - - memset(&hdr, 0, sizeof(struct iscsi_nopout)); - hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; - hdr.flags = ISCSI_FLAG_CMD_FINAL; - - if (rhdr) { - memcpy(hdr.lun, rhdr->lun, 8); - hdr.ttt = rhdr->ttt; - hdr.itt = RESERVED_ITT; - } else - hdr.ttt = RESERVED_ITT; - - mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); - if (!mtask) { - printk(KERN_ERR "Could not send nopout\n"); - return; - } - - /* only track our nops */ - if (!rhdr) { - conn->ping_mtask = mtask; - conn->last_ping = jiffies; - } - scsi_queue_work(conn->session->host, &conn->xmitwork); -} - static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, int datalen) { @@ -503,7 +377,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, struct iscsi_mgmt_task *mtask; uint32_t itt; - conn->last_recv = jiffies; if (hdr->itt != RESERVED_ITT) itt = get_itt(hdr->itt); else @@ -559,7 +432,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, */ if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; - iscsi_free_mgmt_task(conn, mtask); + list_del_init(&mtask->running); + if (conn->login_mtask != mtask) + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); break; case ISCSI_OP_SCSI_TMFUNC_RSP: if (datalen) { @@ -576,16 +452,11 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - if (conn->ping_mtask != mtask) { - /* - * If this is not in response to one of our - * nops then it must be from userspace. - */ - if (iscsi_recv_pdu(conn->cls_conn, hdr, data, - datalen)) - rc = ISCSI_ERR_CONN_FAILED; - } - iscsi_free_mgmt_task(conn, mtask); + if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) + rc = ISCSI_ERR_CONN_FAILED; + list_del_init(&mtask->running); + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); break; default: rc = ISCSI_ERR_BAD_OPCODE; @@ -604,7 +475,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) break; - iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr); + if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0)) + rc = ISCSI_ERR_CONN_FAILED; break; case ISCSI_OP_REJECT: rc = iscsi_handle_reject(conn, hdr, data, datalen); @@ -731,11 +603,11 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, } if (session->tt->init_mgmt_task) - session->tt->init_mgmt_task(conn, mtask, mtask->data, - mtask->data_count); + session->tt->init_mgmt_task(conn, mtask); debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", - hdr->opcode, hdr->itt, mtask->data_count); + hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, + mtask->data_count); } static int iscsi_xmit_mtask(struct iscsi_conn *conn) @@ -784,27 +656,35 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) static int iscsi_xmit_ctask(struct iscsi_conn *conn) { struct iscsi_cmd_task *ctask = conn->ctask; - int rc = 0; - - /* - * serialize with TMF AbortTask - */ - if (ctask->state == ISCSI_TASK_ABORTING) - goto done; + int rc; __iscsi_get_ctask(ctask); spin_unlock_bh(&conn->session->lock); rc = conn->session->tt->xmit_cmd_task(conn, ctask); spin_lock_bh(&conn->session->lock); __iscsi_put_ctask(ctask); - -done: if (!rc) /* done with this ctask */ conn->ctask = NULL; return rc; } +/** + * iscsi_requeue_ctask - requeue ctask to run from session workqueue + * @ctask: ctask to requeue + * + * LLDs that need to run a ctask from the session workqueue should call + * this. The session lock must be held. + */ +void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + + list_move_tail(&ctask->running, &conn->requeue); + scsi_queue_work(conn->session->host, &conn->xmitwork); +} +EXPORT_SYMBOL_GPL(iscsi_requeue_ctask); + /** * iscsi_data_xmit - xmit any command into the scheduled connection * @conn: iscsi connection @@ -843,36 +723,27 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) * overflow us with nop-ins */ check_mgmt: - while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, - sizeof(void*))) { + while (!list_empty(&conn->mgmtqueue)) { + conn->mtask = list_entry(conn->mgmtqueue.next, + struct iscsi_mgmt_task, running); iscsi_prep_mtask(conn, conn->mtask); - list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); + list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); rc = iscsi_xmit_mtask(conn); if (rc) goto again; } - /* process command queue */ + /* process pending command queue */ while (!list_empty(&conn->xmitqueue)) { - /* - * iscsi tcp may readd the task to the xmitqueue to send - * write data - */ + if (conn->tmf_state == TMF_QUEUED) + break; + conn->ctask = list_entry(conn->xmitqueue.next, struct iscsi_cmd_task, running); - switch (conn->ctask->state) { - case ISCSI_TASK_ABORTING: - break; - case ISCSI_TASK_PENDING: - iscsi_prep_scsi_cmd_pdu(conn->ctask); - conn->session->tt->init_cmd_task(conn->ctask); - /* fall through */ - default: - conn->ctask->state = ISCSI_TASK_RUNNING; - break; - } + iscsi_prep_scsi_cmd_pdu(conn->ctask); + conn->session->tt->init_cmd_task(conn->ctask); + conn->ctask->state = ISCSI_TASK_RUNNING; list_move_tail(conn->xmitqueue.next, &conn->run_list); - rc = iscsi_xmit_ctask(conn); if (rc) goto again; @@ -881,7 +752,22 @@ check_mgmt: * we need to check the mgmt queue for nops that need to * be sent to aviod starvation */ - if (__kfifo_len(conn->mgmtqueue)) + if (!list_empty(&conn->mgmtqueue)) + goto check_mgmt; + } + + while (!list_empty(&conn->requeue)) { + if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) + break; + + conn->ctask = list_entry(conn->requeue.next, + struct iscsi_cmd_task, running); + conn->ctask->state = ISCSI_TASK_RUNNING; + list_move_tail(conn->requeue.next, &conn->run_list); + rc = iscsi_xmit_ctask(conn); + if (rc) + goto again; + if (!list_empty(&conn->mgmtqueue)) goto check_mgmt; } spin_unlock_bh(&conn->session->lock); @@ -894,9 +780,10 @@ again: return rc; } -static void iscsi_xmitworker(void *data) +static void iscsi_xmitworker(struct work_struct *work) { - struct iscsi_conn *conn = data; + struct iscsi_conn *conn = + container_of(work, struct iscsi_conn, xmitwork); int rc; /* * serialize Xmit worker on a per-connection basis. @@ -984,10 +871,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) atomic_set(&ctask->refcount, 1); ctask->state = ISCSI_TASK_PENDING; - ctask->mtask = NULL; ctask->conn = conn; ctask->sc = sc; - ctask->total_length = sc->request_bufflen; INIT_LIST_HEAD(&ctask->running); list_add_tail(&ctask->running, &conn->xmitqueue); @@ -1021,16 +906,71 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) } EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); +static struct iscsi_mgmt_task * +__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_session *session = conn->session; + struct iscsi_mgmt_task *mtask; + + if (session->state == ISCSI_STATE_TERMINATE) + return NULL; + + if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || + hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) + /* + * Login and Text are sent serially, in + * request-followed-by-response sequence. + * Same mtask can be used. Same ITT must be used. + * Note that login_mtask is preallocated at conn_create(). + */ + mtask = conn->login_mtask; + else { + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*))) + return NULL; + } + + if (data_size) { + memcpy(mtask->data, data, data_size); + mtask->data_count = data_size; + } else + mtask->data_count = 0; + + memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); + INIT_LIST_HEAD(&mtask->running); + list_add_tail(&mtask->running, &conn->mgmtqueue); + return mtask; +} + +int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + int err = 0; + + spin_lock_bh(&session->lock); + if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) + err = -EPERM; + spin_unlock_bh(&session->lock); + scsi_queue_work(session->host, &conn->xmitwork); + return err; +} +EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); + void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = class_to_transport_session(cls_session); - struct iscsi_conn *conn = session->leadconn; spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - if (conn) - wake_up(&conn->ehwait); + if (session->leadconn) + wake_up(&session->leadconn->ehwait); } spin_unlock_bh(&session->lock); } @@ -1041,7 +981,6 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) struct Scsi_Host *host = sc->device->host; struct iscsi_session *session = iscsi_hostdata(host->hostdata); struct iscsi_conn *conn = session->leadconn; - int fail_session = 0; spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { @@ -1052,19 +991,13 @@ failed: return FAILED; } - if (sc->SCp.phase == session->age) { - debug_scsi("failing connection CID %d due to SCSI host reset\n", - conn->id); - fail_session = 1; - } spin_unlock_bh(&session->lock); /* * we drop the lock here but the leadconn cannot be destoyed while * we are in the scsi eh */ - if (fail_session) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); debug_scsi("iscsi_eh_host_reset wait for relogin\n"); wait_event_interruptible(conn->ehwait, @@ -1085,62 +1018,43 @@ failed: } EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); -static void iscsi_tmabort_timedout(unsigned long data) +static void iscsi_tmf_timedout(unsigned long data) { - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; - struct iscsi_conn *conn = ctask->conn; + struct iscsi_conn *conn = (struct iscsi_conn *)data; struct iscsi_session *session = conn->session; spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmabort_state = TMABORT_TIMEDOUT; - debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", - ctask->sc, ctask->itt); + if (conn->tmf_state == TMF_QUEUED) { + conn->tmf_state = TMF_TIMEDOUT; + debug_scsi("tmf timedout\n"); /* unblock eh_abort() */ wake_up(&conn->ehwait); } spin_unlock(&session->lock); } -static int iscsi_exec_abort_task(struct scsi_cmnd *sc, - struct iscsi_cmd_task *ctask) +static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, + struct iscsi_tm *hdr, int age) { - struct iscsi_conn *conn = ctask->conn; struct iscsi_session *session = conn->session; - struct iscsi_tm *hdr = &conn->tmhdr; - - /* - * ctask timed out but session is OK requests must be serialized. - */ - memset(hdr, 0, sizeof(struct iscsi_tm)); - hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; - hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); - hdr->rtt = ctask->hdr->itt; - hdr->refcmdsn = ctask->hdr->cmdsn; + struct iscsi_mgmt_task *mtask; - ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, - NULL, 0); - if (!ctask->mtask) { + mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (!mtask) { spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - spin_lock_bh(&session->lock) - debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt); + spin_lock_bh(&session->lock); + debug_scsi("tmf exec failure\n"); return -EPERM; } - ctask->state = ISCSI_TASK_ABORTING; - - debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); + conn->tmfcmd_pdus_cnt++; + conn->tmf_timer.expires = 30 * HZ + jiffies; + conn->tmf_timer.function = iscsi_tmf_timedout; + conn->tmf_timer.data = (unsigned long)conn; + add_timer(&conn->tmf_timer); + debug_scsi("tmf set timeout\n"); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmfcmd_pdus_cnt++; - conn->tmabort_timer.expires = 20*HZ + jiffies; - conn->tmabort_timer.function = iscsi_tmabort_timedout; - conn->tmabort_timer.data = (unsigned long)ctask; - add_timer(&conn->tmabort_timer); - debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); - } spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); scsi_queue_work(session->host, &conn->xmitwork); @@ -1148,61 +1062,30 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, /* * block eh thread until: * - * 1) abort response - * 2) abort timeout + * 1) tmf response + * 2) tmf timeout * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(conn->ehwait, - sc->SCp.phase != session->age || + wait_event_interruptible(conn->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmabort_state != TMABORT_INITIAL); + conn->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&conn->tmabort_timer); + del_timer_sync(&conn->tmf_timer); + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); - return 0; -} - -/* - * session lock must be held - */ -static struct iscsi_mgmt_task * -iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) -{ - int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); - struct iscsi_mgmt_task *task; - - debug_scsi("searching %d tasks\n", nr_tasks); - - for (i = 0; i < nr_tasks; i++) { - __kfifo_get(fifo, (void*)&task, sizeof(void*)); - debug_scsi("check task %u\n", task->itt); - - if (task->itt == itt) { - debug_scsi("matched task\n"); - return task; - } + /* if the session drops it will clean up the mtask */ + if (age != session->age || + session->state != ISCSI_STATE_LOGGED_IN) + return -ENOTCONN; - __kfifo_put(fifo, (void*)&task, sizeof(void*)); + if (!list_empty(&mtask->running)) { + list_del_init(&mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); } - return NULL; -} - -static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) -{ - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - - if (!ctask->mtask) - return -EINVAL; - - if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt)) - list_del(&ctask->mtask->running); - __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, - sizeof(void*)); - ctask->mtask = NULL; return 0; } @@ -1226,7 +1109,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, conn->session->queued_cmdsn--; else conn->session->tt->cleanup_cmd_task(conn, ctask); - iscsi_ctask_mtask_cleanup(ctask); sc->result = err; sc->resid = sc->request_bufflen; @@ -1236,6 +1118,44 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, __iscsi_put_ctask(ctask); } +/* + * Fail commands. session lock held and recv side suspended and xmit + * thread flushed + */ +static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) +{ + struct iscsi_cmd_task *ctask, *tmp; + + if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1)) + conn->ctask = NULL; + + /* flush pending */ + list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing pending sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } + + list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing requeued sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } + + /* fail all other running */ + list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing in progress sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } +} + static void iscsi_suspend_tx(struct iscsi_conn *conn) { set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); @@ -1248,110 +1168,26 @@ static void iscsi_start_tx(struct iscsi_conn *conn) scsi_queue_work(conn->session->host, &conn->xmitwork); } -static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) -{ - struct iscsi_cls_session *cls_session; - struct iscsi_session *session; - struct iscsi_conn *conn; - enum scsi_eh_timer_return rc = EH_NOT_HANDLED; - - cls_session = starget_to_session(scsi_target(scmd->device)); - session = class_to_transport_session(cls_session); - - debug_scsi("scsi cmd %p timedout\n", scmd); - - spin_lock(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) { - /* - * We are probably in the middle of iscsi recovery so let - * that complete and handle the error. - */ - rc = EH_RESET_TIMER; - goto done; - } - - conn = session->leadconn; - if (!conn) { - /* In the middle of shuting down */ - rc = EH_RESET_TIMER; - goto done; - } - - if (!conn->recv_timeout && !conn->ping_timeout) - goto done; - /* - * if the ping timedout then we are in the middle of cleaning up - * and can let the iscsi eh handle it - */ - if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + - (conn->ping_timeout * HZ), jiffies)) - rc = EH_RESET_TIMER; - /* - * if we are about to check the transport then give the command - * more time - */ - else if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), - jiffies)) - rc = EH_RESET_TIMER; - /* if in the middle of checking the transport then give us more time */ - else if (conn->ping_mtask) - rc = EH_RESET_TIMER; -done: - spin_unlock(&session->lock); - debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh"); - return rc; -} - -static void iscsi_check_transport_timeouts(unsigned long data) +static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, + struct iscsi_tm *hdr) { - struct iscsi_conn *conn = (struct iscsi_conn *)data; - struct iscsi_session *session = conn->session; - unsigned long timeout, next_timeout = 0, last_recv; - - spin_lock(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) - goto done; - - timeout = conn->recv_timeout; - if (!timeout) - goto done; - - timeout *= HZ; - last_recv = conn->last_recv; - if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), - jiffies)) { - printk(KERN_ERR "ping timeout of %d secs expired, " - "last rx %lu, last ping %lu, now %lu\n", - conn->ping_timeout, last_recv, - conn->last_ping, jiffies); - spin_unlock(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - return; - } - - if (time_before_eq(last_recv + timeout, jiffies)) { - if (time_before_eq(conn->last_ping, last_recv)) { - /* send a ping to try to provoke some traffic */ - debug_scsi("Sending nopout as ping on conn %p\n", conn); - iscsi_send_nopout(conn, NULL); - } - next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); - } else - next_timeout = last_recv + timeout; - - debug_scsi("Setting next tmo %lu\n", next_timeout); - mod_timer(&conn->transport_timer, next_timeout); -done: - spin_unlock(&session->lock); + memset(hdr, 0, sizeof(*hdr)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->rtt = ctask->hdr->itt; + hdr->refcmdsn = ctask->hdr->cmdsn; } int iscsi_eh_abort(struct scsi_cmnd *sc) { struct Scsi_Host *host = sc->device->host; struct iscsi_session *session = iscsi_hostdata(host->hostdata); - struct iscsi_cmd_task *ctask; struct iscsi_conn *conn; - int rc; + struct iscsi_cmd_task *ctask; + struct iscsi_tm *hdr; + int rc, age; mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); @@ -1366,19 +1202,23 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) return SUCCESS; } - ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; - conn = ctask->conn; - - conn->eh_abort_cnt++; - debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); - /* * If we are not logged in or we have started a new session * then let the host reset code handle this */ - if (session->state != ISCSI_STATE_LOGGED_IN || - sc->SCp.phase != session->age) - goto failed; + if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN || + sc->SCp.phase != session->age) { + spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); + return FAILED; + } + + conn = session->leadconn; + conn->eh_abort_cnt++; + age = session->age; + + ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); /* ctask completed before time out */ if (!ctask->sc) { @@ -1386,27 +1226,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto success; } - /* what should we do here ? */ - if (conn->ctask == ctask) { - printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. " - "Failing abort\n", sc, ctask->itt); - goto failed; - } - if (ctask->state == ISCSI_TASK_PENDING) { fail_command(conn, ctask, DID_ABORT << 16); goto success; } - conn->tmabort_state = TMABORT_INITIAL; - rc = iscsi_exec_abort_task(sc, ctask); - if (rc || sc->SCp.phase != session->age || - session->state != ISCSI_STATE_LOGGED_IN) + /* only have one tmf outstanding at a time */ + if (conn->tmf_state != TMF_INITIAL) goto failed; - iscsi_ctask_mtask_cleanup(ctask); + conn->tmf_state = TMF_QUEUED; - switch (conn->tmabort_state) { - case TMABORT_SUCCESS: + hdr = &conn->tmhdr; + iscsi_prep_abort_task_pdu(ctask, hdr); + + if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) { + rc = FAILED; + goto failed; + } + + switch (conn->tmf_state) { + case TMF_SUCCESS: spin_unlock_bh(&session->lock); iscsi_suspend_tx(conn); /* @@ -1415,22 +1254,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) write_lock_bh(conn->recv_lock); spin_lock(&session->lock); fail_command(conn, ctask, DID_ABORT << 16); + conn->tmf_state = TMF_INITIAL; spin_unlock(&session->lock); write_unlock_bh(conn->recv_lock); iscsi_start_tx(conn); goto success_unlocked; - case TMABORT_NOT_FOUND: - if (!ctask->sc) { + case TMF_TIMEDOUT: + spin_unlock_bh(&session->lock); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + goto failed_unlocked; + case TMF_NOT_FOUND: + if (!sc->SCp.ptr) { + conn->tmf_state = TMF_INITIAL; /* ctask completed before tmf abort response */ debug_scsi("sc completed while abort in progress\n"); goto success; } /* fall through */ default: - /* timedout or failed */ - spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - goto failed_unlocked; + conn->tmf_state = TMF_INITIAL; + goto failed; } success: @@ -1443,12 +1286,93 @@ success_unlocked: failed: spin_unlock_bh(&session->lock); failed_unlocked: - debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, + ctask ? ctask->itt : 0); mutex_unlock(&session->eh_mutex); return FAILED; } EXPORT_SYMBOL_GPL(iscsi_eh_abort); +static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) +{ + memset(hdr, 0, sizeof(*hdr)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); + hdr->rtt = ISCSI_RESERVED_TAG; +} + +int iscsi_eh_device_reset(struct scsi_cmnd *sc) +{ + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); + struct iscsi_conn *conn; + struct iscsi_tm *hdr; + int rc = FAILED; + + debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); + + mutex_lock(&session->eh_mutex); + spin_lock_bh(&session->lock); + /* + * Just check if we are not logged in. We cannot check for + * the phase because the reset could come from a ioctl. + */ + if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) + goto unlock; + conn = session->leadconn; + + /* only have one tmf outstanding at a time */ + if (conn->tmf_state != TMF_INITIAL) + goto unlock; + conn->tmf_state = TMF_QUEUED; + + hdr = &conn->tmhdr; + iscsi_prep_lun_reset_pdu(sc, hdr); + + if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) { + rc = FAILED; + goto unlock; + } + + switch (conn->tmf_state) { + case TMF_SUCCESS: + break; + case TMF_TIMEDOUT: + spin_unlock_bh(&session->lock); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + goto done; + default: + conn->tmf_state = TMF_INITIAL; + goto unlock; + } + + rc = SUCCESS; + spin_unlock_bh(&session->lock); + + iscsi_suspend_tx(conn); + /* need to grab the recv lock then session lock */ + write_lock_bh(conn->recv_lock); + spin_lock(&session->lock); + fail_all_commands(conn, sc->device->lun); + conn->tmf_state = TMF_INITIAL; + spin_unlock(&session->lock); + write_unlock_bh(conn->recv_lock); + + iscsi_start_tx(conn); + goto done; + +unlock: + spin_unlock_bh(&session->lock); +done: + debug_scsi("iscsi_eh_device_reset %s\n", + rc == SUCCESS ? "SUCCESS" : "FAILED"); + mutex_unlock(&session->eh_mutex); + return rc; +} +EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); + int iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) { @@ -1520,12 +1444,26 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free); #define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) -static struct iscsi_cls_session * -__iscsi_session_setup(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - uint16_t cmds_max, uint16_t qdepth, - int cmd_task_size, int mgmt_task_size, - uint32_t initial_cmdsn, uint32_t *hostno) +/** + * iscsi_session_setup - create iscsi cls session and host and session + * @scsit: scsi transport template + * @iscsit: iscsi transport template + * @cmds_max: scsi host can queue + * @qdepth: scsi host cmds per lun + * @cmd_task_size: LLD ctask private data size + * @mgmt_task_size: LLD mtask private data size + * @initial_cmdsn: initial CmdSN + * @hostno: host no allocated + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +struct iscsi_cls_session * +iscsi_session_setup(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint16_t cmds_max, uint16_t qdepth, + int cmd_task_size, int mgmt_task_size, + uint32_t initial_cmdsn, uint32_t *hostno) { struct Scsi_Host *shost; struct iscsi_session *session; @@ -1535,9 +1473,9 @@ __iscsi_session_setup(struct iscsi_transport *iscsit, if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { if (qdepth != 0) printk(KERN_ERR "iscsi: invalid queue depth of %d. " - "Queue depth must be between 1 and %d.\n", - qdepth, ISCSI_MAX_CMD_PER_LUN); - qdepth = ISCSI_DEF_CMD_PER_LUN; + "Queue depth must be between 1 and %d.\n", + qdepth, ISCSI_MAX_CMD_PER_LUN); + qdepth = ISCSI_DEF_CMD_PER_LUN; } if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) || @@ -1546,8 +1484,8 @@ __iscsi_session_setup(struct iscsi_transport *iscsit, printk(KERN_ERR "iscsi: invalid can_queue of %d. " "can_queue must be a power of 2 and between " "2 and %d - setting to %d.\n", cmds_max, - ISCSI_MGMT_ITT_OFFSET, ISCSI_XMIT_CMDS_MAX); - cmds_max = ISCSI_XMIT_CMDS_MAX; + ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX); + cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; } shost = scsi_host_alloc(iscsit->host_template, @@ -1564,7 +1502,6 @@ __iscsi_session_setup(struct iscsi_transport *iscsit, shost->max_cmd_len = iscsit->max_cmd_len; shost->transportt = scsit; shost->transportt->create_work_queue = 1; - shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; *hostno = shost->host_no; session = iscsi_hostdata(shost->hostdata); @@ -1640,63 +1577,8 @@ cmdpool_alloc_fail: scsi_host_put(shost); return NULL; } - -/** - * iscsi_session_setup - create iscsi cls session and host and session - * @scsit: scsi transport template - * @iscsit: iscsi transport template - * @cmd_task_size: LLD ctask private data size - * @mgmt_task_size: LLD mtask private data size - * @initial_cmdsn: initial CmdSN - * @hostno: host no allocated - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -struct iscsi_cls_session * -iscsi_session_setup(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - int cmd_task_size, int mgmt_task_size, - uint32_t initial_cmdsn, uint32_t *hostno) -{ - return __iscsi_session_setup(iscsit, scsit, ISCSI_XMIT_CMDS_MAX, - ISCSI_DEF_CMD_PER_LUN, - cmd_task_size, mgmt_task_size, - initial_cmdsn, hostno); -} EXPORT_SYMBOL_GPL(iscsi_session_setup); -/* - * This is a KABI work around. This new version takes the defaults - * session queue depth and default device queue depth. - */ -/** - * iscsi_session_setup - create iscsi cls session and host and session - * @scsit: scsi transport template - * @iscsit: iscsi transport template - * @cmds_max: session queue depth - * @qdepth: default device queue depth - * @cmd_task_size: LLD ctask private data size - * @mgmt_task_size: LLD mtask private data size - * @initial_cmdsn: initial CmdSN - * @hostno: host no allocated - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -struct iscsi_cls_session * -iscsi_session_setup2(struct iscsi_transport *iscsit, - struct scsi_transport_template *scsit, - uint16_t cmds_max, uint16_t qdepth, - int cmd_task_size, int mgmt_task_size, - uint32_t initial_cmdsn, uint32_t *hostno) -{ - return __iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, - cmd_task_size, mgmt_task_size, - initial_cmdsn, hostno); -} -EXPORT_SYMBOL_GPL(iscsi_session_setup2); - /** * iscsi_session_teardown - destroy session, host, and cls_session * shost: scsi host @@ -1755,23 +1637,13 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; - conn->tmabort_state = TMABORT_INITIAL; - - init_timer(&conn->transport_timer); - conn->transport_timer.data = (unsigned long)conn; - conn->transport_timer.function = iscsi_check_transport_timeouts; - + conn->tmf_state = TMF_INITIAL; INIT_LIST_HEAD(&conn->run_list); INIT_LIST_HEAD(&conn->mgmt_run_list); + INIT_LIST_HEAD(&conn->mgmtqueue); INIT_LIST_HEAD(&conn->xmitqueue); - - /* initialize general immediate & non-immediate PDU commands queue */ - conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) - goto mgmtqueue_alloc_fail; - - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + INIT_LIST_HEAD(&conn->requeue); + INIT_WORK(&conn->xmitwork, iscsi_xmitworker); /* allocate login_mtask used for the login/text sequences */ spin_lock_bh(&session->lock); @@ -1788,18 +1660,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) goto login_mtask_data_alloc_fail; conn->login_mtask->data = conn->data = data; - init_timer(&conn->tmabort_timer); - /* - * RHEL5.0 iscsi_tcp tried to ise the xmitmutex to serialize - * access to the connection during sysfs access and teardown - * and setup, but the code did not actually protect the access - * due to a bug. So incase somone uses a new libiscsi with old - * iscsi_tcp, we init this and those weirdos would get the old - * broken behavior. - * - * TODO: Do I have to support such weirdness for KABI? - */ - mutex_init(&conn->xmitmutex); + init_timer(&conn->tmf_timer); init_waitqueue_head(&conn->ehwait); return cls_conn; @@ -1808,8 +1669,6 @@ login_mtask_data_alloc_fail: __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); login_mtask_alloc_fail: - kfifo_free(conn->mgmtqueue); -mgmtqueue_alloc_fail: iscsi_destroy_conn(cls_conn); return NULL; } @@ -1828,10 +1687,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) struct iscsi_session *session = conn->session; unsigned long flags; - del_timer_sync(&conn->transport_timer); - spin_lock_bh(&session->lock); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; if (session->leadconn == conn) { /* @@ -1864,7 +1720,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) } /* flush queued up work because we free the connection below */ - scsi_flush_work(session->host); + iscsi_suspend_tx(conn); spin_lock_bh(&session->lock); kfree(conn->data); @@ -1875,8 +1731,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) session->leadconn = NULL; spin_unlock_bh(&session->lock); - kfifo_free(conn->mgmtqueue); - iscsi_destroy_conn(cls_conn); } EXPORT_SYMBOL_GPL(iscsi_conn_teardown); @@ -1899,29 +1753,11 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) return -EINVAL; } - if (conn->ping_timeout && !conn->recv_timeout) { - printk(KERN_ERR "iscsi: invalid recv timeout of zero. " - "Using 5 seconds\n."); - conn->recv_timeout = 5; - } - - if (conn->recv_timeout && !conn->ping_timeout) { - printk(KERN_ERR "iscsi: invalid ping timeout of zero. " - "Using 5 seconds.\n"); - conn->ping_timeout = 5; - } - spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STARTED; session->state = ISCSI_STATE_LOGGED_IN; session->queued_cmdsn = session->cmdsn; - conn->last_recv = jiffies; - conn->last_ping = jiffies; - if (conn->recv_timeout && conn->ping_timeout) - mod_timer(&conn->transport_timer, - jiffies + (conn->recv_timeout * HZ)); - switch(conn->stop_stage) { case STOP_CONN_RECOVER: /* @@ -1929,7 +1765,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * commands after successful recovery */ conn->stop_stage = 0; - conn->tmabort_state = TMABORT_INITIAL; + conn->tmf_state = TMF_INITIAL; session->age++; spin_unlock_bh(&session->lock); @@ -1954,40 +1790,27 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) struct iscsi_mgmt_task *mtask, *tmp; /* handle pending */ - while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { + list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); - iscsi_free_mgmt_task(conn, mtask); + list_del_init(&mtask->running); + if (mtask == conn->login_mtask) + continue; + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); } /* handle running */ list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); - iscsi_free_mgmt_task(conn, mtask); - } + list_del_init(&mtask->running); - conn->mtask = NULL; -} - -/* Fail commands. Mutex and session lock held and recv side suspended */ -static void fail_all_commands(struct iscsi_conn *conn) -{ - struct iscsi_cmd_task *ctask, *tmp; - - /* flush pending */ - list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { - debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, - ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); - } - - /* fail all other running */ - list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { - debug_scsi("failing in progress sc %p itt 0x%x\n", - ctask->sc, ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); + if (mtask == conn->login_mtask) + continue; + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); } - conn->ctask = NULL; + conn->mtask = NULL; } static void iscsi_start_session_recovery(struct iscsi_session *session, @@ -1995,8 +1818,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, { int old_stop_stage; - del_timer_sync(&conn->transport_timer); - mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (conn->stop_stage == STOP_CONN_TERM) { @@ -2057,7 +1878,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, * flush queues. */ spin_lock_bh(&session->lock); - fail_all_commands(conn); + fail_all_commands(conn, -1); flush_control_queues(session, conn); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); @@ -2108,11 +1929,8 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, uint32_t value; switch(param) { - case ISCSI_PARAM_PING_TMO: - sscanf(buf, "%d", &conn->ping_timeout); - break; - case ISCSI_PARAM_RECV_TMO: - sscanf(buf, "%d", &conn->recv_timeout); + case ISCSI_PARAM_FAST_ABORT: + sscanf(buf, "%d", &session->fast_abort); break; case ISCSI_PARAM_MAX_RECV_DLENGTH: sscanf(buf, "%d", &conn->max_recv_dlength); @@ -2228,6 +2046,9 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, int len; switch(param) { + case ISCSI_PARAM_FAST_ABORT: + len = sprintf(buf, "%d\n", session->fast_abort); + break; case ISCSI_PARAM_INITIAL_R2T_EN: len = sprintf(buf, "%d\n", session->initial_r2t_en); break; @@ -2285,12 +2106,6 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, int len; switch(param) { - case ISCSI_PARAM_PING_TMO: - len = sprintf(buf, "%u\n", conn->ping_timeout); - break; - case ISCSI_PARAM_RECV_TMO: - len = sprintf(buf, "%u\n", conn->recv_timeout); - break; case ISCSI_PARAM_MAX_RECV_DLENGTH: len = sprintf(buf, "%u\n", conn->max_recv_dlength); break; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 6c97a46c..96d44c3d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -27,13 +27,13 @@ #include #include #include -#include -#include +#include "scsi_transport_iscsi.h" +#include "iscsi_if.h" -#define ISCSI_SESSION_ATTRS 15 -#define ISCSI_CONN_ATTRS 13 +#define ISCSI_SESSION_ATTRS 16 +#define ISCSI_CONN_ATTRS 11 #define ISCSI_HOST_ATTRS 4 -#define ISCSI_TRANSPORT_VERSION "2.0-724" +#define ISCSI_TRANSPORT_VERSION "2.0-865" struct iscsi_internal { int daemon_pid; @@ -234,9 +234,11 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, return 0; } -static void session_recovery_timedout(void *data) +static void session_recovery_timedout(struct work_struct *work) { - struct iscsi_cls_session *session = data; + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, + recovery_work.work); dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " "out after %d secs\n", session->recovery_tmo); @@ -276,7 +278,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, session->transport = transport; session->recovery_tmo = 120; - INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->host_list); INIT_LIST_HEAD(&session->sess_list); @@ -811,17 +813,11 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) unsigned long flags; uint32_t hostno; - if ((!ev->u.c_session.cmds_max && !ev->u.c_session.queue_depth) || - !transport->create_session2) - session = transport->create_session(transport, &priv->t, - ev->u.c_session.initial_cmdsn, - &hostno); - else - session = transport->create_session2(transport, &priv->t, - ev->u.c_session.cmds_max, - ev->u.c_session.queue_depth, - ev->u.c_session.initial_cmdsn, - &hostno); + session = transport->create_session(transport, &priv->t, + ev->u.c_session.cmds_max, + ev->u.c_session.queue_depth, + ev->u.c_session.initial_cmdsn, + &hostno); if (!session) return -ENOMEM; @@ -951,20 +947,31 @@ static int iscsi_tgt_dscvr(struct iscsi_transport *transport, struct iscsi_uevent *ev) { + struct Scsi_Host *shost; struct sockaddr *dst_addr; + int err; if (!transport->tgt_dscvr) return -EINVAL; + shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "target discovery could not find host no %u\n", + ev->u.tgt_dscvr.host_no); + return -ENODEV; + } + + dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); - return transport->tgt_dscvr(ev->u.tgt_dscvr.type, - ev->u.tgt_dscvr.host_no, - ev->u.tgt_dscvr.enable, dst_addr); + err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type, + ev->u.tgt_dscvr.enable, dst_addr); + scsi_host_put(shost); + return err; } static int iscsi_set_host_param(struct iscsi_transport *transport, - struct iscsi_uevent *ev) + struct iscsi_uevent *ev) { char *data = (char*)ev + sizeof(*ev); struct Scsi_Host *shost; @@ -1081,7 +1088,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_set_host_param(transport, ev); break; default: - err = -EINVAL; + err = -ENOSYS; break; } @@ -1184,8 +1191,6 @@ iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT); iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS); -iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO); -iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO); #define iscsi_cdev_to_session(_cdev) \ iscsi_dev_to_session(_cdev->dev) @@ -1224,6 +1229,7 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1); iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1); iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1); iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1); +iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1); #define iscsi_priv_session_attr_show(field, format) \ static ssize_t \ @@ -1267,6 +1273,7 @@ do { \ count++; \ } while (0) + #define SETUP_SESSION_RD_ATTR(field, param_flag) \ do { \ if (tt->param_mask & param_flag) { \ @@ -1398,7 +1405,6 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS); SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS); SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME); - BUG_ON(count > ISCSI_HOST_ATTRS); priv->host_attrs[count] = NULL; count = 0; @@ -1420,8 +1426,6 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); - SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO); - SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO); BUG_ON(count > ISCSI_CONN_ATTRS); priv->conn_attrs[count] = NULL; @@ -1447,6 +1451,7 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN); SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD); SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN); + SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT); SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); BUG_ON(count > ISCSI_SESSION_ATTRS); @@ -1521,7 +1526,7 @@ static __init int iscsi_transport_init(void) goto unregister_conn_class; nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, - THIS_MODULE); + NULL, THIS_MODULE); if (!nls) { err = -ENOBUFS; goto unregister_session_class; diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 4e7ae4c0..803e8d9f 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -21,7 +21,7 @@ #ifndef ISCSI_IF_H #define ISCSI_IF_H -#include +#include #define UEVENT_BASE 10 #define KEVENT_BASE 100 @@ -48,9 +48,7 @@ enum iscsi_uevent_e { ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT = UEVENT_BASE + 14, ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15, -#ifndef __GENKSYMS__ ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16, -#endif /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, @@ -74,10 +72,8 @@ struct iscsi_uevent { /* messages u -> k */ struct msg_create_session { uint32_t initial_cmdsn; -#ifndef __GENKSYMS__ uint16_t cmds_max; uint16_t queue_depth; -#endif } c_session; struct msg_destroy_session { uint32_t sid; @@ -143,13 +139,11 @@ struct iscsi_uevent { */ uint32_t enable; } tgt_dscvr; -#ifndef __GENKSYMS__ struct msg_set_host_param { uint32_t host_no; uint32_t param; /* enum iscsi_host_param */ uint32_t len; } set_host_param; -#endif } u; union { /* messages k -> u */ @@ -237,29 +231,14 @@ enum iscsi_param { ISCSI_PARAM_CONN_PORT, ISCSI_PARAM_CONN_ADDRESS, - /* must always be last */ - ISCSI_PARAM_MAX, - -#ifndef __GENKSYMS__ - /* no one uses ISCSI_PARAM_MAX */ - ISCSI_PARAM_USERNAME = ISCSI_PARAM_MAX, + ISCSI_PARAM_USERNAME, ISCSI_PARAM_USERNAME_IN, ISCSI_PARAM_PASSWORD, ISCSI_PARAM_PASSWORD_IN, - /* - * These tmf timers are not yet used in RHEL, but come before the ping - * ones upstream so they are being brought in to maintain ordering. - */ ISCSI_PARAM_FAST_ABORT, - ISCSI_PARAM_ABORT_TMO, - ISCSI_PARAM_LU_RESET_TMO, - ISCSI_PARAM_HOST_RESET_TMO, - - ISCSI_PARAM_PING_TMO, - ISCSI_PARAM_RECV_TMO, - -#endif + /* must always be last */ + ISCSI_PARAM_MAX, }; #define ISCSI_MAX_RECV_DLENGTH (1 << ISCSI_PARAM_MAX_RECV_DLENGTH) @@ -289,11 +268,6 @@ enum iscsi_param { #define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) #define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) #define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) -#define ISCSI_ABORT_TMO (1 << ISCSI_PARAM_ABORT_TMO) -#define ISCSI_LU_RESET_TMO (1 << ISCSI_PARAM_LU_RESET_TMO) -#define ISCSI_HOST_RESET_TMO (1 << ISCSI_PARAM_HOST_RESET_TMO) -#define ISCSI_PING_TMO (1 << ISCSI_PARAM_PING_TMO) -#define ISCSI_RECV_TMO (1 << ISCSI_PARAM_RECV_TMO) /* iSCSI HBA params */ enum iscsi_host_param { @@ -339,7 +313,6 @@ enum iscsi_host_param { * These flags describes reason of stop_conn() call */ #define STOP_CONN_TERM 0x1 -#define STOP_CONN_SUSPEND 0x2 #define STOP_CONN_RECOVER 0x3 #define ISCSI_STATS_CUSTOM_MAX 32 diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index a845f2e4..e821932e 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -40,6 +40,21 @@ } #define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;} +/* + * If running svn modules we may need to define these. + * This should not go upstream since this is already properly defined there + */ +#ifdef __CHECKER__ +#define __bitwise__ __attribute__((bitwise)) +#else +#define __bitwise__ +#endif +#ifdef __CHECK_ENDIAN__ +#define __bitwise __bitwise__ +#else +#define __bitwise +#endif + /* initiator tags; opaque for target */ typedef uint32_t __bitwise__ itt_t; /* below makes sense only for initiator that created this tag */ @@ -58,12 +73,7 @@ struct iscsi_hdr { uint8_t hlength; /* AHSs total length */ uint8_t dlength[3]; /* Data length */ uint8_t lun[8]; - -#ifndef __GENKSYMS__ itt_t itt; /* Initiator Task Tag, opaque for target */ -#else - __be32 itt; -#endif __be32 ttt; /* Target Task Tag */ __be32 statsn; __be32 exp_statsn; @@ -124,11 +134,7 @@ struct iscsi_cmd { uint8_t hlength; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 data_length; __be32 cmdsn; __be32 exp_statsn; @@ -165,11 +171,7 @@ struct iscsi_cmd_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 rsvd1; __be32 statsn; __be32 exp_cmdsn; @@ -227,11 +229,7 @@ struct iscsi_nopout { uint8_t rsvd3; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 ttt; /* Target Transfer Tag */ __be32 cmdsn; __be32 exp_statsn; @@ -246,11 +244,7 @@ struct iscsi_nopin { uint8_t rsvd3; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 ttt; /* Target Transfer Tag */ __be32 statsn; __be32 exp_cmdsn; @@ -266,17 +260,8 @@ struct iscsi_tm { uint8_t hlength; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif - -#ifndef __GENKSYMS__ - itt_t rtt; /* Reference Task Tag */ -#else - __be32 rtt; -#endif + itt_t rtt; /* Reference Task Tag */ __be32 cmdsn; __be32 exp_statsn; __be32 refcmdsn; @@ -305,17 +290,8 @@ struct iscsi_tm_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd2[8]; -#ifndef __GENKSYMS__ itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif - -#ifndef __GENKSYMS__ - itt_t rtt; /* Reference Task Tag */ -#else - __be32 rtt -#endif + itt_t rtt; /* Reference Task Tag */ __be32 statsn; __be32 exp_cmdsn; __be32 max_cmdsn; @@ -340,11 +316,7 @@ struct iscsi_r2t_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif __be32 ttt; /* Target Transfer Tag */ __be32 statsn; __be32 exp_cmdsn; @@ -362,11 +334,7 @@ struct iscsi_data { uint8_t rsvd3; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ itt_t itt; -#else - __be32 itt; -#endif __be32 ttt; __be32 rsvd4; __be32 exp_statsn; @@ -386,11 +354,7 @@ struct iscsi_data_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t lun[8]; -#ifndef __GENKSYMS__ - itt_t itt; -#else - __be32 itt; -#endif + itt_t itt; __be32 ttt; __be32 statsn; __be32 exp_cmdsn; @@ -414,11 +378,7 @@ struct iscsi_text { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd4[8]; -#ifndef __GENKSYMS__ - itt_t itt; -#else - __be32 itt; -#endif + itt_t itt; __be32 ttt; __be32 cmdsn; __be32 exp_statsn; @@ -436,11 +396,7 @@ struct iscsi_text_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd4[8]; -#ifndef __GENKSYMS__ - itt_t itt; -#else - __be32 itt; -#endif + itt_t itt; __be32 ttt; __be32 statsn; __be32 exp_cmdsn; @@ -459,11 +415,7 @@ struct iscsi_login { uint8_t dlength[3]; uint8_t isid[6]; /* Initiator Session ID */ __be16 tsih; /* Target Session Handle */ -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be16 cid; __be16 rsvd3; __be32 cmdsn; @@ -492,11 +444,7 @@ struct iscsi_login_rsp { uint8_t dlength[3]; uint8_t isid[6]; /* Initiator Session ID */ __be16 tsih; /* Target Session Handle */ -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 rsvd3; __be32 statsn; __be32 exp_cmdsn; @@ -553,11 +501,7 @@ struct iscsi_logout { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd2[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be16 cid; uint8_t rsvd3[2]; __be32 cmdsn; @@ -584,11 +528,7 @@ struct iscsi_logout_rsp { uint8_t hlength; uint8_t dlength[3]; uint8_t rsvd3[8]; -#ifndef __GENKSYMS__ - itt_t itt; /* Initiator Task Tag */ -#else - __be32 itt; -#endif + itt_t itt; /* Initiator Task Tag */ __be32 rsvd4; __be32 statsn; __be32 exp_cmdsn; @@ -611,11 +551,7 @@ struct iscsi_snack { uint8_t opcode; uint8_t flags; uint8_t rsvd2[14]; -#ifndef __GENKSYMS__ - itt_t itt; -#else - __be32 itt; -#endif + itt_t itt; __be32 begrun; __be32 runlength; __be32 exp_statsn; @@ -667,8 +603,6 @@ struct iscsi_reject { #define VALUE_MAXLEN 255 #define TARGET_NAME_MAXLEN VALUE_MAXLEN -#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 - #define ISCSI_DEF_MAX_RECV_SEG_LEN 8192 #define ISCSI_MIN_MAX_RECV_SEG_LEN 512 #define ISCSI_MAX_MAX_RECV_SEG_LEN 16777215 @@ -681,6 +615,8 @@ struct iscsi_reject { #define ISCSI_MIN_MAX_BURST_LEN 512 #define ISCSI_MAX_MAX_BURST_LEN 16777215 +#define ISCSI_DEF_TIME2WAIT 2 + /************************* RFC 3720 End *****************************/ #endif /* ISCSI_PROTO_H */ diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 2b936f77..dbea6b46 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -25,8 +25,10 @@ #include #include -#include -#include +#include +#include +#include "iscsi_proto.h" +#include "iscsi_if.h" struct scsi_transport_template; struct scsi_device; @@ -46,11 +48,8 @@ struct iscsi_nopin; #define debug_scsi(fmt...) #endif -#define ISCSI_XMIT_CMDS_MAX 256 /* must be power of 2 */ +#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ #define ISCSI_MGMT_CMDS_MAX 16 /* must be power of 2 */ -#define ISCSI_CONN_MAX 1 - -#define ISCSI_ADDRESS_BUF_LEN 64 #define ISCSI_MGMT_ITT_OFFSET 0xa00 @@ -58,11 +57,14 @@ struct iscsi_nopin; #define ISCSI_MAX_CMD_PER_LUN 128 /* Task Mgmt states */ -#define TMABORT_INITIAL 0x0 -#define TMABORT_SUCCESS 0x1 -#define TMABORT_FAILED 0x2 -#define TMABORT_TIMEDOUT 0x3 -#define TMABORT_NOT_FOUND 0x4 +enum { + TMF_INITIAL, + TMF_QUEUED, + TMF_SUCCESS, + TMF_FAILED, + TMF_TIMEDOUT, + TMF_NOT_FOUND, +}; /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 @@ -73,6 +75,8 @@ struct iscsi_nopin; #define ISCSI_AGE_SHIFT 28 #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) +#define ISCSI_ADDRESS_BUF_LEN 64 + struct iscsi_mgmt_task { /* * Becuae LLDs allocate their hdr differently, this is a pointer to @@ -80,7 +84,7 @@ struct iscsi_mgmt_task { */ struct iscsi_hdr *hdr; char *data; /* mgmt payload */ - int data_count; /* counts data to be sent */ + unsigned data_count; /* counts data to be sent */ uint32_t itt; /* this ITT */ void *dd_data; /* driver/transport data */ struct list_head running; @@ -90,9 +94,6 @@ enum { ISCSI_TASK_COMPLETED, ISCSI_TASK_PENDING, ISCSI_TASK_RUNNING, -#ifndef __GENKSYMS__ - ISCSI_TASK_ABORTING, -#endif }; struct iscsi_cmd_task { @@ -102,18 +103,15 @@ struct iscsi_cmd_task { */ struct iscsi_cmd *hdr; int itt; /* this ITT */ - int datasn; /* DataSN */ uint32_t unsol_datasn; - int imm_count; /* imm-data (bytes) */ - int unsol_count; /* unsolicited (bytes)*/ + unsigned imm_count; /* imm-data (bytes) */ + unsigned unsol_count; /* unsolicited (bytes)*/ /* offset in unsolicited stream (bytes); */ - int unsol_offset; - int data_count; /* remaining Data-Out */ + unsigned unsol_offset; + unsigned data_count; /* remaining Data-Out */ struct scsi_cmnd *sc; /* associated SCSI cmd*/ - int total_length; struct iscsi_conn *conn; /* used connection */ - struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ /* state set/tested under session->lock */ int state; @@ -141,7 +139,6 @@ struct iscsi_conn { /* control data */ int id; /* CID */ - struct list_head item; /* maintains list of conns */ int c_stage; /* connection state */ /* * Preallocated buffer for pdus that have data but do not @@ -156,30 +153,24 @@ struct iscsi_conn { struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ /* xmit */ - struct kfifo *immqueue; /* immediate xmit queue */ - struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ + struct list_head mgmtqueue; /* mgmt (control) xmit queue */ struct list_head mgmt_run_list; /* list of control tasks */ struct list_head xmitqueue; /* data-path cmd queue */ struct list_head run_list; /* list of cmds in progress */ + struct list_head requeue; /* tasks needing another run */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ - /* - * serializes connection xmit, access to kfifos: - * xmitqueue, immqueue, mgmtqueue - */ - struct mutex xmitmutex; - unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */ /* abort */ wait_queue_head_t ehwait; /* used in eh_abort() */ struct iscsi_tm tmhdr; - struct timer_list tmabort_timer; - int tmabort_state; /* see TMABORT_INITIAL, etc.*/ + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ /* negotiated params */ - int max_recv_dlength; /* initiator_max_recv_dsl*/ - int max_xmit_dlength; /* target_max_recv_dsl */ + unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ + unsigned max_xmit_dlength; /* target_max_recv_dsl */ int hdrdgst_en; int datadgst_en; int ifmarker_en; @@ -187,6 +178,12 @@ struct iscsi_conn { /* values userspace uses to id a conn */ int persistent_port; char *persistent_address; + /* remote portal currently connected to */ + int portal_port; + char portal_address[ISCSI_ADDRESS_BUF_LEN]; + /* local address */ + int local_port; + char local_address[ISCSI_ADDRESS_BUF_LEN]; /* MIB-statistics */ uint64_t txdata_octets; @@ -201,21 +198,6 @@ struct iscsi_conn { /* custom statistics */ uint32_t eh_abort_cnt; -#ifndef __GENKSYMS__ - /* remote portal currently connected to */ - int portal_port; - char portal_address[ISCSI_ADDRESS_BUF_LEN]; - /* local address */ - int local_port; - char local_address[ISCSI_ADDRESS_BUF_LEN]; - - struct timer_list transport_timer; - unsigned long last_recv; - unsigned long last_ping; - int ping_timeout; - int recv_timeout; - struct iscsi_mgmt_task *ping_mtask; -#endif }; struct iscsi_queue { @@ -225,25 +207,43 @@ struct iscsi_queue { }; struct iscsi_session { + /* + * Syncs up the scsi eh thread with the iscsi eh thread when sending + * task management functions. This must be taken before the session + * and recv lock. + */ + struct mutex eh_mutex; + /* iSCSI session-wide sequencing */ uint32_t cmdsn; uint32_t exp_cmdsn; uint32_t max_cmdsn; + /* This tracks the reqs queued into the initiator */ + uint32_t queued_cmdsn; + /* configuration */ int initial_r2t_en; - int max_r2t; + unsigned max_r2t; int imm_data_en; - int first_burst; - int max_burst; + unsigned first_burst; + unsigned max_burst; int time2wait; int time2retain; int pdu_inorder_en; int dataseq_inorder_en; int erl; + int fast_abort; int tpgt; + char *username; + char *username_in; + char *password; + char *password_in; char *targetname; - + char *initiatorname; + /* hw address or netdev iscsi connection is bound to */ + char *hwaddress; + char *netdev; /* control data */ struct iscsi_transport *tt; struct Scsi_Host *host; @@ -255,35 +255,14 @@ struct iscsi_session { * - mgmtpool, * * - r2tpool */ int state; /* session state */ - struct list_head item; int age; /* counts session re-opens */ - struct list_head connections; /* list of connections */ int cmds_max; /* size of cmds array */ struct iscsi_cmd_task **cmds; /* Original Cmds arr */ struct iscsi_queue cmdpool; /* PDU's pool */ int mgmtpool_max; /* size of mgmt array */ struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */ -#ifndef __GENKSYMS__ - /* This tracks the reqs queued into the initiator */ - uint32_t queued_cmdsn; - /* - * Syncs up the scsi eh thread with the iscsi eh thread when sending - * task management functions. This must be taken before the session - * and recv lock. - */ - struct mutex eh_mutex; - - char *username; - char *username_in; - char *password; - char *password_in; - char *initiatorname; - /* hw address or netdev iscsi connection is bound to */ - char *hwaddress; - char *netdev; -#endif }; /* @@ -292,9 +271,11 @@ struct iscsi_session { extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); extern int iscsi_eh_abort(struct scsi_cmnd *sc); extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); +extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); extern int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)); + /* * iSCSI host helpers. */ @@ -309,10 +290,7 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost, */ extern struct iscsi_cls_session * iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, - int, int, uint32_t, uint32_t *); -extern struct iscsi_cls_session * -iscsi_session_setup2(struct iscsi_transport *, struct scsi_transport_template *, - uint16_t, uint16_t, int, int, uint32_t, uint32_t *); + uint16_t, uint16_t, int, int, uint32_t, uint32_t *); extern void iscsi_session_teardown(struct iscsi_cls_session *); extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); @@ -341,8 +319,7 @@ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, /* * pdu and task processing */ -extern int iscsi_check_assign_cmdsn(struct iscsi_session *, - struct iscsi_nopin *); +extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *); extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *, struct iscsi_data *hdr); extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, @@ -353,10 +330,7 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, char *, int); extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, uint32_t *); -extern void iscsi_free_mgmt_task(struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask); -extern void iscsi_update_cmdsn(struct iscsi_session *, - struct iscsi_nopin *);; +extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); /* * generic helpers diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index e6d1d735..05e25542 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -24,7 +24,7 @@ #define SCSI_TRANSPORT_ISCSI_H #include -#include +#include "iscsi_if.h" struct scsi_transport_template; struct iscsi_transport; @@ -79,7 +79,8 @@ struct iscsi_transport { char *name; unsigned int caps; /* LLD sets this to indicate what values it can export to sysfs */ - unsigned int param_mask; + uint64_t param_mask; + uint64_t host_param_mask; struct scsi_host_template *host_template; /* LLD connection data size */ int conndata_size; @@ -89,7 +90,8 @@ struct iscsi_transport { unsigned int max_conn; unsigned int max_cmd_len; struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, - struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); + struct scsi_transport_template *t, uint16_t, uint16_t, + uint32_t sn, uint32_t *hn); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); @@ -105,14 +107,18 @@ struct iscsi_transport { enum iscsi_param param, char *buf); int (*get_session_param) (struct iscsi_cls_session *session, enum iscsi_param param, char *buf); + int (*get_host_param) (struct Scsi_Host *shost, + enum iscsi_host_param param, char *buf); + int (*set_host_param) (struct Scsi_Host *shost, + enum iscsi_host_param param, char *buf, + int buflen); int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); void (*init_cmd_task) (struct iscsi_cmd_task *ctask); void (*init_mgmt_task) (struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask, - char *data, uint32_t data_size); + struct iscsi_mgmt_task *mtask); int (*xmit_cmd_task) (struct iscsi_conn *conn, struct iscsi_cmd_task *ctask); void (*cleanup_cmd_task) (struct iscsi_conn *conn, @@ -124,19 +130,8 @@ struct iscsi_transport { uint64_t *ep_handle); int (*ep_poll) (uint64_t ep_handle, int timeout_ms); void (*ep_disconnect) (uint64_t ep_handle); - int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no, + int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, uint32_t enable, struct sockaddr *dst_addr); -#ifndef __GENKSYMS__ - uint64_t host_param_mask; - int (*get_host_param) (struct Scsi_Host *shost, - enum iscsi_host_param param, char *buf); - int (*set_host_param) (struct Scsi_Host *shost, - enum iscsi_host_param param, char *buf, - int buflen); - struct iscsi_cls_session *(*create_session2) (struct iscsi_transport *i, - struct scsi_transport_template *t, uint16_t cmds_max, - uint16_t qdepth, uint32_t sn, uint32_t *hn); -#endif }; /* @@ -187,7 +182,7 @@ struct iscsi_cls_session { /* recovery fields */ int recovery_tmo; - struct work_struct recovery_work; + struct delayed_work recovery_work; int target_id;