From 5cdf5a87a2b80b913499281384112a281e02193a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 15 Jan 2015 13:40:56 +0200 Subject: iscsi-target: use '%*ph' specifier to dump hex buffer Instead of pushing each byte via stack the %*ph specifier allows to supply just a pointer and length of the buffer. The patch converts code to use the specifier. Signed-off-by: Andy Shevchenko Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 9059c1e0b26e..526becd763cf 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -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) -- cgit v1.2.3 From 67f091f290d055441db28045703d9b075a2ae051 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 7 Jan 2015 14:57:31 +0200 Subject: iscsi-target: Move iscsi_target_[core,stat].h under linux include Seems strange to see in include/target/iscsi/iscsi_transport.h: include "../../../drivers/target/iscsi/iscsi_target_core.h" Move it to it's natural location. Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 4 +- drivers/target/iscsi/iscsi_target_auth.c | 2 +- drivers/target/iscsi/iscsi_target_configfs.c | 4 +- drivers/target/iscsi/iscsi_target_core.h | 883 ---------------------- drivers/target/iscsi/iscsi_target_datain_values.c | 2 +- drivers/target/iscsi/iscsi_target_device.c | 2 +- drivers/target/iscsi/iscsi_target_erl0.c | 2 +- drivers/target/iscsi/iscsi_target_erl1.c | 2 +- drivers/target/iscsi/iscsi_target_erl2.c | 2 +- drivers/target/iscsi/iscsi_target_login.c | 4 +- drivers/target/iscsi/iscsi_target_nego.c | 2 +- drivers/target/iscsi/iscsi_target_nodeattrib.c | 2 +- drivers/target/iscsi/iscsi_target_parameters.c | 2 +- drivers/target/iscsi/iscsi_target_seq_pdu_list.c | 2 +- drivers/target/iscsi/iscsi_target_stat.c | 4 +- drivers/target/iscsi/iscsi_target_stat.h | 64 -- drivers/target/iscsi/iscsi_target_tmr.c | 2 +- drivers/target/iscsi/iscsi_target_tpg.c | 2 +- drivers/target/iscsi/iscsi_target_tq.c | 2 +- drivers/target/iscsi/iscsi_target_util.c | 2 +- include/target/iscsi/iscsi_target_core.h | 883 ++++++++++++++++++++++ include/target/iscsi/iscsi_target_stat.h | 64 ++ include/target/iscsi/iscsi_transport.h | 2 +- 23 files changed, 970 insertions(+), 970 deletions(-) delete mode 100644 drivers/target/iscsi/iscsi_target_core.h delete mode 100644 drivers/target/iscsi/iscsi_target_stat.h create mode 100644 include/target/iscsi/iscsi_target_core.h create mode 100644 include/target/iscsi/iscsi_target_stat.h (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 55f6774f706f..dd646c43d16d 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -30,7 +30,7 @@ #include #include -#include "iscsi_target_core.h" +#include #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 #include diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index ab4915c0d933..47e249dccb5f 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -22,7 +22,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_nego.h" #include "iscsi_target_auth.h" diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 526becd763cf..48384b675e62 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -28,7 +28,7 @@ #include #include -#include "iscsi_target_core.h" +#include #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 #include "iscsi_target_configfs.h" struct target_fabric_configfs *lio_target_fabric_configfs; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h deleted file mode 100644 index 09a522bae222..000000000000 --- a/drivers/target/iscsi/iscsi_target_core.h +++ /dev/null @@ -1,883 +0,0 @@ -#ifndef ISCSI_TARGET_CORE_H -#define ISCSI_TARGET_CORE_H - -#include -#include -#include -#include -#include -#include -#include - -#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, - IFC_SENDTARGETS_ALL = 0x00000100, - IFC_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 */ diff --git a/drivers/target/iscsi/iscsi_target_datain_values.c b/drivers/target/iscsi/iscsi_target_datain_values.c index e93d5a7a3f81..fb3b52b124ac 100644 --- a/drivers/target/iscsi/iscsi_target_datain_values.c +++ b/drivers/target/iscsi/iscsi_target_datain_values.c @@ -18,7 +18,7 @@ #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_erl1.h" #include "iscsi_target_util.h" diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c index 7087c736daa5..34c3cd1b05ce 100644 --- a/drivers/target/iscsi/iscsi_target_device.c +++ b/drivers/target/iscsi/iscsi_target_device.c @@ -21,7 +21,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_device.h" #include "iscsi_target_tpg.h" #include "iscsi_target_util.h" diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index a0ae5fc0ad75..bdd8731a4daa 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -21,7 +21,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_tq.h" #include "iscsi_target_erl0.h" diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index cda4d80cfaef..2e561deb30a2 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -22,7 +22,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_datain_values.h" #include "iscsi_target_device.h" diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 4ca8fd2a70db..e24f1c7c5862 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -21,7 +21,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_datain_values.h" #include "iscsi_target_util.h" #include "iscsi_target_erl0.h" diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 713c0c1877ab..153fb66ac1b8 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -24,14 +24,14 @@ #include #include -#include "iscsi_target_core.h" +#include +#include #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" diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 62a095f36bf2..8c02fa34716f 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -22,7 +22,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_parameters.h" #include "iscsi_target_login.h" #include "iscsi_target_nego.h" diff --git a/drivers/target/iscsi/iscsi_target_nodeattrib.c b/drivers/target/iscsi/iscsi_target_nodeattrib.c index 16454a922e2b..208cca8a363c 100644 --- a/drivers/target/iscsi/iscsi_target_nodeattrib.c +++ b/drivers/target/iscsi/iscsi_target_nodeattrib.c @@ -18,7 +18,7 @@ #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_device.h" #include "iscsi_target_tpg.h" #include "iscsi_target_util.h" diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 18c29260b4a2..d4f9e9645697 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -18,7 +18,7 @@ #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_util.h" #include "iscsi_target_parameters.h" diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c index ca41b583f2f6..e446a09c886b 100644 --- a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c +++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c @@ -20,7 +20,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_util.h" #include "iscsi_target_tpg.h" #include "iscsi_target_seq_pdu_list.h" diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c index 103395510307..5e1349a3b143 100644 --- a/drivers/target/iscsi/iscsi_target_stat.c +++ b/drivers/target/iscsi/iscsi_target_stat.c @@ -23,12 +23,12 @@ #include #include -#include "iscsi_target_core.h" +#include #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 #ifndef INITIAL_JIFFIES #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) diff --git a/drivers/target/iscsi/iscsi_target_stat.h b/drivers/target/iscsi/iscsi_target_stat.h deleted file mode 100644 index 3ff76b4faad3..000000000000 --- a/drivers/target/iscsi/iscsi_target_stat.h +++ /dev/null @@ -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 ***/ diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index 78404b1cc0bf..b0224a77e26d 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c @@ -23,7 +23,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_datain_values.h" #include "iscsi_target_device.h" diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 9053a3c0c6e5..bdd127c0e3ae 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -20,7 +20,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_erl0.h" #include "iscsi_target_login.h" #include "iscsi_target_nodeattrib.h" diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c index 601e9cc61e98..18e1971b54f8 100644 --- a/drivers/target/iscsi/iscsi_target_tq.c +++ b/drivers/target/iscsi/iscsi_target_tq.c @@ -20,7 +20,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_tq.h" #include "iscsi_target.h" diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index bcd88ec99793..70f57c192415 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -25,7 +25,7 @@ #include #include -#include "iscsi_target_core.h" +#include #include "iscsi_target_parameters.h" #include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_datain_values.h" diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h new file mode 100644 index 000000000000..09a522bae222 --- /dev/null +++ b/include/target/iscsi/iscsi_target_core.h @@ -0,0 +1,883 @@ +#ifndef ISCSI_TARGET_CORE_H +#define ISCSI_TARGET_CORE_H + +#include +#include +#include +#include +#include +#include +#include + +#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, + IFC_SENDTARGETS_ALL = 0x00000100, + IFC_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 */ diff --git a/include/target/iscsi/iscsi_target_stat.h b/include/target/iscsi/iscsi_target_stat.h new file mode 100644 index 000000000000..3ff76b4faad3 --- /dev/null +++ b/include/target/iscsi/iscsi_target_stat.h @@ -0,0 +1,64 @@ +#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 ***/ diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index daef9daa500c..e6bb166f12c2 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -1,6 +1,6 @@ #include #include -#include "../../../drivers/target/iscsi/iscsi_target_core.h" +#include "iscsi_target_core.h" struct iscsit_transport { #define ISCSIT_TRANSPORT_NAME 16 -- cgit v1.2.3 From c1e34b64044318dde74a4cec24a91ff6415f1c48 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 26 Jan 2015 12:49:05 +0200 Subject: iscsi-target: Introduce session_get_next_ttt Reduce code duplication. Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 12 ++---------- drivers/target/iscsi/iscsi_target_util.c | 9 ++------- include/target/iscsi/iscsi_target_core.h | 13 +++++++++++++ 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index dd646c43d16d..5b25faa43c64 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -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); @@ -3047,11 +3043,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); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 70f57c192415..c211d3f2726c 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -939,13 +939,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); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 09a522bae222..5f41a17bdafd 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -880,4 +880,17 @@ struct iscsit_global { struct iscsi_portal_group *discovery_tpg; }; +static inline u32 session_get_next_ttt(struct iscsi_session *session) +{ + u32 ttt; + + spin_lock_bh(&session->ttt_lock); + ttt = session->targ_xfer_tag++; + if (ttt == 0xFFFFFFFF) + ttt = session->targ_xfer_tag++; + spin_unlock_bh(&session->ttt_lock); + + return ttt; +} + #endif /* ISCSI_TARGET_CORE_H */ -- cgit v1.2.3 From be7dcfb683dd7646050666d1f6597ba413a68b22 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 26 Jan 2015 12:49:06 +0200 Subject: iscsi-target: Don't over-allocate sendtargets text resp buffer No reason to allocate a buffer of size bigger than initiator MaxRecvDataSegmentLength. Moreover, we need to respect initiator MRDSL and not send a larger payload. Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 5b25faa43c64..75c29b687f35 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3397,7 +3397,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); -- cgit v1.2.3 From e4f4e8016e6823475291eb0da7cc95d0fada2237 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 9 Feb 2015 18:07:25 +0200 Subject: iscsi/iser-target: Support multi-sequence sendtargets text response In case sendtargets response is larger than initiator MRDSL, we send a partial sendtargets response (setting F=0, C=1, TTT!=0xffffffff), accept a consecutive empty text message and send the rest of the payload. In case we are done, we set F=1, C=0, TTT=0xffffffff. We do that by storing the sendtargets response bytes done under the session. This patch also makes iscsit_find_cmd_from_itt public for isert. (Re-add cmd->maxcmdsn_inc and clear in iscsit_build_text_rsp - nab) Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 18 +++++-- drivers/target/iscsi/iscsi_target.c | 87 ++++++++++++++++++++++++-------- drivers/target/iscsi/iscsi_target_util.c | 1 + drivers/target/iscsi/iscsi_target_util.h | 1 - include/target/iscsi/iscsi_target_core.h | 1 + 5 files changed, 82 insertions(+), 26 deletions(-) (limited to 'drivers/target') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index da8c860e71c1..075b19cc78e8 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1436,9 +1436,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr); break; case ISCSI_OP_TEXT: - cmd = isert_allocate_cmd(conn); - if (!cmd) - break; + if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) { + cmd = iscsit_find_cmd_from_itt(conn, hdr->itt); + if (!cmd) + break; + } else { + cmd = isert_allocate_cmd(conn); + if (!cmd) + break; + } isert_cmd = iscsit_priv_cmd(cmd); ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd, @@ -1660,6 +1666,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) struct isert_conn *isert_conn = isert_cmd->conn; struct iscsi_conn *conn = isert_conn->conn; struct isert_device *device = isert_conn->conn_device; + struct iscsi_text_rsp *hdr; isert_dbg("Cmd %p\n", isert_cmd); @@ -1700,6 +1707,11 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) case ISCSI_OP_REJECT: case ISCSI_OP_NOOP_OUT: case ISCSI_OP_TEXT: + hdr = (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header; + /* If the continue bit is on, keep the command alive */ + if (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE) + break; + spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) list_del_init(&cmd->i_conn_node); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 75c29b687f35..f533a0dfa4de 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1994,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; } @@ -2007,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" @@ -2036,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)) { @@ -3385,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; @@ -3476,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=" @@ -3494,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 & IFC_SENDTARGETS_SINGLE) break; @@ -3520,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; @@ -3535,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) @@ -4013,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; diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index c211d3f2726c..390df8ed72b2 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -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, diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index a68508c4fec8..1ab754a671ff 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -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); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 5f41a17bdafd..04d8f99ea3a2 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -893,4 +893,5 @@ static inline u32 session_get_next_ttt(struct iscsi_session *session) return ttt; } +extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t); #endif /* ISCSI_TARGET_CORE_H */ -- cgit v1.2.3 From 3fd7b60f2c7418239d586e359e0c6d8503e10646 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 22 Jan 2015 00:56:53 -0800 Subject: iscsi-target: Drop problematic active_ts_list usage This patch drops legacy active_ts_list usage within iscsi_target_tq.c code. It was originally used to track the active thread sets during iscsi-target shutdown, and is no longer used by modern upstream code. Two people have reported list corruption using traditional iscsi-target and iser-target with the following backtrace, that appears to be related to iscsi_thread_set->ts_list being used across both active_ts_list and inactive_ts_list. [ 60.782534] ------------[ cut here ]------------ [ 60.782543] WARNING: CPU: 0 PID: 9430 at lib/list_debug.c:53 __list_del_entry+0x63/0xd0() [ 60.782545] list_del corruption, ffff88045b00d180->next is LIST_POISON1 (dead000000100100) [ 60.782546] Modules linked in: ib_srpt tcm_qla2xxx qla2xxx tcm_loop tcm_fc libfc scsi_transport_fc scsi_tgt ib_isert rdma_cm iw_cm ib_addr iscsi_target_mod target_core_pscsi target_core_file target_core_iblock target_core_mod configfs ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT xt_CHECKSUM iptable_mangle iptable_filter ip_tables bridge stp llc autofs4 sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 ib_ipoib ib_cm ib_uverbs ib_umad mlx4_en mlx4_ib ib_sa ib_mad ib_core mlx4_core dm_mirror dm_region_hash dm_log dm_mod vhost_net macvtap macvlan vhost tun kvm_intel kvm uinput iTCO_wdt iTCO_vendor_support microcode serio_raw pcspkr sb_edac edac_core sg i2c_i801 lpc_ich mfd_core mtip32xx igb i2c_algo_bit i2c_core ptp pps_core ioatdma dca wmi ext3(F) jbd(F) mbcache(F) sd_mod(F) crc_t10dif(F) crct10dif_common(F) ahci(F) libahci(F) isci(F) libsas(F) scsi_transport_sas(F) [last unloaded: speedstep_lib] [ 60.782597] CPU: 0 PID: 9430 Comm: iscsi_ttx Tainted: GF 3.12.19+ #2 [ 60.782598] Hardware name: Supermicro X9DRX+-F/X9DRX+-F, BIOS 3.00 07/09/2013 [ 60.782599] 0000000000000035 ffff88044de31d08 ffffffff81553ae7 0000000000000035 [ 60.782602] ffff88044de31d58 ffff88044de31d48 ffffffff8104d1cc 0000000000000002 [ 60.782605] ffff88045b00d180 ffff88045b00d0c0 ffff88045b00d0c0 ffff88044de31e58 [ 60.782607] Call Trace: [ 60.782611] [] dump_stack+0x49/0x62 [ 60.782615] [] warn_slowpath_common+0x8c/0xc0 [ 60.782618] [] warn_slowpath_fmt+0x46/0x50 [ 60.782620] [] __list_del_entry+0x63/0xd0 [ 60.782622] [] list_del+0x11/0x40 [ 60.782630] [] iscsi_del_ts_from_active_list+0x29/0x50 [iscsi_target_mod] [ 60.782635] [] iscsi_tx_thread_pre_handler+0xa1/0x180 [iscsi_target_mod] [ 60.782642] [] iscsi_target_tx_thread+0x4e/0x220 [iscsi_target_mod] [ 60.782647] [] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod] [ 60.782652] [] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod] [ 60.782655] [] kthread+0xce/0xe0 [ 60.782657] [] ? kthread_freezable_should_stop+0x70/0x70 [ 60.782660] [] ret_from_fork+0x7c/0xb0 [ 60.782662] [] ? kthread_freezable_should_stop+0x70/0x70 [ 60.782663] ---[ end trace 9662f4a661d33965 ]--- Since this code is no longer used, go ahead and drop the problematic usage all-together. Reported-by: Gavin Guo Reported-by: Moussa Ba Cc: stable@vger.kernel.org # 3.1+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_tq.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c index 18e1971b54f8..26aa50996473 100644 --- a/drivers/target/iscsi/iscsi_target_tq.c +++ b/drivers/target/iscsi/iscsi_target_tq.c @@ -24,36 +24,22 @@ #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(); -- cgit v1.2.3 From f161d4b44d7cc1dc66b53365215227db356378b1 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 11 Feb 2015 18:34:40 -0800 Subject: target: Fix PR_APTPL_BUF_LEN buffer size limitation This patch addresses the original PR_APTPL_BUF_LEN = 8k limitiation for write-out of PR APTPL metadata that Martin has recently been running into. It changes core_scsi3_update_and_write_aptpl() to use vzalloc'ed memory instead of kzalloc, and increases the default hardcoded length to 256k. It also adds logic in core_scsi3_update_and_write_aptpl() to double the original length upon core_scsi3_update_aptpl_buf() failure, and retries until the vzalloc'ed buffer is large enough to accommodate the outgoing APTPL metadata. Reported-by: Martin Svec Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 25 +++++++++++++------------ include/target/target_core_base.h | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d56f2aaba9af..67fb3bf240cd 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1862,8 +1862,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; } @@ -1880,8 +1880,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; } @@ -1944,7 +1944,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"; @@ -1958,25 +1958,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; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 397fb635766a..eec07656eb03 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -409,7 +409,7 @@ struct t10_reservation { /* Activate Persistence across Target Power Loss enabled * for SCSI device */ int pr_aptpl_active; -#define PR_APTPL_BUF_LEN 8192 +#define PR_APTPL_BUF_LEN 262144 u32 pr_generation; spinlock_t registration_lock; spinlock_t aptpl_reg_lock; -- cgit v1.2.3 From 72859d91d93319c00a18c29f577e56bf73a8654a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 12 Feb 2015 00:48:25 -0800 Subject: iscsi-target: Avoid IN_LOGOUT failure case for iser-target This patch addresses a bug reported during iser-target login/logout stress testing, where iscsit_take_action_for_connection_exit() is incorrectly invoking iscsit_close_connection() twice during IN_LOGOUT state, after connection shutdown has already been initiated by iser-target code. Here is the backtrace: BUG: unable to handle kernel NULL pointer dereference at 00000000000001f0 IP: [] iscsit_take_action_for_connection_exit+0x62/0x110 [iscsi_target_mod] PGD 0 Oops: 0000 [#1] SMP Modules linked in: target_core_pscsi(O) target_core_file(O) target_core_iblock(O) ib_isert(O) iscsi_target_mod(O) ib_srpt(O) tcm_loop(O) tcm_fc(O) target_core_mod(O) mst_pciconf(OE) bonding mlx5_ib(O) mlx5_core libfc scsi_transport_fc netconsole configfs nfsv3 nfs_acl mlx4_ib(O) rdma_ucm(O) ib_ucm(O) rdma_cm(O) iw_cm(O) ib_uverbs(O) libiscsi_tcp libiscsi scsi_transport_iscsi mlx4_en mlx4_core ib_ipoib(O) ib_cm(O) ib_sa(O) ib_umad(O) ib_mad(O) ib_core(O) ib_addr(O) rpcsec_gss_krb5 auth_rpcgss nfsv4 nfs fscache lockd grace autofs4 sunrpc 8021q garp stp llc ipv6 dm_mirror dm_region_hash dm_log dm_multipath uinput ipmi_si ipmi_msghandler acpi_pad iTCO_wdt iTCO_vendor_support dcdbas microcode pcspkr wmi sb_edac edac_core sg lpc_ich mfd_core shpchp tg3 ptp pps_core dm_mod ext3(E) jbd(E) mbcache(E) sr_mod(E) cdrom(E) sd_mod(E) ahci(E) libahci(E) megaraid_sas(E) [last unloaded: target_core_mod] CPU: 2 PID: 5280 Comm: iscsi_ttx Tainted: G W OE 3.18.0-rc2+ #22 Hardware name: Dell Inc. PowerEdge R720/0VWT90, BIOS 2.0.9 03/08/2013 task: ffff8806132f9010 ti: ffff880601d6c000 task.ti: ffff880601d6c000 RIP: 0010:[] [] iscsit_take_action_for_connection_exit+0x62/0x110 [iscsi_target_mod] RSP: 0018:ffff880601d6fe18 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffff8805dc437800 RCX: 0000000000000006 RDX: 0000000000000000 RSI: 0000000000000200 RDI: ffffffffa033d98b RBP: ffff880601d6fe28 R08: 0000000000000000 R09: 000000000000dd37 R10: 00000000ec5d4202 R11: 0000000000000001 R12: ffff8805dc437bf4 R13: ffff88061b831600 R14: ffff880601d6fe58 R15: ffff8806132f9010 FS: 0000000000000000(0000) GS:ffff88032fa20000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000001f0 CR3: 0000000001a14000 CR4: 00000000000407e0 Stack: ffff8805dc437800 fffffffffffffe00 ffff880601d6feb8 ffffffffa034ed40 ffff8806132f9010 ffff880601d6fe70 0f00000000000000 ffff8805d51fbef0 0000000000000000 ffff8806132f9010 ffffffff8108e7f0 ffff880601d6fe70 Call Trace: [] iscsi_target_tx_thread+0x160/0x220 [iscsi_target_mod] [] ? bit_waitqueue+0xb0/0xb0 [] ? iscsit_handle_snack+0x190/0x190 [iscsi_target_mod] [] kthread+0xce/0xf0 [] ? kthread_freezable_should_stop+0x70/0x70 [] ret_from_fork+0x7c/0xb0 [] ? kthread_freezable_should_stop+0x70/0x70 Code: 06 0f 84 82 00 00 00 3c 08 74 4e f6 05 39 e6 02 00 04 0f 85 9e 00 00 00 c6 43 19 08 4c 89 e7 e8 65 2a 26 e1 48 8b 83 a0 04 00 00 <48> 8b 88 f0 01 00 00 80 b9 d8 04 00 00 02 74 2e f6 05 31 e6 02 RIP [] iscsit_take_action_for_connection_exit+0x62/0x110 [iscsi_target_mod] RSP CR2: 00000000000001f0 ---[ end trace a0c33436cd0836b4 ]--- This special case is still required by ISCSI_TCP transport during a iscsit_handle_logout_cmd() failure case in iscsi_target_rx_opcode(), but must be avoided for iser-target. Reported-by: Sagi Grimberg Reported-by: Slava Shwartsman Cc: Sagi Grimberg Cc: Slava Shwartsman Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_erl0.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index bdd8731a4daa..1c197bad6132 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -22,6 +22,7 @@ #include #include +#include #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; } -- cgit v1.2.3 From 8e575c50a171f2579e367a7f778f86477dfdaf49 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Feb 2015 22:09:47 +0000 Subject: target: Add missing WRITE_SAME end-of-device sanity check This patch adds a check to sbc_setup_write_same() to verify the incoming WRITE_SAME LBA + number of blocks does not exceed past the end-of-device. Also check for potential LBA wrap-around as well. Reported-by: Bart Van Assche Cc: Martin Petersen Cc: Christoph Hellwig Cc: stable@vger.kernel.org # 3.8+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 11bea1952435..b26b52f441a1 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -251,6 +251,8 @@ 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); if ((flags[0] & 0x04) || (flags[0] & 0x02)) { @@ -264,6 +266,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"); -- cgit v1.2.3 From aa179935edea9a64dec4b757090c8106a3907ffa Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Feb 2015 22:27:40 +0000 Subject: target: Check for LBA + sectors wrap-around in sbc_parse_cdb This patch adds a check to sbc_parse_cdb() in order to detect when an LBA + sector vs. end-of-device calculation wraps when the LBA is sufficently large enough (eg: 0xFFFFFFFFFFFFFFFF). Cc: Martin Petersen Cc: Christoph Hellwig Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index b26b52f441a1..17259c05450e 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -982,7 +982,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) } 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); -- cgit v1.2.3 From f7b7c06f386c5e990acb87a8bc96137b9f978977 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Feb 2015 22:49:38 +0000 Subject: target: Fail I/O with PROTECT bit when protection is unsupported This patch adds an explicit check for WRPROTECT + RDPROTECT bit usage within sbc_check_prot(), and fails with TCM_INVALID_CDB_FIELD if the backend device does not have protection enabled. Also, update sbc_check_prot() to return sense_reason_t in order to propigate up the correct sense ASQ. Cc: Martin Petersen Cc: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 51 +++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 17259c05450e..1bb8b4a93a66 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -626,14 +626,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: @@ -641,7 +648,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; @@ -650,12 +657,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; @@ -674,7 +681,7 @@ 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; } sense_reason_t @@ -698,8 +705,9 @@ 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; + 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; @@ -709,8 +717,9 @@ 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; + 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; @@ -720,8 +729,9 @@ 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; + 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; @@ -739,8 +749,9 @@ 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; + ret = sbc_check_prot(dev, cmd, cdb, sectors, true); + if (ret) + return ret; if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; @@ -752,8 +763,9 @@ 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; + ret = sbc_check_prot(dev, cmd, cdb, sectors, true); + if (ret) + return ret; if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; @@ -765,8 +777,9 @@ 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; + ret = sbc_check_prot(dev, cmd, cdb, sectors, true); + if (ret) + return ret; if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; -- cgit v1.2.3 From afd73f1b60fc5883ea4982f68e9522e77b28f1e5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 14 Feb 2015 01:32:11 +0000 Subject: target: Perform PROTECT sanity checks for WRITE_SAME This patch adds a call to sbc_check_prot() within sbc_setup_write_same() code to perform the various protection releated sanity checks, including failing if WRPROTECT or RDPROTECT is set for a backend device that has not advertised support for T10-PI. Also, since WRITE_SAME + T10-PI is currently not supported by IBLOCK + FILEIO backends, go ahead and fail if ->execute_write_same() is invoked with a non zero cmd->prot_op. Cc: Martin Petersen Cc: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 5 +++++ drivers/target/target_core_iblock.c | 5 +++++ drivers/target/target_core_sbc.c | 8 ++++++++ 3 files changed, 18 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index c2aea099ea4a..9f1ed773e976 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -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 || diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 3efff94fbd97..303299efa3a6 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -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 || diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 1bb8b4a93a66..87cbbe220151 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -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) { @@ -254,6 +257,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o 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" @@ -295,6 +299,10 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o 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; } -- cgit v1.2.3 From fde9f50f80fe89a9115b4bfa773017272597d85d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Feb 2015 23:28:27 +0000 Subject: target: Add sanity checks for DPO/FUA bit usage This patch adds a sbc_check_dpofua() function that performs sanity checks for DPO/FUA command bits. It introduces checks to fail when either bit is set, but the backend device is not advertising support for them. It also moves the existing cmd->se_cmd_flags |= SCF_FUA assignement into the new helper function. Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 87cbbe220151..856e800926b8 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -692,6 +692,29 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, 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 sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) { @@ -713,6 +736,9 @@ 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_dpofua(dev, cmd, cdb)) + return TCM_INVALID_CDB_FIELD; + ret = sbc_check_prot(dev, cmd, cdb, sectors, false); if (ret) return ret; @@ -725,6 +751,9 @@ 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_dpofua(dev, cmd, cdb)) + return TCM_INVALID_CDB_FIELD; + ret = sbc_check_prot(dev, cmd, cdb, sectors, false); if (ret) return ret; @@ -737,6 +766,9 @@ 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_dpofua(dev, cmd, cdb)) + return TCM_INVALID_CDB_FIELD; + ret = sbc_check_prot(dev, cmd, cdb, sectors, false); if (ret) return ret; @@ -757,12 +789,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_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; @@ -771,12 +804,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_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; @@ -785,12 +819,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_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; @@ -801,6 +836,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; @@ -810,8 +848,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: { @@ -820,6 +856,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. @@ -834,8 +872,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); -- cgit v1.2.3 From d0a91295557666f9e58b79b5177a98229007803b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 14 Feb 2015 01:56:19 +0000 Subject: target: Fail WRITE_SAME w/ UNMAP=1 when emulate_tpws=0 This patch adds a check within sbc_setup_write_same() to fail a WRITE_SAME w/ UNMAP=1 op, if the backend device has emulate_tpws disabled. Cc: Martin Petersen Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 856e800926b8..0d307c34f08e 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -293,6 +293,11 @@ 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; } -- cgit v1.2.3 From 61fdb4acc8411bf50589bc67431ad12e21e7678a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 14 Feb 2015 02:29:50 +0000 Subject: target: Fail UNMAP when emulate_tpu=0 This patch adds a check within sbc_parse_cdb() to fail a UNMAP op, if the backend device has emulate_tpu disabled. Cc: Martin Petersen Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 0d307c34f08e..9661a6626b2d 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -962,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; -- cgit v1.2.3 From aa04dae454d087376d97f44710c4422df030a8f2 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 14 Feb 2015 02:05:31 +0000 Subject: target: Set LBPWS10 bit in Logical Block Provisioning EVPD This patch sets the missing LBPWS10 bit within spc_emulate_evpd_b2() in order to signal WRITE_SAME (10) w/ UNMAP support, following the existing LBPWS bit to signal WRITE_SAME (16) w/ UNMAP support. Cc: Martin Petersen Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_spc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 1307600fe726..f041f936a6cd 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -650,7 +650,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; } -- cgit v1.2.3