aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-06-14 19:07:47 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2013-06-25 01:35:51 -0400
commit778de368964c5b7e8100cde9f549992d521e9c89 (patch)
tree5925e16a0fa2e29925f3ee44a0f00fc11d2afb4d
parent08234e3adc7a299c9213bcfa0b5e97c359129670 (diff)
iscsi/isert-target: Refactor ISCSI_OP_NOOP RX handling
This patch refactors ISCSI_OP_NOOP handling within iscsi-target in order to handle iscsi_nopout payloads in a transport specific manner. This includes splitting existing iscsit_handle_nop_out() into iscsit_setup_nop_out() and iscsit_process_nop_out() calls, and makes iscsit_handle_nop_out() be only used internally by traditional iscsi socket calls. Next update iser-target code to use new callers and add FIXME for the handling iscsi_nopout payloads. Also fix reject response handling in iscsit_setup_nop_out() to use proper iscsit_add_reject_from_cmd(). v2: Fix uninitialized iscsit_handle_nop_out() payload_length usage (Fengguang) v3: Remove left-over dead code in iscsit_setup_nop_out() (DanC) Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c23
-rw-r--r--drivers/target/iscsi/iscsi_target.c174
-rw-r--r--include/target/iscsi/iscsi_transport.h6
3 files changed, 115 insertions, 88 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 41712f096515..c48c9481025c 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1001,6 +1001,25 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
1001} 1001}
1002 1002
1003static int 1003static int
1004isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
1005 struct iser_rx_desc *rx_desc, unsigned char *buf)
1006{
1007 struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
1008 struct iscsi_conn *conn = isert_conn->conn;
1009 struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1010 int rc;
1011
1012 rc = iscsit_setup_nop_out(conn, cmd, hdr);
1013 if (rc < 0)
1014 return rc;
1015 /*
1016 * FIXME: Add support for NOPOUT payload using unsolicited RDMA payload
1017 */
1018
1019 return iscsit_process_nop_out(conn, cmd, hdr);
1020}
1021
1022static int
1004isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, 1023isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
1005 uint32_t read_stag, uint64_t read_va, 1024 uint32_t read_stag, uint64_t read_va,
1006 uint32_t write_stag, uint64_t write_va) 1025 uint32_t write_stag, uint64_t write_va)
@@ -1032,7 +1051,9 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
1032 if (!cmd) 1051 if (!cmd)
1033 break; 1052 break;
1034 1053
1035 ret = iscsit_handle_nop_out(conn, cmd, (unsigned char *)hdr); 1054 isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd);
1055 ret = isert_handle_nop_out(isert_conn, isert_cmd,
1056 rx_desc, (unsigned char *)hdr);
1036 break; 1057 break;
1037 case ISCSI_OP_SCSI_DATA_OUT: 1058 case ISCSI_OP_SCSI_DATA_OUT:
1038 ret = isert_handle_iscsi_dataout(isert_conn, rx_desc, 1059 ret = isert_handle_iscsi_dataout(isert_conn, rx_desc,
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index cc43d4163adc..f684627244bf 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1535,24 +1535,16 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1535 return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed); 1535 return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
1536} 1536}
1537 1537
1538int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, 1538int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1539 unsigned char *buf) 1539 struct iscsi_nopout *hdr)
1540{ 1540{
1541 unsigned char *ping_data = NULL; 1541 u32 payload_length = ntoh24(hdr->dlength);
1542 int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size;
1543 u32 checksum, data_crc, padding = 0, payload_length;
1544 struct iscsi_cmd *cmd_p = NULL;
1545 struct kvec *iov = NULL;
1546 struct iscsi_nopout *hdr;
1547
1548 hdr = (struct iscsi_nopout *) buf;
1549 payload_length = ntoh24(hdr->dlength);
1550 1542
1551 if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 1543 if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1552 pr_err("NOPOUT ITT is reserved, but Immediate Bit is" 1544 pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
1553 " not set, protocol error.\n"); 1545 " not set, protocol error.\n");
1554 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 1546 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
1555 buf, conn); 1547 1, 0, (unsigned char *)hdr, cmd);
1556 } 1548 }
1557 1549
1558 if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { 1550 if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
@@ -1560,8 +1552,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1560 " greater than MaxXmitDataSegmentLength: %u, protocol" 1552 " greater than MaxXmitDataSegmentLength: %u, protocol"
1561 " error.\n", payload_length, 1553 " error.\n", payload_length,
1562 conn->conn_ops->MaxXmitDataSegmentLength); 1554 conn->conn_ops->MaxXmitDataSegmentLength);
1563 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 1555 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
1564 buf, conn); 1556 1, 0, (unsigned char *)hdr, cmd);
1565 } 1557 }
1566 1558
1567 pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," 1559 pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
@@ -1577,11 +1569,6 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1577 * can contain ping data. 1569 * can contain ping data.
1578 */ 1570 */
1579 if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { 1571 if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1580 if (!cmd)
1581 return iscsit_add_reject(
1582 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1583 1, buf, conn);
1584
1585 cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT; 1572 cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT;
1586 cmd->i_state = ISTATE_SEND_NOPIN; 1573 cmd->i_state = ISTATE_SEND_NOPIN;
1587 cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1574 cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
@@ -1593,8 +1580,87 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1593 cmd->data_direction = DMA_NONE; 1580 cmd->data_direction = DMA_NONE;
1594 } 1581 }
1595 1582
1583 return 0;
1584}
1585EXPORT_SYMBOL(iscsit_setup_nop_out);
1586
1587int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1588 struct iscsi_nopout *hdr)
1589{
1590 struct iscsi_cmd *cmd_p = NULL;
1591 int cmdsn_ret = 0;
1592 /*
1593 * Initiator is expecting a NopIN ping reply..
1594 */
1595 if (hdr->itt != RESERVED_ITT) {
1596 BUG_ON(!cmd);
1597
1598 spin_lock_bh(&conn->cmd_lock);
1599 list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1600 spin_unlock_bh(&conn->cmd_lock);
1601
1602 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1603
1604 if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1605 iscsit_add_cmd_to_response_queue(cmd, conn,
1606 cmd->i_state);
1607 return 0;
1608 }
1609
1610 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
1611 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1612 return 0;
1613
1614 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1615 return iscsit_add_reject_from_cmd(
1616 ISCSI_REASON_PROTOCOL_ERROR,
1617 1, 0, (unsigned char *)hdr, cmd);
1618
1619 return 0;
1620 }
1621 /*
1622 * This was a response to a unsolicited NOPIN ping.
1623 */
1624 if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1625 cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1626 if (!cmd_p)
1627 return -EINVAL;
1628
1629 iscsit_stop_nopin_response_timer(conn);
1630
1631 cmd_p->i_state = ISTATE_REMOVE;
1632 iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1633
1634 iscsit_start_nopin_timer(conn);
1635 return 0;
1636 }
1637 /*
1638 * Otherwise, initiator is not expecting a NOPIN is response.
1639 * Just ignore for now.
1640 */
1641 return 0;
1642}
1643EXPORT_SYMBOL(iscsit_process_nop_out);
1644
1645static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1646 unsigned char *buf)
1647{
1648 unsigned char *ping_data = NULL;
1649 struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
1650 struct kvec *iov = NULL;
1651 u32 payload_length = ntoh24(hdr->dlength);
1652 int ret;
1653
1654 ret = iscsit_setup_nop_out(conn, cmd, hdr);
1655 if (ret < 0)
1656 return ret;
1657 /*
1658 * Handle NOP-OUT payload for traditional iSCSI sockets
1659 */
1596 if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { 1660 if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1597 rx_size = payload_length; 1661 u32 checksum, data_crc, padding = 0;
1662 int niov = 0, rx_got, rx_size = payload_length;
1663
1598 ping_data = kzalloc(payload_length + 1, GFP_KERNEL); 1664 ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
1599 if (!ping_data) { 1665 if (!ping_data) {
1600 pr_err("Unable to allocate memory for" 1666 pr_err("Unable to allocate memory for"
@@ -1673,76 +1739,14 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1673 pr_debug("Ping Data: \"%s\"\n", ping_data); 1739 pr_debug("Ping Data: \"%s\"\n", ping_data);
1674 } 1740 }
1675 1741
1676 if (hdr->itt != RESERVED_ITT) { 1742 return iscsit_process_nop_out(conn, cmd, hdr);
1677 if (!cmd) {
1678 pr_err("Checking CmdSN for NOPOUT,"
1679 " but cmd is NULL!\n");
1680 return -1;
1681 }
1682 /*
1683 * Initiator is expecting a NopIN ping reply,
1684 */
1685 spin_lock_bh(&conn->cmd_lock);
1686 list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
1687 spin_unlock_bh(&conn->cmd_lock);
1688
1689 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1690
1691 if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
1692 iscsit_add_cmd_to_response_queue(cmd, conn,
1693 cmd->i_state);
1694 return 0;
1695 }
1696
1697 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
1698 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1699 ret = 0;
1700 goto ping_out;
1701 }
1702 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1703 return iscsit_add_reject_from_cmd(
1704 ISCSI_REASON_PROTOCOL_ERROR,
1705 1, 0, buf, cmd);
1706
1707 return 0;
1708 }
1709
1710 if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
1711 /*
1712 * This was a response to a unsolicited NOPIN ping.
1713 */
1714 cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1715 if (!cmd_p)
1716 return -1;
1717
1718 iscsit_stop_nopin_response_timer(conn);
1719
1720 cmd_p->i_state = ISTATE_REMOVE;
1721 iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1722 iscsit_start_nopin_timer(conn);
1723 } else {
1724 /*
1725 * Initiator is not expecting a NOPIN is response.
1726 * Just ignore for now.
1727 *
1728 * iSCSI v19-91 10.18
1729 * "A NOP-OUT may also be used to confirm a changed
1730 * ExpStatSN if another PDU will not be available
1731 * for a long time."
1732 */
1733 ret = 0;
1734 goto out;
1735 }
1736
1737 return 0;
1738out: 1743out:
1739 if (cmd) 1744 if (cmd)
1740 iscsit_free_cmd(cmd, false); 1745 iscsit_free_cmd(cmd, false);
1741ping_out: 1746
1742 kfree(ping_data); 1747 kfree(ping_data);
1743 return ret; 1748 return ret;
1744} 1749}
1745EXPORT_SYMBOL(iscsit_handle_nop_out);
1746 1750
1747int 1751int
1748iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, 1752iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index 23a87d0cd72c..ecb53ea6d1c7 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -45,8 +45,10 @@ extern int iscsit_check_dataout_hdr(struct iscsi_conn *, unsigned char *,
45 struct iscsi_cmd **); 45 struct iscsi_cmd **);
46extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *, 46extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *,
47 bool); 47 bool);
48extern int iscsit_handle_nop_out(struct iscsi_conn *, struct iscsi_cmd *, 48extern int iscsit_setup_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
49 unsigned char *); 49 struct iscsi_nopout *);
50extern int iscsit_process_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
51 struct iscsi_nopout *);
50extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *, 52extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *,
51 unsigned char *); 53 unsigned char *);
52extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *, 54extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *,