diff options
Diffstat (limited to 'include/target/target_core_base.h')
| -rw-r--r-- | include/target/target_core_base.h | 274 |
1 files changed, 190 insertions, 84 deletions
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 516764febeb7..7016d93fa383 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -1,9 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef TARGET_CORE_BASE_H #define TARGET_CORE_BASE_H #include <linux/configfs.h> /* struct config_group */ #include <linux/dma-direction.h> /* enum dma_data_direction */ -#include <linux/percpu_ida.h> /* struct percpu_ida */ +#include <linux/sbitmap.h> #include <linux/percpu-refcount.h> #include <linux/semaphore.h> /* struct semaphore */ #include <linux/completion.h> @@ -45,6 +46,10 @@ /* Used by transport_get_inquiry_vpd_device_ident() */ #define INQUIRY_VPD_DEVICE_IDENTIFIER_LEN 254 +#define INQUIRY_VENDOR_LEN 8 +#define INQUIRY_MODEL_LEN 16 +#define INQUIRY_REVISION_LEN 4 + /* Attempts before moving from SHORT to LONG */ #define PYX_TRANSPORT_WINDOW_CLOSED_THRESHOLD 3 #define PYX_TRANSPORT_WINDOW_CLOSED_WAIT_SHORT 3 /* In milliseconds */ @@ -69,8 +74,6 @@ #define DA_EMULATE_MODEL_ALIAS 0 /* Emulation for WriteCache and SYNCHRONIZE_CACHE */ #define DA_EMULATE_WRITE_CACHE 0 -/* Emulation for UNIT ATTENTION Interlock Control */ -#define DA_EMULATE_UA_INTLLCK_CTRL 0 /* Emulation for TASK_ABORTED status (TAS) by default */ #define DA_EMULATE_TAS 1 /* Emulation for Thin Provisioning UNMAP using block/blk-lib.c:blkdev_issue_discard() */ @@ -86,6 +89,10 @@ #define DA_EMULATE_3PC 1 /* No Emulation for PSCSI by default */ #define DA_EMULATE_ALUA 0 +/* Emulate SCSI2 RESERVE/RELEASE and Persistent Reservations by default */ +#define DA_EMULATE_PR 1 +/* Emulation for REPORT SUPPORTED OPERATION CODES */ +#define DA_EMULATE_RSOC 1 /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ #define DA_ENFORCE_PR_ISIDS 1 /* Force SPC-3 PR Activate Persistence across Target Power Loss */ @@ -101,6 +108,15 @@ #define SE_MODE_PAGE_BUF 512 #define SE_SENSE_BUF 96 +enum target_submit_type { + /* Use the fabric driver's default submission type */ + TARGET_FABRIC_DEFAULT_SUBMIT, + /* Submit from the calling context */ + TARGET_DIRECT_SUBMIT, + /* Defer submission to the LIO workqueue */ + TARGET_QUEUE_SUBMIT, +}; + /* struct se_hba->hba_flags */ enum hba_flags_table { HBA_FLAGS_INTERNAL_USE = 0x01, @@ -122,26 +138,27 @@ enum transport_state_table { /* Used for struct se_cmd->se_cmd_flags */ enum se_cmd_flags_table { - SCF_SUPPORTED_SAM_OPCODE = 0x00000001, - SCF_TRANSPORT_TASK_SENSE = 0x00000002, - SCF_EMULATED_TASK_SENSE = 0x00000004, - SCF_SCSI_DATA_CDB = 0x00000008, - SCF_SCSI_TMR_CDB = 0x00000010, - SCF_FUA = 0x00000080, - SCF_SE_LUN_CMD = 0x00000100, - SCF_BIDI = 0x00000400, - SCF_SENT_CHECK_CONDITION = 0x00000800, - SCF_OVERFLOW_BIT = 0x00001000, - SCF_UNDERFLOW_BIT = 0x00002000, - SCF_SEND_DELAYED_TAS = 0x00004000, - SCF_ALUA_NON_OPTIMIZED = 0x00008000, - SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, - SCF_COMPARE_AND_WRITE = 0x00080000, - SCF_COMPARE_AND_WRITE_POST = 0x00100000, - SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000, - SCF_ACK_KREF = 0x00400000, - SCF_USE_CPUID = 0x00800000, - SCF_TASK_ATTR_SET = 0x01000000, + SCF_SUPPORTED_SAM_OPCODE = (1 << 0), + SCF_TRANSPORT_TASK_SENSE = (1 << 1), + SCF_EMULATED_TASK_SENSE = (1 << 2), + SCF_SCSI_DATA_CDB = (1 << 3), + SCF_SCSI_TMR_CDB = (1 << 4), + SCF_FUA = (1 << 5), + SCF_SE_LUN_CMD = (1 << 6), + SCF_BIDI = (1 << 7), + SCF_SENT_CHECK_CONDITION = (1 << 8), + SCF_OVERFLOW_BIT = (1 << 9), + SCF_UNDERFLOW_BIT = (1 << 10), + SCF_ALUA_NON_OPTIMIZED = (1 << 11), + SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = (1 << 12), + SCF_COMPARE_AND_WRITE = (1 << 13), + SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = (1 << 14), + SCF_ACK_KREF = (1 << 15), + SCF_USE_CPUID = (1 << 16), + SCF_TASK_ATTR_SET = (1 << 17), + SCF_TREAT_READ_AS_NORMAL = (1 << 18), + SCF_TASK_ORDERED_SYNC = (1 << 19), + SCF_ATOMIC = (1 << 20), }; /* @@ -167,7 +184,7 @@ enum tcm_sense_reason_table { TCM_WRITE_PROTECTED = R(0x0c), TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d), TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e), - TCM_CHECK_CONDITION_NOT_READY = R(0x0f), + TCM_RESERVATION_CONFLICT = R(0x10), TCM_ADDRESS_OUT_OF_RANGE = R(0x11), TCM_OUT_OF_RESOURCES = R(0x12), @@ -181,6 +198,13 @@ enum tcm_sense_reason_table { TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a), TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b), TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c), + TCM_INSUFFICIENT_REGISTRATION_RESOURCES = R(0x1d), + TCM_LUN_BUSY = R(0x1e), + TCM_INVALID_FIELD_IN_COMMAND_IU = R(0x1f), + TCM_ALUA_TG_PT_STANDBY = R(0x20), + TCM_ALUA_TG_PT_UNAVAILABLE = R(0x21), + TCM_ALUA_STATE_TRANSITION = R(0x22), + TCM_ALUA_OFFLINE = R(0x23), #undef R }; @@ -189,7 +213,6 @@ enum target_sc_flags_table { TARGET_SCF_ACK_KREF = 0x02, TARGET_SCF_UNKNOWN_SIZE = 0x04, TARGET_SCF_USE_CPUID = 0x08, - TARGET_SCF_LOOKUP_LUN_FROM_TAG = 0x10, }; /* fabric independent task management function values */ @@ -201,6 +224,7 @@ enum tcm_tmreq_table { TMR_LUN_RESET = 5, TMR_TARGET_WARM_RESET = 6, TMR_TARGET_COLD_RESET = 7, + TMR_LUN_RESET_PRO = 0x80, TMR_UNKNOWN = 0xff, }; @@ -311,10 +335,15 @@ struct t10_vpd { }; struct t10_wwn { - char vendor[8]; - char model[16]; - char revision[4]; + /* + * SCSI left aligned strings may not be null terminated. +1 to ensure a + * null terminator is always present. + */ + char vendor[INQUIRY_VENDOR_LEN + 1]; + char model[INQUIRY_MODEL_LEN + 1]; + char revision[INQUIRY_REVISION_LEN + 1]; char unit_serial[INQUIRY_VPD_SERIAL_LEN]; + u32 company_id; spinlock_t t10_vpd_lock; struct se_device *t10_dev; struct config_group t10_wwn_group; @@ -421,6 +450,13 @@ enum target_prot_type { TARGET_DIF_TYPE3_PROT, }; +/* Emulation for UNIT ATTENTION Interlock Control */ +enum target_ua_intlck_ctrl { + TARGET_UA_INTLCK_CTRL_CLEAR = 0, + TARGET_UA_INTLCK_CTRL_NO_CLEAR = 1, + TARGET_UA_INTLCK_CTRL_ESTABLISH_UA = 2, +}; + enum target_core_dif_check { TARGET_DIF_CHECK_GUARD = 0x1 << 0, TARGET_DIF_CHECK_APPTAG = 0x1 << 1, @@ -434,12 +470,11 @@ enum target_core_dif_check { #define TCM_ACA_TAG 0x24 struct se_cmd { + /* Used for fail with specific sense codes */ + sense_reason_t sense_reason; /* SAM response code being sent to initiator */ u8 scsi_status; - u8 scsi_asc; - u8 scsi_ascq; u16 scsi_sense_length; - unsigned cmd_wait_set:1; unsigned unknown_data_length:1; bool state_active:1; u64 tag; /* SAM command identifier aka task tag */ @@ -451,6 +486,7 @@ struct se_cmd { int sam_task_attr; /* Used for se_sess->sess_tag_pool */ unsigned int map_tag; + int map_cpu; /* Transport protocol dependent state, see transport_state_table */ enum transport_state_table t_state; /* See se_cmd_flags_table */ @@ -469,9 +505,11 @@ struct se_cmd { struct se_lun *se_lun; /* Only used for internal passthrough and legacy TCM fabric modules */ struct se_session *se_sess; + struct target_cmd_counter *cmd_cnt; struct se_tmr_req *se_tmr_req; - struct list_head se_cmd_list; - struct completion cmd_wait_comp; + struct llist_node se_cmd_list; + struct completion *free_compl; + struct completion *abrt_compl; const struct target_core_fabric_ops *se_tfo; sense_reason_t (*execute_cmd)(struct se_cmd *); sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool, int *); @@ -521,7 +559,11 @@ struct se_cmd { struct scatterlist *t_prot_sg; unsigned int t_prot_nents; sense_reason_t pi_err; - sector_t bad_sector; + u64 sense_info; + /* + * CPU LIO will execute the cmd on. Defaults to the CPU the cmd is + * initialized on. Drivers can override. + */ int cpuid; }; @@ -589,8 +631,14 @@ static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item) acl_fabric_stat_group); } +struct target_cmd_counter { + struct percpu_ref refcnt; + wait_queue_head_t refcnt_wq; + struct completion stop_done; + atomic_t stopped; +}; + struct se_session { - unsigned sess_tearing_down:1; u64 sess_bin_isid; enum target_prot_op sup_prot_ops; enum target_prot_type sess_prot_type; @@ -599,11 +647,10 @@ struct se_session { void *fabric_sess_ptr; struct list_head sess_list; struct list_head sess_acl_list; - struct list_head sess_cmd_list; - struct list_head sess_wait_list; spinlock_t sess_cmd_lock; void *sess_cmd_map; - struct percpu_ida sess_tag_pool; + struct sbitmap_queue sess_tag_pool; + struct target_cmd_counter *cmd_cnt; }; struct se_device; @@ -624,22 +671,25 @@ struct se_lun_acl { struct se_ml_stat_grps ml_stat_grps; }; +struct se_dev_entry_io_stats { + u64 total_cmds; + u64 read_bytes; + u64 write_bytes; +}; + struct se_dev_entry { u64 mapped_lun; u64 pr_res_key; u64 creation_time; bool lun_access_ro; u32 attach_count; - atomic_long_t total_cmds; - atomic_long_t read_bytes; - atomic_long_t write_bytes; - atomic_t ua_count; + struct se_dev_entry_io_stats __percpu *stats; /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ struct kref pr_kref; struct completion pr_comp; - struct se_lun_acl __rcu *se_lun_acl; + struct se_lun_acl *se_lun_acl; spinlock_t ua_lock; - struct se_lun __rcu *se_lun; + struct se_lun *se_lun; #define DEF_PR_REG_ACTIVE 1 unsigned long deve_flags; struct list_head alua_port_list; @@ -650,26 +700,27 @@ struct se_dev_entry { }; struct se_dev_attrib { - int emulate_model_alias; - int emulate_dpo; - int emulate_fua_write; - int emulate_fua_read; - int emulate_write_cache; - int emulate_ua_intlck_ctrl; - int emulate_tas; - int emulate_tpu; - int emulate_tpws; - int emulate_caw; - int emulate_3pc; - int pi_prot_format; + bool emulate_model_alias; + bool emulate_dpo; /* deprecated */ + bool emulate_fua_write; + bool emulate_fua_read; /* deprecated */ + bool emulate_write_cache; + enum target_ua_intlck_ctrl emulate_ua_intlck_ctrl; + bool emulate_tas; + bool emulate_tpu; + bool emulate_tpws; + bool emulate_caw; + bool emulate_3pc; + bool emulate_pr; + bool emulate_rsoc; enum target_prot_type pi_prot_type; enum target_prot_type hw_pi_prot_type; - int pi_prot_verify; - int enforce_pr_isids; - int force_pr_aptpl; - int is_nonrot; - int emulate_rest_reord; - int unmap_zeroes_data; + bool pi_prot_verify; + bool enforce_pr_isids; + bool force_pr_aptpl; + bool is_nonrot; + bool emulate_rest_reord; + bool unmap_zeroes_data; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; @@ -681,7 +732,12 @@ struct se_dev_attrib { u32 unmap_granularity; u32 unmap_granularity_alignment; u32 max_write_same_len; - u32 max_bytes_per_io; + u32 atomic_max_len; + u32 atomic_alignment; + u32 atomic_granularity; + u32 atomic_max_with_boundary; + u32 atomic_max_boundary; + u8 submit_type; struct se_device *da_dev; struct config_group da_group; }; @@ -694,9 +750,9 @@ struct se_port_stat_grps { }; struct scsi_port_stats { - atomic_long_t cmd_pdus; - atomic_long_t tx_data_octets; - atomic_long_t rx_data_octets; + u64 cmd_pdus; + u64 tx_data_octets; + u64 rx_data_octets; }; struct se_lun { @@ -705,8 +761,6 @@ struct se_lun { bool lun_access_ro; u32 lun_index; - /* RELATIVE TARGET PORT IDENTIFER */ - u16 lun_rtpi; atomic_t lun_acl_count; struct se_device __rcu *lun_se_dev; @@ -721,14 +775,13 @@ struct se_lun { /* ALUA target port group linkage */ struct list_head lun_tg_pt_gp_link; - struct t10_alua_tg_pt_gp *lun_tg_pt_gp; + struct t10_alua_tg_pt_gp __rcu *lun_tg_pt_gp; spinlock_t lun_tg_pt_gp_lock; struct se_portal_group *lun_tpg; - struct scsi_port_stats lun_stats; + struct scsi_port_stats __percpu *lun_stats; struct config_group lun_group; struct se_port_stat_grps port_stat_grps; - struct completion lun_ref_comp; struct completion lun_shutdown_comp; struct percpu_ref lun_ref; struct list_head lun_dev_link; @@ -743,9 +796,28 @@ struct se_dev_stat_grps { struct config_group scsi_lu_group; }; +struct se_cmd_queue { + struct llist_head cmd_list; + struct work_struct work; +}; + +struct se_dev_plug { + struct se_device *se_dev; +}; + +struct se_device_queue { + struct list_head state_list; + spinlock_t lock; + struct se_cmd_queue sq; +}; + +struct se_dev_io_stats { + u64 total_cmds; + u64 read_bytes; + u64 write_bytes; +}; + struct se_device { - /* RELATIVE TARGET PORT IDENTIFER Counter */ - u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ u32 dev_cur_ordered_id; u32 dev_flags; @@ -755,6 +827,7 @@ struct se_device { #define DF_USING_UDEV_PATH 0x00000008 #define DF_USING_ALIAS 0x00000010 #define DF_READ_ONLY 0x00000020 + u8 transport_flags; /* Physical device queue depth */ u32 queue_depth; /* Used for SPC-2 reservations enforce of ISIDs */ @@ -765,16 +838,13 @@ struct se_device { atomic_long_t num_resets; atomic_long_t aborts_complete; atomic_long_t aborts_no_task; - atomic_long_t num_cmds; - atomic_long_t read_bytes; - atomic_long_t write_bytes; + struct se_dev_io_stats __percpu *stats; /* Active commands on this virtual SE device */ - atomic_t simple_cmds; - atomic_t dev_ordered_sync; + struct percpu_ref non_ordered; + bool ordered_sync_in_progress; atomic_t dev_qf_count; u32 export_count; spinlock_t delayed_cmd_lock; - spinlock_t execute_task_lock; spinlock_t dev_reservation_lock; unsigned int dev_reservation_flags; #define DRF_SPC2_RESERVATIONS 0x00000001 @@ -783,18 +853,17 @@ struct se_device { spinlock_t se_tmr_lock; spinlock_t qf_cmd_lock; struct semaphore caw_sem; - /* Used for legacy SPC-2 reservationsa */ - struct se_node_acl *dev_reserved_node_acl; + /* Used for legacy SPC-2 reservations */ + struct se_session *reservation_holder; /* Used for ALUA Logical Unit Group membership */ struct t10_alua_lu_gp_member *dev_alua_lu_gp_mem; /* Used for SPC-3 Persistent Reservations */ struct t10_pr_registration *dev_pr_res_holder; struct list_head dev_sep_list; struct list_head dev_tmr_list; - struct workqueue_struct *tmr_wq; struct work_struct qf_work_queue; + struct work_struct delayed_cmd_work; struct list_head delayed_cmd_list; - struct list_head state_list; struct list_head qf_cmd_list; /* Pointer to associated SE HBA */ struct se_hba *se_hba; @@ -805,6 +874,7 @@ struct se_device { /* T10 SPC-2 + SPC-3 Reservations */ struct t10_reservation t10_pr; struct se_dev_attrib dev_attrib; + struct config_group dev_action_group; struct config_group dev_group; struct config_group dev_pr_group; struct se_dev_stat_grps dev_stat_grps; @@ -820,6 +890,25 @@ struct se_device { /* For se_lun->lun_se_dev RCU read-side critical access */ u32 hba_index; struct rcu_head rcu_head; + int queue_cnt; + struct se_device_queue *queues; + struct mutex lun_reset_mutex; +}; + +struct target_opcode_descriptor { + u8 support:3; + u8 serv_action_valid:1; + u8 opcode; + u16 service_action; + u32 cdb_size; + u8 specific_timeout; + u16 nominal_timeout; + u16 recommended_timeout; + bool (*enabled)(const struct target_opcode_descriptor *descr, + struct se_cmd *cmd); + void (*update_usage_bits)(u8 *usage_bits, + struct se_device *dev); + u8 usage_bits[]; }; struct se_hba { @@ -857,6 +946,10 @@ struct se_portal_group { * Negative values can be used by fabric drivers for internal use TPGs. */ int proto_id; + bool enabled; + /* RELATIVE TARGET PORT IDENTIFIER */ + u16 tpg_rtpi; + bool rtpi_manual; /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ atomic_t tpg_pr_ref_count; /* Spinlock for adding/removing ACLed Nodes */ @@ -864,7 +957,6 @@ struct se_portal_group { /* Spinlock for adding/removing sessions */ spinlock_t session_lock; struct mutex tpg_lun_mutex; - struct list_head se_tpg_node; /* linked list for initiator ACL list */ struct list_head acl_node_list; struct hlist_head tpg_lun_hlist; @@ -907,11 +999,20 @@ static inline struct se_portal_group *param_to_tpg(struct config_item *item) tpg_param_group); } +enum { + /* Use se_cmd's cpuid for completion */ + SE_COMPL_AFFINITY_CPUID = -1, + /* Complete on current CPU */ + SE_COMPL_AFFINITY_CURR_CPU = -2, +}; + struct se_wwn { struct target_fabric_configfs *wwn_tf; void *priv; struct config_group wwn_group; struct config_group fabric_stat_group; + struct config_group param_group; + int cmd_compl_affinity; }; static inline void atomic_inc_mb(atomic_t *v) @@ -928,4 +1029,9 @@ static inline void atomic_dec_mb(atomic_t *v) smp_mb__after_atomic(); } +static inline void target_free_tag(struct se_session *sess, struct se_cmd *cmd) +{ + sbitmap_queue_clear(&sess->sess_tag_pool, cmd->map_tag, cmd->map_cpu); +} + #endif /* TARGET_CORE_BASE_H */ |
