Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[linux-drm-fsl-dcu.git] / drivers / target / iscsi / iscsi_target.c
index 38e44b9abf0f145eacde1e9b90dcf26c45ca2633..d70e9119e906cba0c0f38da61948ce745bc5d6e5 100644 (file)
@@ -805,14 +805,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        int iscsi_task_attr;
        int sam_task_attr;
 
-       spin_lock_bh(&conn->sess->session_stats_lock);
-       conn->sess->cmd_pdus++;
-       if (conn->sess->se_sess->se_node_acl) {
-               spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
-               conn->sess->se_sess->se_node_acl->num_cmds++;
-               spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
-       }
-       spin_unlock_bh(&conn->sess->session_stats_lock);
+       atomic_long_inc(&conn->sess->cmd_pdus);
 
        hdr                     = (struct iscsi_scsi_req *) buf;
        payload_length          = ntoh24(hdr->dlength);
@@ -1254,20 +1247,12 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
        int rc;
 
        if (!payload_length) {
-               pr_err("DataOUT payload is ZERO, protocol error.\n");
-               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
-                                        buf);
+               pr_warn("DataOUT payload is ZERO, ignoring.\n");
+               return 0;
        }
 
        /* iSCSI write */
-       spin_lock_bh(&conn->sess->session_stats_lock);
-       conn->sess->rx_data_octets += payload_length;
-       if (conn->sess->se_sess->se_node_acl) {
-               spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
-               conn->sess->se_sess->se_node_acl->write_bytes += payload_length;
-               spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
-       }
-       spin_unlock_bh(&conn->sess->session_stats_lock);
+       atomic_long_add(payload_length, &conn->sess->rx_data_octets);
 
        if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("DataSegmentLength: %u is greater than"
@@ -1486,7 +1471,7 @@ EXPORT_SYMBOL(iscsit_check_dataout_payload);
 
 static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 {
-       struct iscsi_cmd *cmd;
+       struct iscsi_cmd *cmd = NULL;
        struct iscsi_data *hdr = (struct iscsi_data *)buf;
        int rc;
        bool data_crc_failed = false;
@@ -1954,6 +1939,13 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                                         (unsigned char *)hdr);
        }
 
+       if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
+            (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
+               pr_err("Multi sequence text commands currently not supported\n");
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
+                                       (unsigned char *)hdr);
+       }
+
        pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
                " ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
                hdr->exp_statsn, payload_length);
@@ -2630,14 +2622,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
                return -1;
        }
 
-       spin_lock_bh(&conn->sess->session_stats_lock);
-       conn->sess->tx_data_octets += datain.length;
-       if (conn->sess->se_sess->se_node_acl) {
-               spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
-               conn->sess->se_sess->se_node_acl->read_bytes += datain.length;
-               spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
-       }
-       spin_unlock_bh(&conn->sess->session_stats_lock);
+       atomic_long_add(datain.length, &conn->sess->tx_data_octets);
        /*
         * Special case for successfully execution w/ both DATAIN
         * and Sense Data.
@@ -3162,9 +3147,7 @@ void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
        if (inc_stat_sn)
                cmd->stat_sn = conn->stat_sn++;
 
-       spin_lock_bh(&conn->sess->session_stats_lock);
-       conn->sess->rsp_pdus++;
-       spin_unlock_bh(&conn->sess->session_stats_lock);
+       atomic_long_inc(&conn->sess->rsp_pdus);
 
        memset(hdr, 0, ISCSI_HDR_LEN);
        hdr->opcode             = ISCSI_OP_SCSI_CMD_RSP;
@@ -3374,6 +3357,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
        struct iscsi_tiqn *tiqn;
        struct iscsi_tpg_np *tpg_np;
        int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
+       int target_name_printed;
        unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
        unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
 
@@ -3411,19 +3395,23 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                        continue;
                }
 
-               len = sprintf(buf, "TargetName=%s", tiqn->tiqn);
-               len += 1;
-
-               if ((len + payload_len) > buffer_len) {
-                       end_of_buf = 1;
-                       goto eob;
-               }
-               memcpy(payload + payload_len, buf, len);
-               payload_len += len;
+               target_name_printed = 0;
 
                spin_lock(&tiqn->tiqn_tpg_lock);
                list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
 
+                       /* If demo_mode_discovery=0 and generate_node_acls=0
+                        * (demo mode dislabed) do not return
+                        * TargetName+TargetAddress unless a NodeACL exists.
+                        */
+
+                       if ((tpg->tpg_attrib.generate_node_acls == 0) &&
+                           (tpg->tpg_attrib.demo_mode_discovery == 0) &&
+                           (!core_tpg_get_initiator_node_acl(&tpg->tpg_se_tpg,
+                               cmd->conn->sess->sess_ops->InitiatorName))) {
+                               continue;
+                       }
+
                        spin_lock(&tpg->tpg_state_lock);
                        if ((tpg->tpg_state == TPG_STATE_FREE) ||
                            (tpg->tpg_state == TPG_STATE_INACTIVE)) {
@@ -3438,6 +3426,22 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                                struct iscsi_np *np = tpg_np->tpg_np;
                                bool inaddr_any = iscsit_check_inaddr_any(np);
 
+                               if (!target_name_printed) {
+                                       len = sprintf(buf, "TargetName=%s",
+                                                     tiqn->tiqn);
+                                       len += 1;
+
+                                       if ((len + payload_len) > buffer_len) {
+                                               spin_unlock(&tpg->tpg_np_lock);
+                                               spin_unlock(&tiqn->tiqn_tpg_lock);
+                                               end_of_buf = 1;
+                                               goto eob;
+                                       }
+                                       memcpy(payload + payload_len, buf, len);
+                                       payload_len += len;
+                                       target_name_printed = 1;
+                               }
+
                                len = sprintf(buf, "TargetAddress="
                                        "%s:%hu,%hu",
                                        (inaddr_any == false) ?
@@ -4092,9 +4096,7 @@ restart:
                                 * hit default in the switch below.
                                 */
                                memset(buffer, 0xff, ISCSI_HDR_LEN);
-                               spin_lock_bh(&conn->sess->session_stats_lock);
-                               conn->sess->conn_digest_errors++;
-                               spin_unlock_bh(&conn->sess->session_stats_lock);
+                               atomic_long_inc(&conn->sess->conn_digest_errors);
                        } else {
                                pr_debug("Got HeaderDigest CRC32C"
                                                " 0x%08x\n", checksum);
@@ -4381,7 +4383,7 @@ int iscsit_close_connection(
 
 int iscsit_close_session(struct iscsi_session *sess)
 {
-       struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
+       struct iscsi_portal_group *tpg = sess->tpg;
        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
 
        if (atomic_read(&sess->nconn)) {