mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"The highlights this round include:
- Update vhost-scsi to support F_ANY_LAYOUT using mm/iov_iter.c
logic, and signal VERSION_1 support (MST + Viro + nab)
- Fix iscsi/iser-target to remove problematic active_ts_set usage
(Gavin Guo)
- Update iscsi/iser-target to support multi-sequence sendtargets
(Sagi)
- Fix original PR_APTPL_BUF_LEN 8k size limitation (Martin Svec)
- Add missing WRITE_SAME end-of-device sanity check (Bart)
- Check for LBA + sectors wrap-around in sbc_parse_cdb() (nab)
- Other various minor SPC/SBC compliance fixes based upon Ronnie
Sahlberg test suite (nab)"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (32 commits)
target: Set LBPWS10 bit in Logical Block Provisioning EVPD
target: Fail UNMAP when emulate_tpu=0
target: Fail WRITE_SAME w/ UNMAP=1 when emulate_tpws=0
target: Add sanity checks for DPO/FUA bit usage
target: Perform PROTECT sanity checks for WRITE_SAME
target: Fail I/O with PROTECT bit when protection is unsupported
target: Check for LBA + sectors wrap-around in sbc_parse_cdb
target: Add missing WRITE_SAME end-of-device sanity check
iscsi-target: Avoid IN_LOGOUT failure case for iser-target
target: Fix PR_APTPL_BUF_LEN buffer size limitation
iscsi-target: Drop problematic active_ts_list usage
iscsi/iser-target: Support multi-sequence sendtargets text response
iser-target: Remove duplicate function names
vhost/scsi: potential memory corruption
vhost/scsi: Global tcm_vhost -> vhost_scsi rename
vhost/scsi: Drop left-over scsi_tcq.h include
vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits
vhost/scsi: Add ANY_LAYOUT support in vhost_scsi_handle_vq
vhost/scsi: Add ANY_LAYOUT iov -> sgl mapping prerequisites
vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len
...
This commit is contained in:
commit
e20d3ef540
32 changed files with 829 additions and 689 deletions
|
|
@ -30,7 +30,7 @@
|
|||
#include <target/target_core_fabric.h>
|
||||
#include <target/target_core_configfs.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_tq.h"
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
|
|
@ -968,11 +968,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
|
||||
conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
|
||||
if (hdr->flags & ISCSI_FLAG_CMD_READ) {
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF)
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
} else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
|
||||
cmd->targ_xfer_tag = 0xFFFFFFFF;
|
||||
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
|
||||
|
|
@ -1998,6 +1994,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
|
||||
cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
|
||||
cmd->data_direction = DMA_NONE;
|
||||
cmd->text_in_ptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2011,9 +2008,13 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
int cmdsn_ret;
|
||||
|
||||
if (!text_in) {
|
||||
pr_err("Unable to locate text_in buffer for sendtargets"
|
||||
" discovery\n");
|
||||
goto reject;
|
||||
cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
|
||||
pr_err("Unable to locate text_in buffer for sendtargets"
|
||||
" discovery\n");
|
||||
goto reject;
|
||||
}
|
||||
goto empty_sendtargets;
|
||||
}
|
||||
if (strncmp("SendTargets", text_in, 11) != 0) {
|
||||
pr_err("Received Text Data that is not"
|
||||
|
|
@ -2040,6 +2041,7 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
empty_sendtargets:
|
||||
iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
|
||||
|
||||
if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
|
||||
|
|
@ -3047,11 +3049,7 @@ static int iscsit_send_r2t(
|
|||
int_to_scsilun(cmd->se_cmd.orig_fe_lun,
|
||||
(struct scsi_lun *)&hdr->lun);
|
||||
hdr->itt = cmd->init_task_tag;
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
r2t->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
if (r2t->targ_xfer_tag == 0xFFFFFFFF)
|
||||
r2t->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag);
|
||||
hdr->statsn = cpu_to_be32(conn->stat_sn);
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
|
|
@ -3393,7 +3391,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
|
|||
|
||||
static int
|
||||
iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
enum iscsit_transport_type network_transport)
|
||||
enum iscsit_transport_type network_transport,
|
||||
int skip_bytes, bool *completed)
|
||||
{
|
||||
char *payload = NULL;
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
|
|
@ -3405,7 +3404,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
|||
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
|
||||
unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
|
||||
|
||||
buffer_len = max(conn->conn_ops->MaxRecvDataSegmentLength,
|
||||
buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
|
||||
SENDTARGETS_BUF_LIMIT);
|
||||
|
||||
payload = kzalloc(buffer_len, GFP_KERNEL);
|
||||
|
|
@ -3484,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
|||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
target_name_printed = 1;
|
||||
|
||||
if (skip_bytes && len <= skip_bytes) {
|
||||
skip_bytes -= len;
|
||||
} else {
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
target_name_printed = 1;
|
||||
if (len > skip_bytes)
|
||||
skip_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
len = sprintf(buf, "TargetAddress="
|
||||
|
|
@ -3502,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
|||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
|
||||
if (skip_bytes && len <= skip_bytes) {
|
||||
skip_bytes -= len;
|
||||
} else {
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
if (len > skip_bytes)
|
||||
skip_bytes = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock(&tpg->tpg_np_lock);
|
||||
}
|
||||
spin_unlock(&tiqn->tiqn_tpg_lock);
|
||||
eob:
|
||||
if (end_of_buf)
|
||||
if (end_of_buf) {
|
||||
*completed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
|
||||
break;
|
||||
|
|
@ -3528,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
|||
enum iscsit_transport_type network_transport)
|
||||
{
|
||||
int text_length, padding;
|
||||
bool completed = true;
|
||||
|
||||
text_length = iscsit_build_sendtargets_response(cmd, network_transport);
|
||||
text_length = iscsit_build_sendtargets_response(cmd, network_transport,
|
||||
cmd->read_data_done,
|
||||
&completed);
|
||||
if (text_length < 0)
|
||||
return text_length;
|
||||
|
||||
if (completed) {
|
||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||
} else {
|
||||
hdr->flags |= ISCSI_FLAG_TEXT_CONTINUE;
|
||||
cmd->read_data_done += text_length;
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF)
|
||||
cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
}
|
||||
hdr->opcode = ISCSI_OP_TEXT_RSP;
|
||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||
padding = ((-text_length) & 3);
|
||||
hton24(hdr->dlength, text_length);
|
||||
hdr->itt = cmd->init_task_tag;
|
||||
|
|
@ -3543,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
|||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
||||
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
/*
|
||||
* Reset maxcmdsn_inc in multi-part text payload exchanges to
|
||||
* correctly increment MaxCmdSN for each response answering a
|
||||
* non immediate text request with a valid CmdSN.
|
||||
*/
|
||||
cmd->maxcmdsn_inc = 0;
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||
|
||||
pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn,
|
||||
text_length, conn->cid);
|
||||
pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
|
||||
cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
|
||||
!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
|
||||
!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
|
||||
|
||||
return text_length + padding;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_build_text_rsp);
|
||||
|
||||
/*
|
||||
* FIXME: Add support for F_BIT and C_BIT when the length is longer than
|
||||
* MaxRecvDataSegmentLength.
|
||||
*/
|
||||
static int iscsit_send_text_rsp(
|
||||
struct iscsi_cmd *cmd,
|
||||
struct iscsi_conn *conn)
|
||||
|
|
@ -4021,9 +4050,15 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
|
|||
ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
|
||||
break;
|
||||
case ISCSI_OP_TEXT:
|
||||
cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
|
||||
if (!cmd)
|
||||
goto reject;
|
||||
if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
|
||||
cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
|
||||
if (!cmd)
|
||||
goto reject;
|
||||
} else {
|
||||
cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
|
||||
if (!cmd)
|
||||
goto reject;
|
||||
}
|
||||
|
||||
ret = iscsit_handle_text_cmd(conn, cmd, buf);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_nego.h"
|
||||
#include "iscsi_target_auth.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include <target/configfs_macros.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
#include "iscsi_target_configfs.h"
|
||||
|
||||
struct target_fabric_configfs *lio_target_fabric_configfs;
|
||||
|
|
@ -674,12 +674,9 @@ static ssize_t lio_target_nacl_show_info(
|
|||
rb += sprintf(page+rb, "InitiatorAlias: %s\n",
|
||||
sess->sess_ops->InitiatorAlias);
|
||||
|
||||
rb += sprintf(page+rb, "LIO Session ID: %u "
|
||||
"ISID: 0x%02x %02x %02x %02x %02x %02x "
|
||||
"TSIH: %hu ", sess->sid,
|
||||
sess->isid[0], sess->isid[1], sess->isid[2],
|
||||
sess->isid[3], sess->isid[4], sess->isid[5],
|
||||
sess->tsih);
|
||||
rb += sprintf(page+rb,
|
||||
"LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ",
|
||||
sess->sid, sess->isid, sess->tsih);
|
||||
rb += sprintf(page+rb, "SessionType: %s\n",
|
||||
(sess->sess_ops->SessionType) ?
|
||||
"Discovery" : "Normal");
|
||||
|
|
@ -1758,9 +1755,7 @@ static u32 lio_sess_get_initiator_sid(
|
|||
/*
|
||||
* iSCSI Initiator Session Identifier from RFC-3720.
|
||||
*/
|
||||
return snprintf(buf, size, "%02x%02x%02x%02x%02x%02x",
|
||||
sess->isid[0], sess->isid[1], sess->isid[2],
|
||||
sess->isid[3], sess->isid[4], sess->isid[5]);
|
||||
return snprintf(buf, size, "%6phN", sess->isid);
|
||||
}
|
||||
|
||||
static int lio_queue_data_in(struct se_cmd *se_cmd)
|
||||
|
|
|
|||
|
|
@ -1,883 +0,0 @@
|
|||
#ifndef ISCSI_TARGET_CORE_H
|
||||
#define ISCSI_TARGET_CORE_H
|
||||
|
||||
#include <linux/in.h>
|
||||
#include <linux/configfs.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/iscsi_proto.h>
|
||||
#include <target/target_core_base.h>
|
||||
|
||||
#define ISCSIT_VERSION "v4.1.0"
|
||||
#define ISCSI_MAX_DATASN_MISSING_COUNT 16
|
||||
#define ISCSI_TX_THREAD_TCP_TIMEOUT 2
|
||||
#define ISCSI_RX_THREAD_TCP_TIMEOUT 2
|
||||
#define SECONDS_FOR_ASYNC_LOGOUT 10
|
||||
#define SECONDS_FOR_ASYNC_TEXT 10
|
||||
#define SECONDS_FOR_LOGOUT_COMP 15
|
||||
#define WHITE_SPACE " \t\v\f\n\r"
|
||||
#define ISCSIT_MIN_TAGS 16
|
||||
#define ISCSIT_EXTRA_TAGS 8
|
||||
#define ISCSIT_TCP_BACKLOG 256
|
||||
|
||||
/* struct iscsi_node_attrib sanity values */
|
||||
#define NA_DATAOUT_TIMEOUT 3
|
||||
#define NA_DATAOUT_TIMEOUT_MAX 60
|
||||
#define NA_DATAOUT_TIMEOUT_MIX 2
|
||||
#define NA_DATAOUT_TIMEOUT_RETRIES 5
|
||||
#define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15
|
||||
#define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1
|
||||
#define NA_NOPIN_TIMEOUT 15
|
||||
#define NA_NOPIN_TIMEOUT_MAX 60
|
||||
#define NA_NOPIN_TIMEOUT_MIN 3
|
||||
#define NA_NOPIN_RESPONSE_TIMEOUT 30
|
||||
#define NA_NOPIN_RESPONSE_TIMEOUT_MAX 60
|
||||
#define NA_NOPIN_RESPONSE_TIMEOUT_MIN 3
|
||||
#define NA_RANDOM_DATAIN_PDU_OFFSETS 0
|
||||
#define NA_RANDOM_DATAIN_SEQ_OFFSETS 0
|
||||
#define NA_RANDOM_R2T_OFFSETS 0
|
||||
|
||||
/* struct iscsi_tpg_attrib sanity values */
|
||||
#define TA_AUTHENTICATION 1
|
||||
#define TA_LOGIN_TIMEOUT 15
|
||||
#define TA_LOGIN_TIMEOUT_MAX 30
|
||||
#define TA_LOGIN_TIMEOUT_MIN 5
|
||||
#define TA_NETIF_TIMEOUT 2
|
||||
#define TA_NETIF_TIMEOUT_MAX 15
|
||||
#define TA_NETIF_TIMEOUT_MIN 2
|
||||
#define TA_GENERATE_NODE_ACLS 0
|
||||
#define TA_DEFAULT_CMDSN_DEPTH 64
|
||||
#define TA_DEFAULT_CMDSN_DEPTH_MAX 512
|
||||
#define TA_DEFAULT_CMDSN_DEPTH_MIN 1
|
||||
#define TA_CACHE_DYNAMIC_ACLS 0
|
||||
/* Enabled by default in demo mode (generic_node_acls=1) */
|
||||
#define TA_DEMO_MODE_WRITE_PROTECT 1
|
||||
/* Disabled by default in production mode w/ explict ACLs */
|
||||
#define TA_PROD_MODE_WRITE_PROTECT 0
|
||||
#define TA_DEMO_MODE_DISCOVERY 1
|
||||
#define TA_DEFAULT_ERL 0
|
||||
#define TA_CACHE_CORE_NPS 0
|
||||
/* T10 protection information disabled by default */
|
||||
#define TA_DEFAULT_T10_PI 0
|
||||
|
||||
#define ISCSI_IOV_DATA_BUFFER 5
|
||||
|
||||
enum iscsit_transport_type {
|
||||
ISCSI_TCP = 0,
|
||||
ISCSI_SCTP_TCP = 1,
|
||||
ISCSI_SCTP_UDP = 2,
|
||||
ISCSI_IWARP_TCP = 3,
|
||||
ISCSI_IWARP_SCTP = 4,
|
||||
ISCSI_INFINIBAND = 5,
|
||||
};
|
||||
|
||||
/* RFC-3720 7.1.4 Standard Connection State Diagram for a Target */
|
||||
enum target_conn_state_table {
|
||||
TARG_CONN_STATE_FREE = 0x1,
|
||||
TARG_CONN_STATE_XPT_UP = 0x3,
|
||||
TARG_CONN_STATE_IN_LOGIN = 0x4,
|
||||
TARG_CONN_STATE_LOGGED_IN = 0x5,
|
||||
TARG_CONN_STATE_IN_LOGOUT = 0x6,
|
||||
TARG_CONN_STATE_LOGOUT_REQUESTED = 0x7,
|
||||
TARG_CONN_STATE_CLEANUP_WAIT = 0x8,
|
||||
};
|
||||
|
||||
/* RFC-3720 7.3.2 Session State Diagram for a Target */
|
||||
enum target_sess_state_table {
|
||||
TARG_SESS_STATE_FREE = 0x1,
|
||||
TARG_SESS_STATE_ACTIVE = 0x2,
|
||||
TARG_SESS_STATE_LOGGED_IN = 0x3,
|
||||
TARG_SESS_STATE_FAILED = 0x4,
|
||||
TARG_SESS_STATE_IN_CONTINUE = 0x5,
|
||||
};
|
||||
|
||||
/* struct iscsi_data_count->type */
|
||||
enum data_count_type {
|
||||
ISCSI_RX_DATA = 1,
|
||||
ISCSI_TX_DATA = 2,
|
||||
};
|
||||
|
||||
/* struct iscsi_datain_req->dr_complete */
|
||||
enum datain_req_comp_table {
|
||||
DATAIN_COMPLETE_NORMAL = 1,
|
||||
DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY = 2,
|
||||
DATAIN_COMPLETE_CONNECTION_RECOVERY = 3,
|
||||
};
|
||||
|
||||
/* struct iscsi_datain_req->recovery */
|
||||
enum datain_req_rec_table {
|
||||
DATAIN_WITHIN_COMMAND_RECOVERY = 1,
|
||||
DATAIN_CONNECTION_RECOVERY = 2,
|
||||
};
|
||||
|
||||
/* struct iscsi_portal_group->state */
|
||||
enum tpg_state_table {
|
||||
TPG_STATE_FREE = 0,
|
||||
TPG_STATE_ACTIVE = 1,
|
||||
TPG_STATE_INACTIVE = 2,
|
||||
TPG_STATE_COLD_RESET = 3,
|
||||
};
|
||||
|
||||
/* struct iscsi_tiqn->tiqn_state */
|
||||
enum tiqn_state_table {
|
||||
TIQN_STATE_ACTIVE = 1,
|
||||
TIQN_STATE_SHUTDOWN = 2,
|
||||
};
|
||||
|
||||
/* struct iscsi_cmd->cmd_flags */
|
||||
enum cmd_flags_table {
|
||||
ICF_GOT_LAST_DATAOUT = 0x00000001,
|
||||
ICF_GOT_DATACK_SNACK = 0x00000002,
|
||||
ICF_NON_IMMEDIATE_UNSOLICITED_DATA = 0x00000004,
|
||||
ICF_SENT_LAST_R2T = 0x00000008,
|
||||
ICF_WITHIN_COMMAND_RECOVERY = 0x00000010,
|
||||
ICF_CONTIG_MEMORY = 0x00000020,
|
||||
ICF_ATTACHED_TO_RQUEUE = 0x00000040,
|
||||
ICF_OOO_CMDSN = 0x00000080,
|
||||
ICF_SENDTARGETS_ALL = 0x00000100,
|
||||
ICF_SENDTARGETS_SINGLE = 0x00000200,
|
||||
};
|
||||
|
||||
/* struct iscsi_cmd->i_state */
|
||||
enum cmd_i_state_table {
|
||||
ISTATE_NO_STATE = 0,
|
||||
ISTATE_NEW_CMD = 1,
|
||||
ISTATE_DEFERRED_CMD = 2,
|
||||
ISTATE_UNSOLICITED_DATA = 3,
|
||||
ISTATE_RECEIVE_DATAOUT = 4,
|
||||
ISTATE_RECEIVE_DATAOUT_RECOVERY = 5,
|
||||
ISTATE_RECEIVED_LAST_DATAOUT = 6,
|
||||
ISTATE_WITHIN_DATAOUT_RECOVERY = 7,
|
||||
ISTATE_IN_CONNECTION_RECOVERY = 8,
|
||||
ISTATE_RECEIVED_TASKMGT = 9,
|
||||
ISTATE_SEND_ASYNCMSG = 10,
|
||||
ISTATE_SENT_ASYNCMSG = 11,
|
||||
ISTATE_SEND_DATAIN = 12,
|
||||
ISTATE_SEND_LAST_DATAIN = 13,
|
||||
ISTATE_SENT_LAST_DATAIN = 14,
|
||||
ISTATE_SEND_LOGOUTRSP = 15,
|
||||
ISTATE_SENT_LOGOUTRSP = 16,
|
||||
ISTATE_SEND_NOPIN = 17,
|
||||
ISTATE_SENT_NOPIN = 18,
|
||||
ISTATE_SEND_REJECT = 19,
|
||||
ISTATE_SENT_REJECT = 20,
|
||||
ISTATE_SEND_R2T = 21,
|
||||
ISTATE_SENT_R2T = 22,
|
||||
ISTATE_SEND_R2T_RECOVERY = 23,
|
||||
ISTATE_SENT_R2T_RECOVERY = 24,
|
||||
ISTATE_SEND_LAST_R2T = 25,
|
||||
ISTATE_SENT_LAST_R2T = 26,
|
||||
ISTATE_SEND_LAST_R2T_RECOVERY = 27,
|
||||
ISTATE_SENT_LAST_R2T_RECOVERY = 28,
|
||||
ISTATE_SEND_STATUS = 29,
|
||||
ISTATE_SEND_STATUS_BROKEN_PC = 30,
|
||||
ISTATE_SENT_STATUS = 31,
|
||||
ISTATE_SEND_STATUS_RECOVERY = 32,
|
||||
ISTATE_SENT_STATUS_RECOVERY = 33,
|
||||
ISTATE_SEND_TASKMGTRSP = 34,
|
||||
ISTATE_SENT_TASKMGTRSP = 35,
|
||||
ISTATE_SEND_TEXTRSP = 36,
|
||||
ISTATE_SENT_TEXTRSP = 37,
|
||||
ISTATE_SEND_NOPIN_WANT_RESPONSE = 38,
|
||||
ISTATE_SENT_NOPIN_WANT_RESPONSE = 39,
|
||||
ISTATE_SEND_NOPIN_NO_RESPONSE = 40,
|
||||
ISTATE_REMOVE = 41,
|
||||
ISTATE_FREE = 42,
|
||||
};
|
||||
|
||||
/* Used for iscsi_recover_cmdsn() return values */
|
||||
enum recover_cmdsn_ret_table {
|
||||
CMDSN_ERROR_CANNOT_RECOVER = -1,
|
||||
CMDSN_NORMAL_OPERATION = 0,
|
||||
CMDSN_LOWER_THAN_EXP = 1,
|
||||
CMDSN_HIGHER_THAN_EXP = 2,
|
||||
CMDSN_MAXCMDSN_OVERRUN = 3,
|
||||
};
|
||||
|
||||
/* Used for iscsi_handle_immediate_data() return values */
|
||||
enum immedate_data_ret_table {
|
||||
IMMEDIATE_DATA_CANNOT_RECOVER = -1,
|
||||
IMMEDIATE_DATA_NORMAL_OPERATION = 0,
|
||||
IMMEDIATE_DATA_ERL1_CRC_FAILURE = 1,
|
||||
};
|
||||
|
||||
/* Used for iscsi_decide_dataout_action() return values */
|
||||
enum dataout_action_ret_table {
|
||||
DATAOUT_CANNOT_RECOVER = -1,
|
||||
DATAOUT_NORMAL = 0,
|
||||
DATAOUT_SEND_R2T = 1,
|
||||
DATAOUT_SEND_TO_TRANSPORT = 2,
|
||||
DATAOUT_WITHIN_COMMAND_RECOVERY = 3,
|
||||
};
|
||||
|
||||
/* Used for struct iscsi_node_auth->naf_flags */
|
||||
enum naf_flags_table {
|
||||
NAF_USERID_SET = 0x01,
|
||||
NAF_PASSWORD_SET = 0x02,
|
||||
NAF_USERID_IN_SET = 0x04,
|
||||
NAF_PASSWORD_IN_SET = 0x08,
|
||||
};
|
||||
|
||||
/* Used by various struct timer_list to manage iSCSI specific state */
|
||||
enum iscsi_timer_flags_table {
|
||||
ISCSI_TF_RUNNING = 0x01,
|
||||
ISCSI_TF_STOP = 0x02,
|
||||
ISCSI_TF_EXPIRED = 0x04,
|
||||
};
|
||||
|
||||
/* Used for struct iscsi_np->np_flags */
|
||||
enum np_flags_table {
|
||||
NPF_IP_NETWORK = 0x00,
|
||||
};
|
||||
|
||||
/* Used for struct iscsi_np->np_thread_state */
|
||||
enum np_thread_state_table {
|
||||
ISCSI_NP_THREAD_ACTIVE = 1,
|
||||
ISCSI_NP_THREAD_INACTIVE = 2,
|
||||
ISCSI_NP_THREAD_RESET = 3,
|
||||
ISCSI_NP_THREAD_SHUTDOWN = 4,
|
||||
ISCSI_NP_THREAD_EXIT = 5,
|
||||
};
|
||||
|
||||
struct iscsi_conn_ops {
|
||||
u8 HeaderDigest; /* [0,1] == [None,CRC32C] */
|
||||
u8 DataDigest; /* [0,1] == [None,CRC32C] */
|
||||
u32 MaxRecvDataSegmentLength; /* [512..2**24-1] */
|
||||
u32 MaxXmitDataSegmentLength; /* [512..2**24-1] */
|
||||
u8 OFMarker; /* [0,1] == [No,Yes] */
|
||||
u8 IFMarker; /* [0,1] == [No,Yes] */
|
||||
u32 OFMarkInt; /* [1..65535] */
|
||||
u32 IFMarkInt; /* [1..65535] */
|
||||
/*
|
||||
* iSER specific connection parameters
|
||||
*/
|
||||
u32 InitiatorRecvDataSegmentLength; /* [512..2**24-1] */
|
||||
u32 TargetRecvDataSegmentLength; /* [512..2**24-1] */
|
||||
};
|
||||
|
||||
struct iscsi_sess_ops {
|
||||
char InitiatorName[224];
|
||||
char InitiatorAlias[256];
|
||||
char TargetName[224];
|
||||
char TargetAlias[256];
|
||||
char TargetAddress[256];
|
||||
u16 TargetPortalGroupTag; /* [0..65535] */
|
||||
u16 MaxConnections; /* [1..65535] */
|
||||
u8 InitialR2T; /* [0,1] == [No,Yes] */
|
||||
u8 ImmediateData; /* [0,1] == [No,Yes] */
|
||||
u32 MaxBurstLength; /* [512..2**24-1] */
|
||||
u32 FirstBurstLength; /* [512..2**24-1] */
|
||||
u16 DefaultTime2Wait; /* [0..3600] */
|
||||
u16 DefaultTime2Retain; /* [0..3600] */
|
||||
u16 MaxOutstandingR2T; /* [1..65535] */
|
||||
u8 DataPDUInOrder; /* [0,1] == [No,Yes] */
|
||||
u8 DataSequenceInOrder; /* [0,1] == [No,Yes] */
|
||||
u8 ErrorRecoveryLevel; /* [0..2] */
|
||||
u8 SessionType; /* [0,1] == [Normal,Discovery]*/
|
||||
/*
|
||||
* iSER specific session parameters
|
||||
*/
|
||||
u8 RDMAExtensions; /* [0,1] == [No,Yes] */
|
||||
};
|
||||
|
||||
struct iscsi_queue_req {
|
||||
int state;
|
||||
struct iscsi_cmd *cmd;
|
||||
struct list_head qr_list;
|
||||
};
|
||||
|
||||
struct iscsi_data_count {
|
||||
int data_length;
|
||||
int sync_and_steering;
|
||||
enum data_count_type type;
|
||||
u32 iov_count;
|
||||
u32 ss_iov_count;
|
||||
u32 ss_marker_count;
|
||||
struct kvec *iov;
|
||||
};
|
||||
|
||||
struct iscsi_param_list {
|
||||
bool iser;
|
||||
struct list_head param_list;
|
||||
struct list_head extra_response_list;
|
||||
};
|
||||
|
||||
struct iscsi_datain_req {
|
||||
enum datain_req_comp_table dr_complete;
|
||||
int generate_recovery_values;
|
||||
enum datain_req_rec_table recovery;
|
||||
u32 begrun;
|
||||
u32 runlength;
|
||||
u32 data_length;
|
||||
u32 data_offset;
|
||||
u32 data_sn;
|
||||
u32 next_burst_len;
|
||||
u32 read_data_done;
|
||||
u32 seq_send_order;
|
||||
struct list_head cmd_datain_node;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_ooo_cmdsn {
|
||||
u16 cid;
|
||||
u32 batch_count;
|
||||
u32 cmdsn;
|
||||
u32 exp_cmdsn;
|
||||
struct iscsi_cmd *cmd;
|
||||
struct list_head ooo_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_datain {
|
||||
u8 flags;
|
||||
u32 data_sn;
|
||||
u32 length;
|
||||
u32 offset;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_r2t {
|
||||
int seq_complete;
|
||||
int recovery_r2t;
|
||||
int sent_r2t;
|
||||
u32 r2t_sn;
|
||||
u32 offset;
|
||||
u32 targ_xfer_tag;
|
||||
u32 xfer_len;
|
||||
struct list_head r2t_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_cmd {
|
||||
enum iscsi_timer_flags_table dataout_timer_flags;
|
||||
/* DataOUT timeout retries */
|
||||
u8 dataout_timeout_retries;
|
||||
/* Within command recovery count */
|
||||
u8 error_recovery_count;
|
||||
/* iSCSI dependent state for out or order CmdSNs */
|
||||
enum cmd_i_state_table deferred_i_state;
|
||||
/* iSCSI dependent state */
|
||||
enum cmd_i_state_table i_state;
|
||||
/* Command is an immediate command (ISCSI_OP_IMMEDIATE set) */
|
||||
u8 immediate_cmd;
|
||||
/* Immediate data present */
|
||||
u8 immediate_data;
|
||||
/* iSCSI Opcode */
|
||||
u8 iscsi_opcode;
|
||||
/* iSCSI Response Code */
|
||||
u8 iscsi_response;
|
||||
/* Logout reason when iscsi_opcode == ISCSI_INIT_LOGOUT_CMND */
|
||||
u8 logout_reason;
|
||||
/* Logout response code when iscsi_opcode == ISCSI_INIT_LOGOUT_CMND */
|
||||
u8 logout_response;
|
||||
/* MaxCmdSN has been incremented */
|
||||
u8 maxcmdsn_inc;
|
||||
/* Immediate Unsolicited Dataout */
|
||||
u8 unsolicited_data;
|
||||
/* Reject reason code */
|
||||
u8 reject_reason;
|
||||
/* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */
|
||||
u16 logout_cid;
|
||||
/* Command flags */
|
||||
enum cmd_flags_table cmd_flags;
|
||||
/* Initiator Task Tag assigned from Initiator */
|
||||
itt_t init_task_tag;
|
||||
/* Target Transfer Tag assigned from Target */
|
||||
u32 targ_xfer_tag;
|
||||
/* CmdSN assigned from Initiator */
|
||||
u32 cmd_sn;
|
||||
/* ExpStatSN assigned from Initiator */
|
||||
u32 exp_stat_sn;
|
||||
/* StatSN assigned to this ITT */
|
||||
u32 stat_sn;
|
||||
/* DataSN Counter */
|
||||
u32 data_sn;
|
||||
/* R2TSN Counter */
|
||||
u32 r2t_sn;
|
||||
/* Last DataSN acknowledged via DataAck SNACK */
|
||||
u32 acked_data_sn;
|
||||
/* Used for echoing NOPOUT ping data */
|
||||
u32 buf_ptr_size;
|
||||
/* Used to store DataDigest */
|
||||
u32 data_crc;
|
||||
/* Counter for MaxOutstandingR2T */
|
||||
u32 outstanding_r2ts;
|
||||
/* Next R2T Offset when DataSequenceInOrder=Yes */
|
||||
u32 r2t_offset;
|
||||
/* Iovec current and orig count for iscsi_cmd->iov_data */
|
||||
u32 iov_data_count;
|
||||
u32 orig_iov_data_count;
|
||||
/* Number of miscellaneous iovecs used for IP stack calls */
|
||||
u32 iov_misc_count;
|
||||
/* Number of struct iscsi_pdu in struct iscsi_cmd->pdu_list */
|
||||
u32 pdu_count;
|
||||
/* Next struct iscsi_pdu to send in struct iscsi_cmd->pdu_list */
|
||||
u32 pdu_send_order;
|
||||
/* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */
|
||||
u32 pdu_start;
|
||||
/* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */
|
||||
u32 seq_send_order;
|
||||
/* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */
|
||||
u32 seq_count;
|
||||
/* Current struct iscsi_seq in struct iscsi_cmd->seq_list */
|
||||
u32 seq_no;
|
||||
/* Lowest offset in current DataOUT sequence */
|
||||
u32 seq_start_offset;
|
||||
/* Highest offset in current DataOUT sequence */
|
||||
u32 seq_end_offset;
|
||||
/* Total size in bytes received so far of READ data */
|
||||
u32 read_data_done;
|
||||
/* Total size in bytes received so far of WRITE data */
|
||||
u32 write_data_done;
|
||||
/* Counter for FirstBurstLength key */
|
||||
u32 first_burst_len;
|
||||
/* Counter for MaxBurstLength key */
|
||||
u32 next_burst_len;
|
||||
/* Transfer size used for IP stack calls */
|
||||
u32 tx_size;
|
||||
/* Buffer used for various purposes */
|
||||
void *buf_ptr;
|
||||
/* Used by SendTargets=[iqn.,eui.] discovery */
|
||||
void *text_in_ptr;
|
||||
/* See include/linux/dma-mapping.h */
|
||||
enum dma_data_direction data_direction;
|
||||
/* iSCSI PDU Header + CRC */
|
||||
unsigned char pdu[ISCSI_HDR_LEN + ISCSI_CRC_LEN];
|
||||
/* Number of times struct iscsi_cmd is present in immediate queue */
|
||||
atomic_t immed_queue_count;
|
||||
atomic_t response_queue_count;
|
||||
spinlock_t datain_lock;
|
||||
spinlock_t dataout_timeout_lock;
|
||||
/* spinlock for protecting struct iscsi_cmd->i_state */
|
||||
spinlock_t istate_lock;
|
||||
/* spinlock for adding within command recovery entries */
|
||||
spinlock_t error_lock;
|
||||
/* spinlock for adding R2Ts */
|
||||
spinlock_t r2t_lock;
|
||||
/* DataIN List */
|
||||
struct list_head datain_list;
|
||||
/* R2T List */
|
||||
struct list_head cmd_r2t_list;
|
||||
/* Timer for DataOUT */
|
||||
struct timer_list dataout_timer;
|
||||
/* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */
|
||||
struct kvec *iov_data;
|
||||
/* Iovecs for miscellaneous purposes */
|
||||
#define ISCSI_MISC_IOVECS 5
|
||||
struct kvec iov_misc[ISCSI_MISC_IOVECS];
|
||||
/* Array of struct iscsi_pdu used for DataPDUInOrder=No */
|
||||
struct iscsi_pdu *pdu_list;
|
||||
/* Current struct iscsi_pdu used for DataPDUInOrder=No */
|
||||
struct iscsi_pdu *pdu_ptr;
|
||||
/* Array of struct iscsi_seq used for DataSequenceInOrder=No */
|
||||
struct iscsi_seq *seq_list;
|
||||
/* Current struct iscsi_seq used for DataSequenceInOrder=No */
|
||||
struct iscsi_seq *seq_ptr;
|
||||
/* TMR Request when iscsi_opcode == ISCSI_OP_SCSI_TMFUNC */
|
||||
struct iscsi_tmr_req *tmr_req;
|
||||
/* Connection this command is alligient to */
|
||||
struct iscsi_conn *conn;
|
||||
/* Pointer to connection recovery entry */
|
||||
struct iscsi_conn_recovery *cr;
|
||||
/* Session the command is part of, used for connection recovery */
|
||||
struct iscsi_session *sess;
|
||||
/* list_head for connection list */
|
||||
struct list_head i_conn_node;
|
||||
/* The TCM I/O descriptor that is accessed via container_of() */
|
||||
struct se_cmd se_cmd;
|
||||
/* Sense buffer that will be mapped into outgoing status */
|
||||
#define ISCSI_SENSE_BUFFER_LEN (TRANSPORT_SENSE_BUFFER + 2)
|
||||
unsigned char sense_buffer[ISCSI_SENSE_BUFFER_LEN];
|
||||
|
||||
u32 padding;
|
||||
u8 pad_bytes[4];
|
||||
|
||||
struct scatterlist *first_data_sg;
|
||||
u32 first_data_sg_off;
|
||||
u32 kmapped_nents;
|
||||
sense_reason_t sense_reason;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_tmr_req {
|
||||
bool task_reassign:1;
|
||||
u32 exp_data_sn;
|
||||
struct iscsi_cmd *ref_cmd;
|
||||
struct iscsi_conn_recovery *conn_recovery;
|
||||
struct se_tmr_req *se_tmr_req;
|
||||
};
|
||||
|
||||
struct iscsi_conn {
|
||||
wait_queue_head_t queues_wq;
|
||||
/* Authentication Successful for this connection */
|
||||
u8 auth_complete;
|
||||
/* State connection is currently in */
|
||||
u8 conn_state;
|
||||
u8 conn_logout_reason;
|
||||
u8 network_transport;
|
||||
enum iscsi_timer_flags_table nopin_timer_flags;
|
||||
enum iscsi_timer_flags_table nopin_response_timer_flags;
|
||||
/* Used to know what thread encountered a transport failure */
|
||||
u8 which_thread;
|
||||
/* connection id assigned by the Initiator */
|
||||
u16 cid;
|
||||
/* Remote TCP Port */
|
||||
u16 login_port;
|
||||
u16 local_port;
|
||||
int net_size;
|
||||
int login_family;
|
||||
u32 auth_id;
|
||||
u32 conn_flags;
|
||||
/* Used for iscsi_tx_login_rsp() */
|
||||
itt_t login_itt;
|
||||
u32 exp_statsn;
|
||||
/* Per connection status sequence number */
|
||||
u32 stat_sn;
|
||||
/* IFMarkInt's Current Value */
|
||||
u32 if_marker;
|
||||
/* OFMarkInt's Current Value */
|
||||
u32 of_marker;
|
||||
/* Used for calculating OFMarker offset to next PDU */
|
||||
u32 of_marker_offset;
|
||||
#define IPV6_ADDRESS_SPACE 48
|
||||
unsigned char login_ip[IPV6_ADDRESS_SPACE];
|
||||
unsigned char local_ip[IPV6_ADDRESS_SPACE];
|
||||
int conn_usage_count;
|
||||
int conn_waiting_on_uc;
|
||||
atomic_t check_immediate_queue;
|
||||
atomic_t conn_logout_remove;
|
||||
atomic_t connection_exit;
|
||||
atomic_t connection_recovery;
|
||||
atomic_t connection_reinstatement;
|
||||
atomic_t connection_wait_rcfr;
|
||||
atomic_t sleep_on_conn_wait_comp;
|
||||
atomic_t transport_failed;
|
||||
struct completion conn_post_wait_comp;
|
||||
struct completion conn_wait_comp;
|
||||
struct completion conn_wait_rcfr_comp;
|
||||
struct completion conn_waiting_on_uc_comp;
|
||||
struct completion conn_logout_comp;
|
||||
struct completion tx_half_close_comp;
|
||||
struct completion rx_half_close_comp;
|
||||
/* socket used by this connection */
|
||||
struct socket *sock;
|
||||
void (*orig_data_ready)(struct sock *);
|
||||
void (*orig_state_change)(struct sock *);
|
||||
#define LOGIN_FLAGS_READ_ACTIVE 1
|
||||
#define LOGIN_FLAGS_CLOSED 2
|
||||
#define LOGIN_FLAGS_READY 4
|
||||
unsigned long login_flags;
|
||||
struct delayed_work login_work;
|
||||
struct delayed_work login_cleanup_work;
|
||||
struct iscsi_login *login;
|
||||
struct timer_list nopin_timer;
|
||||
struct timer_list nopin_response_timer;
|
||||
struct timer_list transport_timer;
|
||||
struct task_struct *login_kworker;
|
||||
/* Spinlock used for add/deleting cmd's from conn_cmd_list */
|
||||
spinlock_t cmd_lock;
|
||||
spinlock_t conn_usage_lock;
|
||||
spinlock_t immed_queue_lock;
|
||||
spinlock_t nopin_timer_lock;
|
||||
spinlock_t response_queue_lock;
|
||||
spinlock_t state_lock;
|
||||
/* libcrypto RX and TX contexts for crc32c */
|
||||
struct hash_desc conn_rx_hash;
|
||||
struct hash_desc conn_tx_hash;
|
||||
/* Used for scheduling TX and RX connection kthreads */
|
||||
cpumask_var_t conn_cpumask;
|
||||
unsigned int conn_rx_reset_cpumask:1;
|
||||
unsigned int conn_tx_reset_cpumask:1;
|
||||
/* list_head of struct iscsi_cmd for this connection */
|
||||
struct list_head conn_cmd_list;
|
||||
struct list_head immed_queue_list;
|
||||
struct list_head response_queue_list;
|
||||
struct iscsi_conn_ops *conn_ops;
|
||||
struct iscsi_login *conn_login;
|
||||
struct iscsit_transport *conn_transport;
|
||||
struct iscsi_param_list *param_list;
|
||||
/* Used for per connection auth state machine */
|
||||
void *auth_protocol;
|
||||
void *context;
|
||||
struct iscsi_login_thread_s *login_thread;
|
||||
struct iscsi_portal_group *tpg;
|
||||
struct iscsi_tpg_np *tpg_np;
|
||||
/* Pointer to parent session */
|
||||
struct iscsi_session *sess;
|
||||
/* Pointer to thread_set in use for this conn's threads */
|
||||
struct iscsi_thread_set *thread_set;
|
||||
/* list_head for session connection list */
|
||||
struct list_head conn_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_conn_recovery {
|
||||
u16 cid;
|
||||
u32 cmd_count;
|
||||
u32 maxrecvdatasegmentlength;
|
||||
u32 maxxmitdatasegmentlength;
|
||||
int ready_for_reallegiance;
|
||||
struct list_head conn_recovery_cmd_list;
|
||||
spinlock_t conn_recovery_cmd_lock;
|
||||
struct timer_list time2retain_timer;
|
||||
struct iscsi_session *sess;
|
||||
struct list_head cr_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_session {
|
||||
u8 initiator_vendor;
|
||||
u8 isid[6];
|
||||
enum iscsi_timer_flags_table time2retain_timer_flags;
|
||||
u8 version_active;
|
||||
u16 cid_called;
|
||||
u16 conn_recovery_count;
|
||||
u16 tsih;
|
||||
/* state session is currently in */
|
||||
u32 session_state;
|
||||
/* session wide counter: initiator assigned task tag */
|
||||
itt_t init_task_tag;
|
||||
/* session wide counter: target assigned task tag */
|
||||
u32 targ_xfer_tag;
|
||||
u32 cmdsn_window;
|
||||
|
||||
/* protects cmdsn values */
|
||||
struct mutex cmdsn_mutex;
|
||||
/* session wide counter: expected command sequence number */
|
||||
u32 exp_cmd_sn;
|
||||
/* session wide counter: maximum allowed command sequence number */
|
||||
u32 max_cmd_sn;
|
||||
struct list_head sess_ooo_cmdsn_list;
|
||||
|
||||
/* LIO specific session ID */
|
||||
u32 sid;
|
||||
char auth_type[8];
|
||||
/* unique within the target */
|
||||
int session_index;
|
||||
/* Used for session reference counting */
|
||||
int session_usage_count;
|
||||
int session_waiting_on_uc;
|
||||
atomic_long_t cmd_pdus;
|
||||
atomic_long_t rsp_pdus;
|
||||
atomic_long_t tx_data_octets;
|
||||
atomic_long_t rx_data_octets;
|
||||
atomic_long_t conn_digest_errors;
|
||||
atomic_long_t conn_timeout_errors;
|
||||
u64 creation_time;
|
||||
/* Number of active connections */
|
||||
atomic_t nconn;
|
||||
atomic_t session_continuation;
|
||||
atomic_t session_fall_back_to_erl0;
|
||||
atomic_t session_logout;
|
||||
atomic_t session_reinstatement;
|
||||
atomic_t session_stop_active;
|
||||
atomic_t sleep_on_sess_wait_comp;
|
||||
/* connection list */
|
||||
struct list_head sess_conn_list;
|
||||
struct list_head cr_active_list;
|
||||
struct list_head cr_inactive_list;
|
||||
spinlock_t conn_lock;
|
||||
spinlock_t cr_a_lock;
|
||||
spinlock_t cr_i_lock;
|
||||
spinlock_t session_usage_lock;
|
||||
spinlock_t ttt_lock;
|
||||
struct completion async_msg_comp;
|
||||
struct completion reinstatement_comp;
|
||||
struct completion session_wait_comp;
|
||||
struct completion session_waiting_on_uc_comp;
|
||||
struct timer_list time2retain_timer;
|
||||
struct iscsi_sess_ops *sess_ops;
|
||||
struct se_session *se_sess;
|
||||
struct iscsi_portal_group *tpg;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_login {
|
||||
u8 auth_complete;
|
||||
u8 checked_for_existing;
|
||||
u8 current_stage;
|
||||
u8 leading_connection;
|
||||
u8 first_request;
|
||||
u8 version_min;
|
||||
u8 version_max;
|
||||
u8 login_complete;
|
||||
u8 login_failed;
|
||||
bool zero_tsih;
|
||||
char isid[6];
|
||||
u32 cmd_sn;
|
||||
itt_t init_task_tag;
|
||||
u32 initial_exp_statsn;
|
||||
u32 rsp_length;
|
||||
u16 cid;
|
||||
u16 tsih;
|
||||
char req[ISCSI_HDR_LEN];
|
||||
char rsp[ISCSI_HDR_LEN];
|
||||
char *req_buf;
|
||||
char *rsp_buf;
|
||||
struct iscsi_conn *conn;
|
||||
struct iscsi_np *np;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_node_attrib {
|
||||
u32 dataout_timeout;
|
||||
u32 dataout_timeout_retries;
|
||||
u32 default_erl;
|
||||
u32 nopin_timeout;
|
||||
u32 nopin_response_timeout;
|
||||
u32 random_datain_pdu_offsets;
|
||||
u32 random_datain_seq_offsets;
|
||||
u32 random_r2t_offsets;
|
||||
u32 tmr_cold_reset;
|
||||
u32 tmr_warm_reset;
|
||||
struct iscsi_node_acl *nacl;
|
||||
};
|
||||
|
||||
struct se_dev_entry_s;
|
||||
|
||||
struct iscsi_node_auth {
|
||||
enum naf_flags_table naf_flags;
|
||||
int authenticate_target;
|
||||
/* Used for iscsit_global->discovery_auth,
|
||||
* set to zero (auth disabled) by default */
|
||||
int enforce_discovery_auth;
|
||||
#define MAX_USER_LEN 256
|
||||
#define MAX_PASS_LEN 256
|
||||
char userid[MAX_USER_LEN];
|
||||
char password[MAX_PASS_LEN];
|
||||
char userid_mutual[MAX_USER_LEN];
|
||||
char password_mutual[MAX_PASS_LEN];
|
||||
};
|
||||
|
||||
#include "iscsi_target_stat.h"
|
||||
|
||||
struct iscsi_node_stat_grps {
|
||||
struct config_group iscsi_sess_stats_group;
|
||||
struct config_group iscsi_conn_stats_group;
|
||||
};
|
||||
|
||||
struct iscsi_node_acl {
|
||||
struct iscsi_node_attrib node_attrib;
|
||||
struct iscsi_node_auth node_auth;
|
||||
struct iscsi_node_stat_grps node_stat_grps;
|
||||
struct se_node_acl se_node_acl;
|
||||
};
|
||||
|
||||
struct iscsi_tpg_attrib {
|
||||
u32 authentication;
|
||||
u32 login_timeout;
|
||||
u32 netif_timeout;
|
||||
u32 generate_node_acls;
|
||||
u32 cache_dynamic_acls;
|
||||
u32 default_cmdsn_depth;
|
||||
u32 demo_mode_write_protect;
|
||||
u32 prod_mode_write_protect;
|
||||
u32 demo_mode_discovery;
|
||||
u32 default_erl;
|
||||
u8 t10_pi;
|
||||
struct iscsi_portal_group *tpg;
|
||||
};
|
||||
|
||||
struct iscsi_np {
|
||||
int np_network_transport;
|
||||
int np_ip_proto;
|
||||
int np_sock_type;
|
||||
enum np_thread_state_table np_thread_state;
|
||||
bool enabled;
|
||||
enum iscsi_timer_flags_table np_login_timer_flags;
|
||||
u32 np_exports;
|
||||
enum np_flags_table np_flags;
|
||||
unsigned char np_ip[IPV6_ADDRESS_SPACE];
|
||||
u16 np_port;
|
||||
spinlock_t np_thread_lock;
|
||||
struct completion np_restart_comp;
|
||||
struct socket *np_socket;
|
||||
struct __kernel_sockaddr_storage np_sockaddr;
|
||||
struct task_struct *np_thread;
|
||||
struct timer_list np_login_timer;
|
||||
void *np_context;
|
||||
struct iscsit_transport *np_transport;
|
||||
struct list_head np_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_tpg_np {
|
||||
struct iscsi_np *tpg_np;
|
||||
struct iscsi_portal_group *tpg;
|
||||
struct iscsi_tpg_np *tpg_np_parent;
|
||||
struct list_head tpg_np_list;
|
||||
struct list_head tpg_np_child_list;
|
||||
struct list_head tpg_np_parent_list;
|
||||
struct se_tpg_np se_tpg_np;
|
||||
spinlock_t tpg_np_parent_lock;
|
||||
struct completion tpg_np_comp;
|
||||
struct kref tpg_np_kref;
|
||||
};
|
||||
|
||||
struct iscsi_portal_group {
|
||||
unsigned char tpg_chap_id;
|
||||
/* TPG State */
|
||||
enum tpg_state_table tpg_state;
|
||||
/* Target Portal Group Tag */
|
||||
u16 tpgt;
|
||||
/* Id assigned to target sessions */
|
||||
u16 ntsih;
|
||||
/* Number of active sessions */
|
||||
u32 nsessions;
|
||||
/* Number of Network Portals available for this TPG */
|
||||
u32 num_tpg_nps;
|
||||
/* Per TPG LIO specific session ID. */
|
||||
u32 sid;
|
||||
/* Spinlock for adding/removing Network Portals */
|
||||
spinlock_t tpg_np_lock;
|
||||
spinlock_t tpg_state_lock;
|
||||
struct se_portal_group tpg_se_tpg;
|
||||
struct mutex tpg_access_lock;
|
||||
struct semaphore np_login_sem;
|
||||
struct iscsi_tpg_attrib tpg_attrib;
|
||||
struct iscsi_node_auth tpg_demo_auth;
|
||||
/* Pointer to default list of iSCSI parameters for TPG */
|
||||
struct iscsi_param_list *param_list;
|
||||
struct iscsi_tiqn *tpg_tiqn;
|
||||
struct list_head tpg_gnp_list;
|
||||
struct list_head tpg_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_wwn_stat_grps {
|
||||
struct config_group iscsi_stat_group;
|
||||
struct config_group iscsi_instance_group;
|
||||
struct config_group iscsi_sess_err_group;
|
||||
struct config_group iscsi_tgt_attr_group;
|
||||
struct config_group iscsi_login_stats_group;
|
||||
struct config_group iscsi_logout_stats_group;
|
||||
};
|
||||
|
||||
struct iscsi_tiqn {
|
||||
#define ISCSI_IQN_LEN 224
|
||||
unsigned char tiqn[ISCSI_IQN_LEN];
|
||||
enum tiqn_state_table tiqn_state;
|
||||
int tiqn_access_count;
|
||||
u32 tiqn_active_tpgs;
|
||||
u32 tiqn_ntpgs;
|
||||
u32 tiqn_num_tpg_nps;
|
||||
u32 tiqn_nsessions;
|
||||
struct list_head tiqn_list;
|
||||
struct list_head tiqn_tpg_list;
|
||||
spinlock_t tiqn_state_lock;
|
||||
spinlock_t tiqn_tpg_lock;
|
||||
struct se_wwn tiqn_wwn;
|
||||
struct iscsi_wwn_stat_grps tiqn_stat_grps;
|
||||
int tiqn_index;
|
||||
struct iscsi_sess_err_stats sess_err_stats;
|
||||
struct iscsi_login_stats login_stats;
|
||||
struct iscsi_logout_stats logout_stats;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsit_global {
|
||||
/* In core shutdown */
|
||||
u32 in_shutdown;
|
||||
u32 active_ts;
|
||||
/* Unique identifier used for the authentication daemon */
|
||||
u32 auth_id;
|
||||
u32 inactive_ts;
|
||||
/* Thread Set bitmap count */
|
||||
int ts_bitmap_count;
|
||||
/* Thread Set bitmap pointer */
|
||||
unsigned long *ts_bitmap;
|
||||
/* Used for iSCSI discovery session authentication */
|
||||
struct iscsi_node_acl discovery_acl;
|
||||
struct iscsi_portal_group *discovery_tpg;
|
||||
};
|
||||
|
||||
#endif /* ISCSI_TARGET_CORE_H */
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <scsi/iscsi_proto.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_erl1.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
|
|
@ -939,7 +940,8 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
|||
|
||||
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
|
||||
spin_unlock_bh(&conn->state_lock);
|
||||
iscsit_close_connection(conn);
|
||||
if (conn->conn_transport->transport_type == ISCSI_TCP)
|
||||
iscsit_close_connection(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_device.h"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@
|
|||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_nego.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
#include "iscsi_target_erl2.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_nego.h"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <target/target_core_base.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_parameters.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@
|
|||
#include <target/target_core_base.h>
|
||||
#include <target/configfs_macros.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
|
||||
#ifndef INITIAL_JIFFIES
|
||||
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
#ifndef ISCSI_TARGET_STAT_H
|
||||
#define ISCSI_TARGET_STAT_H
|
||||
|
||||
/*
|
||||
* For struct iscsi_tiqn->tiqn_wwn default groups
|
||||
*/
|
||||
extern struct config_item_type iscsi_stat_instance_cit;
|
||||
extern struct config_item_type iscsi_stat_sess_err_cit;
|
||||
extern struct config_item_type iscsi_stat_tgt_attr_cit;
|
||||
extern struct config_item_type iscsi_stat_login_cit;
|
||||
extern struct config_item_type iscsi_stat_logout_cit;
|
||||
|
||||
/*
|
||||
* For struct iscsi_session->se_sess default groups
|
||||
*/
|
||||
extern struct config_item_type iscsi_stat_sess_cit;
|
||||
|
||||
/* iSCSI session error types */
|
||||
#define ISCSI_SESS_ERR_UNKNOWN 0
|
||||
#define ISCSI_SESS_ERR_DIGEST 1
|
||||
#define ISCSI_SESS_ERR_CXN_TIMEOUT 2
|
||||
#define ISCSI_SESS_ERR_PDU_FORMAT 3
|
||||
|
||||
/* iSCSI session error stats */
|
||||
struct iscsi_sess_err_stats {
|
||||
spinlock_t lock;
|
||||
u32 digest_errors;
|
||||
u32 cxn_timeout_errors;
|
||||
u32 pdu_format_errors;
|
||||
u32 last_sess_failure_type;
|
||||
char last_sess_fail_rem_name[224];
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/* iSCSI login failure types (sub oids) */
|
||||
#define ISCSI_LOGIN_FAIL_OTHER 2
|
||||
#define ISCSI_LOGIN_FAIL_REDIRECT 3
|
||||
#define ISCSI_LOGIN_FAIL_AUTHORIZE 4
|
||||
#define ISCSI_LOGIN_FAIL_AUTHENTICATE 5
|
||||
#define ISCSI_LOGIN_FAIL_NEGOTIATE 6
|
||||
|
||||
/* iSCSI login stats */
|
||||
struct iscsi_login_stats {
|
||||
spinlock_t lock;
|
||||
u32 accepts;
|
||||
u32 other_fails;
|
||||
u32 redirects;
|
||||
u32 authorize_fails;
|
||||
u32 authenticate_fails;
|
||||
u32 negotiate_fails; /* used for notifications */
|
||||
u64 last_fail_time; /* time stamp (jiffies) */
|
||||
u32 last_fail_type;
|
||||
int last_intr_fail_ip_family;
|
||||
unsigned char last_intr_fail_ip_addr[IPV6_ADDRESS_SPACE];
|
||||
char last_intr_fail_name[224];
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/* iSCSI logout stats */
|
||||
struct iscsi_logout_stats {
|
||||
spinlock_t lock;
|
||||
u32 normal_logouts;
|
||||
u32 abnormal_logouts;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
#endif /*** ISCSI_TARGET_STAT_H ***/
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_device.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <target/target_core_fabric.h>
|
||||
#include <target/target_core_configfs.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_erl0.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_nodeattrib.h"
|
||||
|
|
|
|||
|
|
@ -20,40 +20,26 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target.h"
|
||||
|
||||
static LIST_HEAD(active_ts_list);
|
||||
static LIST_HEAD(inactive_ts_list);
|
||||
static DEFINE_SPINLOCK(active_ts_lock);
|
||||
static DEFINE_SPINLOCK(inactive_ts_lock);
|
||||
static DEFINE_SPINLOCK(ts_bitmap_lock);
|
||||
|
||||
static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
spin_lock(&active_ts_lock);
|
||||
list_add_tail(&ts->ts_list, &active_ts_list);
|
||||
iscsit_global->active_ts++;
|
||||
spin_unlock(&active_ts_lock);
|
||||
}
|
||||
|
||||
static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
if (!list_empty(&ts->ts_list)) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
spin_lock(&inactive_ts_lock);
|
||||
list_add_tail(&ts->ts_list, &inactive_ts_list);
|
||||
iscsit_global->inactive_ts++;
|
||||
spin_unlock(&inactive_ts_lock);
|
||||
}
|
||||
|
||||
static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
spin_lock(&active_ts_lock);
|
||||
list_del(&ts->ts_list);
|
||||
iscsit_global->active_ts--;
|
||||
spin_unlock(&active_ts_lock);
|
||||
}
|
||||
|
||||
static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
|
||||
{
|
||||
struct iscsi_thread_set *ts;
|
||||
|
|
@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
|
|||
|
||||
ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
|
||||
|
||||
list_del(&ts->ts_list);
|
||||
list_del_init(&ts->ts_list);
|
||||
iscsit_global->inactive_ts--;
|
||||
spin_unlock(&inactive_ts_lock);
|
||||
|
||||
|
|
@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_thread_sets(void)
|
|||
|
||||
void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
|
||||
{
|
||||
iscsi_add_ts_to_active_list(ts);
|
||||
|
||||
spin_lock_bh(&ts->ts_state_lock);
|
||||
conn->thread_set = ts;
|
||||
ts->conn = conn;
|
||||
|
|
@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
|
|||
|
||||
if (ts->delay_inactive && (--ts->thread_count == 0)) {
|
||||
spin_unlock_bh(&ts->ts_state_lock);
|
||||
iscsi_del_ts_from_active_list(ts);
|
||||
|
||||
if (!iscsit_global->in_shutdown)
|
||||
iscsi_deallocate_extra_thread_sets();
|
||||
|
|
@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
|
|||
|
||||
if (ts->delay_inactive && (--ts->thread_count == 0)) {
|
||||
spin_unlock_bh(&ts->ts_state_lock);
|
||||
iscsi_del_ts_from_active_list(ts);
|
||||
|
||||
if (!iscsit_global->in_shutdown)
|
||||
iscsi_deallocate_extra_thread_sets();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <target/target_core_configfs.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
|
|
@ -390,6 +390,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
|
|||
init_task_tag, conn->cid);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_find_cmd_from_itt);
|
||||
|
||||
struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
|
||||
struct iscsi_conn *conn,
|
||||
|
|
@ -939,13 +940,8 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
|
|||
state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE :
|
||||
ISTATE_SEND_NOPIN_NO_RESPONSE;
|
||||
cmd->init_task_tag = RESERVED_ITT;
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = (want_response) ? conn->sess->targ_xfer_tag++ :
|
||||
0xFFFFFFFF;
|
||||
if (want_response && (cmd->targ_xfer_tag == 0xFFFFFFFF))
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
|
||||
cmd->targ_xfer_tag = (want_response) ?
|
||||
session_get_next_ttt(conn->sess) : 0xFFFFFFFF;
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
|
|||
extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
unsigned char * ,__be32 cmdsn);
|
||||
extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
|
||||
itt_t, u32);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32);
|
||||
|
|
|
|||
|
|
@ -494,6 +494,11 @@ fd_execute_write_same(struct se_cmd *cmd)
|
|||
target_complete_cmd(cmd, SAM_STAT_GOOD);
|
||||
return 0;
|
||||
}
|
||||
if (cmd->prot_op) {
|
||||
pr_err("WRITE_SAME: Protection information with FILEIO"
|
||||
" backends not supported\n");
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
sg = &cmd->t_data_sg[0];
|
||||
|
||||
if (cmd->t_data_nents > 1 ||
|
||||
|
|
|
|||
|
|
@ -464,6 +464,11 @@ iblock_execute_write_same(struct se_cmd *cmd)
|
|||
sector_t block_lba = cmd->t_task_lba;
|
||||
sector_t sectors = sbc_get_write_same_sectors(cmd);
|
||||
|
||||
if (cmd->prot_op) {
|
||||
pr_err("WRITE_SAME: Protection information with IBLOCK"
|
||||
" backends not supported\n");
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
sg = &cmd->t_data_sg[0];
|
||||
|
||||
if (cmd->t_data_nents > 1 ||
|
||||
|
|
|
|||
|
|
@ -1874,8 +1874,8 @@ static int core_scsi3_update_aptpl_buf(
|
|||
}
|
||||
|
||||
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
||||
pr_err("Unable to update renaming"
|
||||
" APTPL metadata\n");
|
||||
pr_err("Unable to update renaming APTPL metadata,"
|
||||
" reallocating larger buffer\n");
|
||||
ret = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1892,8 +1892,8 @@ static int core_scsi3_update_aptpl_buf(
|
|||
lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
|
||||
|
||||
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
||||
pr_err("Unable to update renaming"
|
||||
" APTPL metadata\n");
|
||||
pr_err("Unable to update renaming APTPL metadata,"
|
||||
" reallocating larger buffer\n");
|
||||
ret = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1956,7 +1956,7 @@ static int __core_scsi3_write_aptpl_to_file(
|
|||
static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int rc;
|
||||
int rc, len = PR_APTPL_BUF_LEN;
|
||||
|
||||
if (!aptpl) {
|
||||
char *null_buf = "No Registrations or Reservations\n";
|
||||
|
|
@ -1970,25 +1970,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
|
||||
retry:
|
||||
buf = vzalloc(len);
|
||||
if (!buf)
|
||||
return TCM_OUT_OF_RESOURCES;
|
||||
|
||||
rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
|
||||
rc = core_scsi3_update_aptpl_buf(dev, buf, len);
|
||||
if (rc < 0) {
|
||||
kfree(buf);
|
||||
return TCM_OUT_OF_RESOURCES;
|
||||
vfree(buf);
|
||||
len *= 2;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
rc = __core_scsi3_write_aptpl_to_file(dev, buf);
|
||||
if (rc != 0) {
|
||||
pr_err("SPC-3 PR: Could not update APTPL\n");
|
||||
kfree(buf);
|
||||
vfree(buf);
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
dev->t10_pr.pr_aptpl_active = 1;
|
||||
kfree(buf);
|
||||
vfree(buf);
|
||||
pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@
|
|||
#include "target_core_ua.h"
|
||||
#include "target_core_alua.h"
|
||||
|
||||
static sense_reason_t
|
||||
sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool);
|
||||
|
||||
static sense_reason_t
|
||||
sbc_emulate_readcapacity(struct se_cmd *cmd)
|
||||
{
|
||||
|
|
@ -251,7 +254,10 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
|
|||
static sense_reason_t
|
||||
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
sector_t end_lba = dev->transport->get_blocks(dev) + 1;
|
||||
unsigned int sectors = sbc_get_write_same_sectors(cmd);
|
||||
sense_reason_t ret;
|
||||
|
||||
if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
|
||||
pr_err("WRITE_SAME PBDATA and LBDATA"
|
||||
|
|
@ -264,6 +270,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
|
|||
sectors, cmd->se_dev->dev_attrib.max_write_same_len);
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
/*
|
||||
* Sanity check for LBA wrap and request past end of device.
|
||||
*/
|
||||
if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
|
||||
((cmd->t_task_lba + sectors) > end_lba)) {
|
||||
pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n",
|
||||
(unsigned long long)end_lba, cmd->t_task_lba, sectors);
|
||||
return TCM_ADDRESS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
|
||||
if (flags[0] & 0x10) {
|
||||
pr_warn("WRITE SAME with ANCHOR not supported\n");
|
||||
|
|
@ -277,12 +293,21 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
|
|||
if (!ops->execute_write_same_unmap)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
if (!dev->dev_attrib.emulate_tpws) {
|
||||
pr_err("Got WRITE_SAME w/ UNMAP=1, but backend device"
|
||||
" has emulate_tpws disabled\n");
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
}
|
||||
cmd->execute_cmd = ops->execute_write_same_unmap;
|
||||
return 0;
|
||||
}
|
||||
if (!ops->execute_write_same)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, &cmd->t_task_cdb[0], sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->execute_cmd = ops->execute_write_same;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -614,14 +639,21 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
static sense_reason_t
|
||||
sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
||||
u32 sectors, bool is_write)
|
||||
{
|
||||
u8 protect = cdb[1] >> 5;
|
||||
|
||||
if ((!cmd->t_prot_sg || !cmd->t_prot_nents) && cmd->prot_pto)
|
||||
return true;
|
||||
if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
|
||||
if (protect && !dev->dev_attrib.pi_prot_type) {
|
||||
pr_err("CDB contains protect bit, but device does not"
|
||||
" advertise PROTECT=1 feature bit\n");
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
if (cmd->prot_pto)
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
switch (dev->dev_attrib.pi_prot_type) {
|
||||
case TARGET_DIF_TYPE3_PROT:
|
||||
|
|
@ -629,7 +661,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
|||
break;
|
||||
case TARGET_DIF_TYPE2_PROT:
|
||||
if (protect)
|
||||
return false;
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->reftag_seed = cmd->t_task_lba;
|
||||
break;
|
||||
|
|
@ -638,12 +670,12 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
|||
break;
|
||||
case TARGET_DIF_TYPE0_PROT:
|
||||
default:
|
||||
return true;
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type,
|
||||
is_write, cmd))
|
||||
return false;
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->prot_type = dev->dev_attrib.pi_prot_type;
|
||||
cmd->prot_length = dev->prot_length * sectors;
|
||||
|
|
@ -662,7 +694,30 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
|||
__func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
|
||||
cmd->prot_op, cmd->prot_checks);
|
||||
|
||||
return true;
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
static int
|
||||
sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
|
||||
{
|
||||
if (cdb[1] & 0x10) {
|
||||
if (!dev->dev_attrib.emulate_dpo) {
|
||||
pr_err("Got CDB: 0x%02x with DPO bit set, but device"
|
||||
" does not advertise support for DPO\n", cdb[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (cdb[1] & 0x8) {
|
||||
if (!dev->dev_attrib.emulate_fua_write ||
|
||||
!dev->dev_attrib.emulate_write_cache) {
|
||||
pr_err("Got CDB: 0x%02x with FUA bit set, but device"
|
||||
" does not advertise support for FUA write\n",
|
||||
cdb[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sense_reason_t
|
||||
|
|
@ -686,8 +741,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_10(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
|
|
@ -697,8 +756,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_12(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
|
|
@ -708,8 +771,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_16(cdb);
|
||||
cmd->t_task_lba = transport_lba_64(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
|
|
@ -727,11 +794,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_10(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
|
|
@ -740,11 +809,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_12(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
|
|
@ -753,11 +824,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
sectors = transport_get_sectors_16(cdb);
|
||||
cmd->t_task_lba = transport_lba_64(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
|
|
@ -768,6 +841,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
return TCM_INVALID_CDB_FIELD;
|
||||
sectors = transport_get_sectors_10(cdb);
|
||||
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
|
||||
|
|
@ -777,8 +853,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
cmd->transport_complete_callback = &xdreadwrite_callback;
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
break;
|
||||
case VARIABLE_LENGTH_CMD:
|
||||
{
|
||||
|
|
@ -787,6 +861,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
case XDWRITEREAD_32:
|
||||
sectors = transport_get_sectors_32(cdb);
|
||||
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
/*
|
||||
* Use WRITE_32 and READ_32 opcodes for the emulated
|
||||
* XDWRITE_READ_32 logic.
|
||||
|
|
@ -801,8 +877,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
cmd->transport_complete_callback = &xdreadwrite_callback;
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
break;
|
||||
case WRITE_SAME_32:
|
||||
sectors = transport_get_sectors_32(cdb);
|
||||
|
|
@ -888,6 +962,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
if (!ops->execute_unmap)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
if (!dev->dev_attrib.emulate_tpu) {
|
||||
pr_err("Got UNMAP, but backend device has"
|
||||
" emulate_tpu disabled\n");
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
}
|
||||
size = get_unaligned_be16(&cdb[7]);
|
||||
cmd->execute_cmd = ops->execute_unmap;
|
||||
break;
|
||||
|
|
@ -955,7 +1034,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
|||
unsigned long long end_lba;
|
||||
check_lba:
|
||||
end_lba = dev->transport->get_blocks(dev) + 1;
|
||||
if (cmd->t_task_lba + sectors > end_lba) {
|
||||
if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
|
||||
((cmd->t_task_lba + sectors) > end_lba)) {
|
||||
pr_err("cmd exceeds last lba %llu "
|
||||
"(lba %llu, sectors %u)\n",
|
||||
end_lba, cmd->t_task_lba, sectors);
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
|
|||
* support the use of the WRITE SAME (16) command to unmap LBAs.
|
||||
*/
|
||||
if (dev->dev_attrib.emulate_tpws != 0)
|
||||
buf[5] |= 0x40;
|
||||
buf[5] |= 0x40 | 0x20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue