typedef char __s8; typedef unsigned char __u8; typedef short __s16; typedef unsigned short __u16; typedef int __s32; typedef unsigned int __u32; typedef long long __s64; typedef unsigned long long __u64; typedef signed char s8; typedef unsigned char u8; typedef signed short s16; typedef unsigned short u16; typedef signed int s32; typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; enum { false = 0, true = 1 }; typedef struct { unsigned long fds_bits[1024 / (8 * sizeof(long))]; } __kernel_fd_set; typedef void (*__kernel_sighandler_t)(int); typedef int __kernel_key_t; typedef int __kernel_mqd_t; typedef long __kernel_long_t; typedef unsigned long __kernel_ulong_t; typedef __kernel_ulong_t __kernel_ino_t; typedef unsigned int __kernel_mode_t; typedef int __kernel_pid_t; typedef int __kernel_ipc_pid_t; typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; typedef __kernel_long_t __kernel_suseconds_t; typedef int __kernel_daddr_t; typedef unsigned int __kernel_uid32_t; typedef unsigned int __kernel_gid32_t; typedef __kernel_uid_t __kernel_old_uid_t; typedef __kernel_gid_t __kernel_old_gid_t; typedef unsigned int __kernel_old_dev_t; typedef unsigned int __kernel_size_t; typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; typedef struct { int val[2]; } __kernel_fsid_t; typedef __kernel_long_t __kernel_off_t; typedef long long __kernel_loff_t; typedef __kernel_long_t __kernel_time_t; typedef __kernel_long_t __kernel_clock_t; typedef int __kernel_timer_t; typedef int __kernel_clockid_t; typedef char * __kernel_caddr_t; typedef unsigned short __kernel_uid16_t; typedef unsigned short __kernel_gid16_t; typedef __u16 __le16; typedef __u16 __be16; typedef __u32 __le32; typedef __u32 __be32; typedef __u64 __le64; typedef __u64 __be64; typedef __u16 __sum16; typedef __u32 __wsum; typedef __u32 __kernel_dev_t; typedef __kernel_fd_set fd_set; typedef __kernel_dev_t dev_t; typedef __kernel_ino_t ino_t; typedef __kernel_mode_t mode_t; typedef unsigned short umode_t; typedef __u32 nlink_t; typedef __kernel_off_t off_t; typedef __kernel_pid_t pid_t; typedef __kernel_daddr_t daddr_t; typedef __kernel_key_t key_t; typedef __kernel_suseconds_t suseconds_t; typedef __kernel_timer_t timer_t; typedef __kernel_clockid_t clockid_t; typedef __kernel_mqd_t mqd_t; typedef _Bool bool; typedef __kernel_uid32_t uid_t; typedef __kernel_gid32_t gid_t; typedef __kernel_uid16_t uid16_t; typedef __kernel_gid16_t gid16_t; typedef unsigned long uintptr_t; typedef __kernel_loff_t loff_t; typedef __kernel_size_t size_t; typedef __kernel_ssize_t ssize_t; typedef __kernel_ptrdiff_t ptrdiff_t; typedef __kernel_time_t time_t; typedef __kernel_clock_t clock_t; typedef __kernel_caddr_t caddr_t; typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned char unchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef __u8 u_int8_t; typedef __s8 int8_t; typedef __u16 u_int16_t; typedef __s16 int16_t; typedef __u32 u_int32_t; typedef __s32 int32_t; typedef __u8 uint8_t; typedef __u16 uint16_t; typedef __u32 uint32_t; typedef __u64 uint64_t; typedef __u64 u_int64_t; typedef __s64 int64_t; typedef u64 sector_t; typedef u64 blkcnt_t; typedef u32 dma_addr_t; typedef unsigned gfp_t; typedef unsigned fmode_t; typedef unsigned oom_flags_t; typedef u32 phys_addr_t; typedef phys_addr_t resource_size_t; typedef unsigned long irq_hw_number_t; typedef struct { int counter; } atomic_t; struct list_head { struct list_head *next, *prev; }; typedef struct { volatile unsigned int slock; } arch_spinlock_t; typedef struct raw_spinlock { arch_spinlock_t raw_lock; unsigned int magic, owner_cpu; void *owner; } raw_spinlock_t; typedef struct spinlock { union { struct raw_spinlock rlock; }; } spinlock_t; typedef atomic_t atomic_long_t; typedef struct __wait_queue wait_queue_t; typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key); struct __wait_queue { unsigned int flags; void *private; wait_queue_func_t func; struct list_head task_list; }; struct wait_bit_key { void *flags; int bit_nr; }; struct wait_bit_queue { struct wait_bit_key key; wait_queue_t wait; }; struct __wait_queue_head { spinlock_t lock; struct list_head task_list; }; typedef struct __wait_queue_head wait_queue_head_t; struct mutex { atomic_t count; spinlock_t wait_lock; struct list_head wait_list; struct task_struct *owner; const char *name; void *magic; }; typedef struct cpumask { unsigned long bits[(((2) + (8 * sizeof(long)) - 1) / (8 * sizeof(long)))]; } cpumask_t; struct completion { unsigned int done; wait_queue_head_t wait; }; struct workqueue_struct; struct work_struct; typedef void (*work_func_t)(struct work_struct *work); void delayed_work_timer_fn(unsigned long __data); enum { WORK_STRUCT_PENDING_BIT = 0, WORK_STRUCT_DELAYED_BIT = 1, WORK_STRUCT_PWQ_BIT = 2, WORK_STRUCT_LINKED_BIT = 3, WORK_STRUCT_STATIC_BIT = 4, WORK_STRUCT_COLOR_SHIFT = 5, WORK_STRUCT_COLOR_BITS = 4, WORK_STRUCT_PENDING = 1 << WORK_STRUCT_PENDING_BIT, WORK_STRUCT_DELAYED = 1 << WORK_STRUCT_DELAYED_BIT, WORK_STRUCT_PWQ = 1 << WORK_STRUCT_PWQ_BIT, WORK_STRUCT_LINKED = 1 << WORK_STRUCT_LINKED_BIT, WORK_STRUCT_STATIC = 1 << WORK_STRUCT_STATIC_BIT, WORK_NR_COLORS = (1 << WORK_STRUCT_COLOR_BITS) - 1, WORK_NO_COLOR = WORK_NR_COLORS, WORK_CPU_UNBOUND = 2, WORK_CPU_END = 2 + 1, WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + WORK_STRUCT_COLOR_BITS, WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), WORK_OFFQ_FLAG_BITS = 1, WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, WORK_OFFQ_LEFT = 32 - WORK_OFFQ_POOL_SHIFT, WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31, WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1, WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT, WORK_BUSY_PENDING = 1 << 0, WORK_BUSY_RUNNING = 1 << 1, WORKER_DESC_LEN = 24, }; struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func; }; struct kref { atomic_t refcount; }; enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, DMA_FROM_DEVICE = 2, DMA_NONE = 3, }; struct semaphore { raw_spinlock_t lock; unsigned int count; struct list_head wait_list; }; struct config_item { char *ci_name; char ci_namebuf[20]; struct kref ci_kref; struct list_head ci_entry; struct config_item *ci_parent; struct config_group *ci_group; struct config_item_type *ci_type; struct dentry *ci_dentry; }; struct config_item_type { struct module *ct_owner; struct configfs_item_operations *ct_item_ops; struct configfs_group_operations *ct_group_ops; struct configfs_attribute **ct_attrs; }; struct config_group { struct config_item cg_item; struct list_head cg_children; struct configfs_subsystem *cg_subsys; struct config_group **default_groups; }; struct configfs_attribute { const char *ca_name; struct module *ca_owner; umode_t ca_mode; }; struct percpu_ida_cpu; struct percpu_ida { unsigned nr_tags; struct percpu_ida_cpu *tag_cpu; cpumask_t cpus_have_tags; struct { spinlock_t lock; unsigned cpu_last_stolen; wait_queue_head_t wait; unsigned nr_free; unsigned *freelist; } __attribute__((__aligned__((1 << 6)))); }; enum hba_flags_table { HBA_FLAGS_INTERNAL_USE = 0x01, HBA_FLAGS_PSCSI_MODE = 0x02, }; enum transport_lun_status_table { TRANSPORT_LUN_STATUS_FREE = 0, TRANSPORT_LUN_STATUS_ACTIVE = 1, }; enum transport_tpg_type_table { TRANSPORT_TPG_TYPE_NORMAL = 0, TRANSPORT_TPG_TYPE_DISCOVERY = 1, }; enum transport_state_table { TRANSPORT_NO_STATE = 0, TRANSPORT_NEW_CMD = 1, TRANSPORT_WRITE_PENDING = 3, TRANSPORT_PROCESSING = 5, TRANSPORT_COMPLETE = 6, TRANSPORT_ISTATE_PROCESSING = 11, TRANSPORT_COMPLETE_QF_WP = 18, TRANSPORT_COMPLETE_QF_OK = 19, }; 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_SENT_DELAYED_TAS = 0x00004000, SCF_ALUA_NON_OPTIMIZED = 0x00008000, SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, SCF_ACK_KREF = 0x00040000, SCF_COMPARE_AND_WRITE = 0x00080000, SCF_COMPARE_AND_WRITE_POST = 0x00100000, SCF_CMD_XCOPY_PASSTHROUGH = 0x00200000, }; enum transport_lunflags_table { TRANSPORT_LUNFLAGS_NO_ACCESS = 0x00, TRANSPORT_LUNFLAGS_INITIATOR_ACCESS = 0x01, TRANSPORT_LUNFLAGS_READ_ONLY = 0x02, TRANSPORT_LUNFLAGS_READ_WRITE = 0x04, }; typedef unsigned sense_reason_t; enum tcm_sense_reason_table { TCM_NO_SENSE = ( sense_reason_t )(0x00), TCM_NON_EXISTENT_LUN = ( sense_reason_t )(0x01), TCM_UNSUPPORTED_SCSI_OPCODE = ( sense_reason_t )(0x02), TCM_INCORRECT_AMOUNT_OF_DATA = ( sense_reason_t )(0x03), TCM_UNEXPECTED_UNSOLICITED_DATA = ( sense_reason_t )(0x04), TCM_SERVICE_CRC_ERROR = ( sense_reason_t )(0x05), TCM_SNACK_REJECTED = ( sense_reason_t )(0x06), TCM_SECTOR_COUNT_TOO_MANY = ( sense_reason_t )(0x07), TCM_INVALID_CDB_FIELD = ( sense_reason_t )(0x08), TCM_INVALID_PARAMETER_LIST = ( sense_reason_t )(0x09), TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = ( sense_reason_t )(0x0a), TCM_UNKNOWN_MODE_PAGE = ( sense_reason_t )(0x0b), TCM_WRITE_PROTECTED = ( sense_reason_t )(0x0c), TCM_CHECK_CONDITION_ABORT_CMD = ( sense_reason_t )(0x0d), TCM_CHECK_CONDITION_UNIT_ATTENTION = ( sense_reason_t )(0x0e), TCM_CHECK_CONDITION_NOT_READY = ( sense_reason_t )(0x0f), TCM_RESERVATION_CONFLICT = ( sense_reason_t )(0x10), TCM_ADDRESS_OUT_OF_RANGE = ( sense_reason_t )(0x11), TCM_OUT_OF_RESOURCES = ( sense_reason_t )(0x12), TCM_PARAMETER_LIST_LENGTH_ERROR = ( sense_reason_t )(0x13), TCM_MISCOMPARE_VERIFY = ( sense_reason_t )(0x14), }; enum target_sc_flags_table { TARGET_SCF_BIDI_OP = 0x01, TARGET_SCF_ACK_KREF = 0x02, TARGET_SCF_UNKNOWN_SIZE = 0x04, }; enum tcm_tmreq_table { TMR_ABORT_TASK = 1, TMR_ABORT_TASK_SET = 2, TMR_CLEAR_ACA = 3, TMR_CLEAR_TASK_SET = 4, TMR_LUN_RESET = 5, TMR_TARGET_WARM_RESET = 6, TMR_TARGET_COLD_RESET = 7, }; enum tcm_tmrsp_table { TMR_FUNCTION_COMPLETE = 1, TMR_TASK_DOES_NOT_EXIST = 2, TMR_LUN_DOES_NOT_EXIST = 3, TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED = 4, TMR_FUNCTION_REJECTED = 5, }; typedef enum { SCSI_INST_INDEX, SCSI_DEVICE_INDEX, SCSI_AUTH_INTR_INDEX, SCSI_INDEX_TYPE_MAX } scsi_index_t; struct se_cmd; struct t10_alua { u16 alua_tg_pt_gps_counter; u32 alua_tg_pt_gps_count; spinlock_t tg_pt_gps_lock; struct se_device *t10_dev; struct t10_alua_tg_pt_gp *default_tg_pt_gp; struct config_group alua_tg_pt_gps_group; struct list_head tg_pt_gps_list; }; struct t10_alua_lu_gp { u16 lu_gp_id; int lu_gp_valid_id; u32 lu_gp_members; atomic_t lu_gp_ref_cnt; spinlock_t lu_gp_lock; struct config_group lu_gp_group; struct list_head lu_gp_node; struct list_head lu_gp_mem_list; }; struct t10_alua_lu_gp_member { bool lu_gp_assoc; atomic_t lu_gp_mem_ref_cnt; spinlock_t lu_gp_mem_lock; struct t10_alua_lu_gp *lu_gp; struct se_device *lu_gp_mem_dev; struct list_head lu_gp_mem_list; }; struct t10_alua_tg_pt_gp { u16 tg_pt_gp_id; int tg_pt_gp_valid_id; int tg_pt_gp_alua_access_status; int tg_pt_gp_alua_access_type; int tg_pt_gp_nonop_delay_msecs; int tg_pt_gp_trans_delay_msecs; int tg_pt_gp_implict_trans_secs; int tg_pt_gp_pref; int tg_pt_gp_write_metadata; u32 tg_pt_gp_md_buf_len; u32 tg_pt_gp_members; atomic_t tg_pt_gp_alua_access_state; atomic_t tg_pt_gp_ref_cnt; spinlock_t tg_pt_gp_lock; struct mutex tg_pt_gp_md_mutex; struct se_device *tg_pt_gp_dev; struct config_group tg_pt_gp_group; struct list_head tg_pt_gp_list; struct list_head tg_pt_gp_mem_list; }; struct t10_alua_tg_pt_gp_member { bool tg_pt_gp_assoc; atomic_t tg_pt_gp_mem_ref_cnt; spinlock_t tg_pt_gp_mem_lock; struct t10_alua_tg_pt_gp *tg_pt_gp; struct se_port *tg_pt; struct list_head tg_pt_gp_mem_list; }; struct t10_wwn { char vendor[8]; char model[16]; char revision[4]; char unit_serial[254]; spinlock_t t10_vpd_lock; struct se_device *t10_dev; struct config_group t10_wwn_group; struct list_head t10_vpd_list; }; struct t10_pr_registration { char pr_reg_isid[16]; unsigned char pr_iport[256]; unsigned char pr_tport[256]; u16 pr_aptpl_rpti; u16 pr_reg_tpgt; int pr_reg_all_tg_pt; int pr_reg_aptpl; int pr_res_holder; int pr_res_type; int pr_res_scope; bool isid_present_at_reg; u32 pr_res_mapped_lun; u32 pr_aptpl_target_lun; u32 pr_res_generation; u64 pr_reg_bin_isid; u64 pr_res_key; atomic_t pr_res_holders; struct se_node_acl *pr_reg_nacl; struct se_dev_entry *pr_reg_deve; struct se_lun *pr_reg_tg_pt_lun; struct list_head pr_reg_list; struct list_head pr_reg_abort_list; struct list_head pr_reg_aptpl_list; struct list_head pr_reg_atp_list; struct list_head pr_reg_atp_mem_list; }; struct t10_reservation { int pr_all_tg_pt; int pr_aptpl_active; u32 pr_generation; spinlock_t registration_lock; spinlock_t aptpl_reg_lock; struct se_node_acl *pr_res_holder; struct list_head registration_list; struct list_head aptpl_reg_list; }; struct se_tmr_req { u8 function; u8 response; int call_transport; u32 ref_task_tag; void *fabric_tmr_ptr; struct se_cmd *task_cmd; struct se_device *tmr_dev; struct se_lun *tmr_lun; struct list_head tmr_list; }; struct se_cmd { u8 scsi_status; u8 scsi_asc; u8 scsi_ascq; u16 scsi_sense_length; int alua_nonop_delay; enum dma_data_direction data_direction; int sam_task_attr; unsigned int map_tag; enum transport_state_table t_state; unsigned cmd_wait_set:1; unsigned unknown_data_length:1; u32 se_cmd_flags; u32 se_ordered_id; u32 data_length; u32 residual_count; u32 orig_fe_lun; u64 pr_res_key; void *sense_buffer; struct list_head se_delayed_node; struct list_head se_lun_node; struct list_head se_qf_node; struct se_device *se_dev; struct se_dev_entry *se_deve; struct se_lun *se_lun; struct se_session *se_sess; struct se_tmr_req *se_tmr_req; struct list_head se_cmd_list; struct completion cmd_wait_comp; struct kref cmd_kref; struct target_core_fabric_ops *se_tfo; sense_reason_t (*execute_cmd)(struct se_cmd *); sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *, u32, enum dma_data_direction); sense_reason_t (*transport_complete_callback)(struct se_cmd *); unsigned char *t_task_cdb; unsigned char __t_task_cdb[32]; unsigned long long t_task_lba; unsigned int t_task_nolb; unsigned int transport_state; spinlock_t t_state_lock; struct completion t_transport_stop_comp; struct completion transport_lun_fe_stop_comp; struct completion transport_lun_stop_comp; struct work_struct work; struct scatterlist *t_data_sg; struct scatterlist *t_data_sg_orig; unsigned int t_data_nents; unsigned int t_data_nents_orig; void *t_data_vmap; struct scatterlist *t_bidi_data_sg; unsigned int t_bidi_data_nents; struct list_head state_list; bool state_active; struct completion task_stop_comp; void *priv; }; struct se_ua { u8 ua_asc; u8 ua_ascq; struct se_node_acl *ua_nacl; struct list_head ua_dev_list; struct list_head ua_nacl_list; }; struct se_node_acl { char initiatorname[224]; bool dynamic_node_acl; bool acl_stop:1; u32 queue_depth; u32 acl_index; char acl_tag[64]; u64 num_cmds; u64 read_bytes; u64 write_bytes; spinlock_t stats_lock; atomic_t acl_pr_ref_count; struct se_dev_entry **device_list; struct se_session *nacl_sess; struct se_portal_group *se_tpg; spinlock_t device_list_lock; spinlock_t nacl_sess_lock; struct config_group acl_group; struct config_group acl_attrib_group; struct config_group acl_auth_group; struct config_group acl_param_group; struct config_group acl_fabric_stat_group; struct config_group *acl_default_groups[5]; struct list_head acl_list; struct list_head acl_sess_list; struct completion acl_free_comp; struct kref acl_kref; }; struct se_session { unsigned sess_tearing_down:1; u64 sess_bin_isid; struct se_node_acl *se_node_acl; struct se_portal_group *se_tpg; 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; struct kref sess_kref; void *sess_cmd_map; struct percpu_ida sess_tag_pool; }; struct se_device; struct se_transform_info; struct scatterlist; struct se_ml_stat_grps { struct config_group stat_group; struct config_group scsi_auth_intr_group; struct config_group scsi_att_intr_port_group; }; struct se_lun_acl { char initiatorname[224]; u32 mapped_lun; struct se_node_acl *se_lun_nacl; struct se_lun *se_lun; struct list_head lacl_list; struct config_group se_lun_group; struct se_ml_stat_grps ml_stat_grps; }; struct se_dev_entry { bool def_pr_registered; u32 lun_flags; u32 mapped_lun; u32 total_cmds; u64 pr_res_key; u64 creation_time; u32 attach_count; u64 read_bytes; u64 write_bytes; atomic_t ua_count; atomic_t pr_ref_count; struct se_lun_acl *se_lun_acl; spinlock_t ua_lock; struct se_lun *se_lun; struct list_head alua_port_list; struct list_head ua_list; }; 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 enforce_pr_isids; int is_nonrot; int emulate_rest_reord; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; u32 fabric_max_sectors; u32 optimal_sectors; u32 hw_queue_depth; u32 queue_depth; u32 max_unmap_lba_count; u32 max_unmap_block_desc_count; u32 unmap_granularity; u32 unmap_granularity_alignment; u32 max_write_same_len; struct se_device *da_dev; struct config_group da_group; }; struct se_dev_stat_grps { struct config_group stat_group; struct config_group scsi_dev_group; struct config_group scsi_tgt_dev_group; struct config_group scsi_lu_group; }; struct se_device { u32 dev_link_magic; u16 dev_rpti_counter; u32 dev_cur_ordered_id; u32 dev_flags; u32 dev_port_count; u32 queue_depth; u64 dev_res_bin_isid; u32 dev_index; u64 creation_time; u32 num_resets; u64 num_cmds; u64 read_bytes; u64 write_bytes; spinlock_t stats_lock; atomic_t simple_cmds; atomic_t dev_ordered_id; atomic_t dev_ordered_sync; atomic_t dev_qf_count; int export_count; spinlock_t delayed_cmd_lock; spinlock_t execute_task_lock; spinlock_t dev_reservation_lock; unsigned int dev_reservation_flags; spinlock_t se_port_lock; spinlock_t se_tmr_lock; spinlock_t qf_cmd_lock; struct semaphore caw_sem; struct se_node_acl *dev_reserved_node_acl; struct t10_alua_lu_gp_member *dev_alua_lu_gp_mem; 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 list_head delayed_cmd_list; struct list_head state_list; struct list_head qf_cmd_list; struct list_head g_dev_node; struct se_hba *se_hba; struct t10_wwn t10_wwn; struct t10_alua t10_alua; struct t10_reservation t10_pr; struct se_dev_attrib dev_attrib; struct config_group dev_group; struct config_group dev_pr_group; struct se_dev_stat_grps dev_stat_grps; unsigned char dev_alias[512]; unsigned char udev_path[512]; struct se_subsystem_api *transport; struct list_head dev_list; }; struct se_hba { u16 hba_tpgt; u32 hba_id; u32 hba_flags; u32 dev_count; u32 hba_index; void *hba_ptr; struct list_head hba_node; spinlock_t device_lock; struct config_group hba_group; struct mutex hba_access_mutex; struct se_subsystem_api *transport; }; struct se_port_stat_grps { struct config_group stat_group; struct config_group scsi_port_group; struct config_group scsi_tgt_port_group; struct config_group scsi_transport_group; }; struct se_lun { u32 lun_link_magic; enum transport_lun_status_table lun_status; u32 lun_access; u32 lun_flags; u32 unpacked_lun; atomic_t lun_acl_count; spinlock_t lun_acl_lock; spinlock_t lun_cmd_lock; spinlock_t lun_sep_lock; struct completion lun_shutdown_comp; struct list_head lun_cmd_list; struct list_head lun_acl_list; struct se_device *lun_se_dev; struct se_port *lun_sep; struct config_group lun_group; struct se_port_stat_grps port_stat_grps; }; struct scsi_port_stats { u64 cmd_pdus; u64 tx_data_octets; u64 rx_data_octets; }; struct se_port { u16 sep_rtpi; int sep_tg_pt_secondary_stat; int sep_tg_pt_secondary_write_md; u32 sep_index; struct scsi_port_stats sep_stats; atomic_t sep_tg_pt_secondary_offline; atomic_t sep_tg_pt_ref_cnt; spinlock_t sep_alua_lock; struct mutex sep_tg_pt_md_mutex; struct t10_alua_tg_pt_gp_member *sep_alua_tg_pt_gp_mem; struct se_lun *sep_lun; struct se_portal_group *sep_tpg; struct list_head sep_alua_list; struct list_head sep_list; }; struct se_tpg_np { struct se_portal_group *tpg_np_parent; struct config_group tpg_np_group; }; struct se_portal_group { enum transport_tpg_type_table se_tpg_type; u32 num_node_acls; atomic_t tpg_pr_ref_count; spinlock_t acl_node_lock; spinlock_t session_lock; spinlock_t tpg_lun_lock; void *se_tpg_fabric_ptr; struct list_head se_tpg_node; struct list_head acl_node_list; struct se_lun **tpg_lun_list; struct se_lun tpg_virt_lun0; struct list_head tpg_sess_list; struct target_core_fabric_ops *se_tpg_tfo; struct se_wwn *se_tpg_wwn; struct config_group tpg_group; struct config_group *tpg_default_groups[7]; struct config_group tpg_lun_group; struct config_group tpg_np_group; struct config_group tpg_acl_group; struct config_group tpg_attrib_group; struct config_group tpg_auth_group; struct config_group tpg_param_group; }; struct se_wwn { struct target_fabric_configfs *wwn_tf; struct config_group wwn_group; struct config_group *wwn_default_groups[2]; struct config_group fabric_stat_group; }; void *transport_kmap_data_sg(struct se_cmd *); void transport_kunmap_data_sg(struct se_cmd *); struct target_core_fabric_ops { struct configfs_subsystem *tf_subsys; char *(*get_fabric_name)(void); u8 (*get_fabric_proto_ident)(struct se_portal_group *); char *(*tpg_get_wwn)(struct se_portal_group *); u16 (*tpg_get_tag)(struct se_portal_group *); u32 (*tpg_get_default_depth)(struct se_portal_group *); u32 (*tpg_get_pr_transport_id)(struct se_portal_group *, struct se_node_acl *, struct t10_pr_registration *, int *, unsigned char *); u32 (*tpg_get_pr_transport_id_len)(struct se_portal_group *, struct se_node_acl *, struct t10_pr_registration *, int *); char *(*tpg_parse_pr_out_transport_id)(struct se_portal_group *, const char *, u32 *, char **); int (*tpg_check_demo_mode)(struct se_portal_group *); int (*tpg_check_demo_mode_cache)(struct se_portal_group *); int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *); int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *); int (*tpg_check_demo_mode_login_only)(struct se_portal_group *); struct se_node_acl *(*tpg_alloc_fabric_acl)( struct se_portal_group *); void (*tpg_release_fabric_acl)(struct se_portal_group *, struct se_node_acl *); u32 (*tpg_get_inst_index)(struct se_portal_group *); int (*check_stop_free)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); void (*put_session)(struct se_session *); int (*shutdown_session)(struct se_session *); void (*close_session)(struct se_session *); u32 (*sess_get_index)(struct se_session *); u32 (*sess_get_initiator_sid)(struct se_session *, unsigned char *, u32); int (*write_pending)(struct se_cmd *); int (*write_pending_status)(struct se_cmd *); void (*set_default_node_attributes)(struct se_node_acl *); u32 (*get_task_tag)(struct se_cmd *); int (*get_cmd_state)(struct se_cmd *); int (*queue_data_in)(struct se_cmd *); int (*queue_status)(struct se_cmd *); void (*queue_tm_rsp)(struct se_cmd *); struct se_wwn *(*fabric_make_wwn)(struct target_fabric_configfs *, struct config_group *, const char *); void (*fabric_drop_wwn)(struct se_wwn *); struct se_portal_group *(*fabric_make_tpg)(struct se_wwn *, struct config_group *, const char *); void (*fabric_drop_tpg)(struct se_portal_group *); int (*fabric_post_link)(struct se_portal_group *, struct se_lun *); void (*fabric_pre_unlink)(struct se_portal_group *, struct se_lun *); struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *, struct config_group *, const char *); void (*fabric_drop_np)(struct se_tpg_np *); struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *, struct config_group *, const char *); void (*fabric_drop_nodeacl)(struct se_node_acl *); }; struct target_fabric_configfs_template { struct config_item_type tfc_discovery_cit; struct config_item_type tfc_wwn_cit; struct config_item_type tfc_wwn_fabric_stats_cit; struct config_item_type tfc_tpg_cit; struct config_item_type tfc_tpg_base_cit; struct config_item_type tfc_tpg_lun_cit; struct config_item_type tfc_tpg_port_cit; struct config_item_type tfc_tpg_port_stat_cit; struct config_item_type tfc_tpg_np_cit; struct config_item_type tfc_tpg_np_base_cit; struct config_item_type tfc_tpg_attrib_cit; struct config_item_type tfc_tpg_auth_cit; struct config_item_type tfc_tpg_param_cit; struct config_item_type tfc_tpg_nacl_cit; struct config_item_type tfc_tpg_nacl_base_cit; struct config_item_type tfc_tpg_nacl_attrib_cit; struct config_item_type tfc_tpg_nacl_auth_cit; struct config_item_type tfc_tpg_nacl_param_cit; struct config_item_type tfc_tpg_nacl_stat_cit; struct config_item_type tfc_tpg_mappedlun_cit; struct config_item_type tfc_tpg_mappedlun_stat_cit; }; struct target_fabric_configfs { char tf_name[32]; atomic_t tf_access_cnt; struct list_head tf_list; struct config_group tf_group; struct config_group tf_disc_group; struct config_group *tf_default_groups[2]; struct config_item *tf_fabric; struct config_item_type *tf_fabric_cit; struct configfs_subsystem *tf_subsys; struct module *tf_module; struct target_core_fabric_ops tf_ops; struct target_fabric_configfs_template tf_cit_tmpl; }; extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *); static sense_reason_t core_scsi3_pri_read_keys(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u32 add_len = 0, off = 8; if (cmd->data_length < 8) { printk("\001" "3" "PRIN SA READ_KEYS SCSI Data Length: %u" " too small\n", cmd->data_length); return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[3] = (dev->t10_pr.pr_generation & 0xff); spin_lock(&dev->t10_pr.registration_lock); for (pr_reg = ({ const typeof( ((typeof(*pr_reg) *)0)->pr_reg_list ) *__mptr = ((&dev->t10_pr.registration_list)->next); (typeof(*pr_reg) *)( (char *)__mptr - __builtin_offsetof(typeof(*pr_reg),pr_reg_list) );}); &pr_reg->pr_reg_list != (&dev->t10_pr.registration_list); pr_reg = ({ const typeof( ((typeof(*pr_reg) *)0)->pr_reg_list ) *__mptr = (pr_reg->pr_reg_list.next); (typeof(*pr_reg) *)( (char *)__mptr - __builtin_offsetof(typeof(*pr_reg),pr_reg_list) );})) { if ((add_len + 8) > (cmd->data_length - 8)) break; buf[off++] = ((pr_reg->pr_res_key >> 56) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 48) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 40) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 32) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 24) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 16) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 8) & 0xff); buf[off++] = (pr_reg->pr_res_key & 0xff); add_len += 8; } spin_unlock(&dev->t10_pr.registration_lock); buf[4] = ((add_len >> 24) & 0xff); buf[5] = ((add_len >> 16) & 0xff); buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); transport_kunmap_data_sg(cmd); return 0; } static sense_reason_t core_scsi3_pri_read_reservation(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; unsigned char *buf; u64 pr_res_key; u32 add_len = 16; if (cmd->data_length < 8) { printk("\001" "3" "PRIN SA READ_RESERVATIONS SCSI Data Length: %u" " too small\n", cmd->data_length) ; return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[3] = (dev->t10_pr.pr_generation & 0xff); spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; if (pr_reg) { buf[4] = ((add_len >> 24) & 0xff); buf[5] = ((add_len >> 16) & 0xff); buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); if (cmd->data_length < 22) goto err; if ((pr_reg->pr_res_type == 0x07) || (pr_reg->pr_res_type == 0x08)) pr_res_key = 0; else pr_res_key = pr_reg->pr_res_key; buf[8] = ((pr_res_key >> 56) & 0xff); buf[9] = ((pr_res_key >> 48) & 0xff); buf[10] = ((pr_res_key >> 40) & 0xff); buf[11] = ((pr_res_key >> 32) & 0xff); buf[12] = ((pr_res_key >> 24) & 0xff); buf[13] = ((pr_res_key >> 16) & 0xff); buf[14] = ((pr_res_key >> 8) & 0xff); buf[15] = (pr_res_key & 0xff); buf[21] = (pr_reg->pr_res_scope & 0xf0) | (pr_reg->pr_res_type & 0x0f); } err: spin_unlock(&dev->dev_reservation_lock); transport_kunmap_data_sg(cmd); return 0; } static sense_reason_t core_scsi3_pri_report_capabilities(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u16 add_len = 8; if (cmd->data_length < 6) { printk("\001" "3" "PRIN SA REPORT_CAPABILITIES SCSI Data Length:" " %u too small\n", cmd->data_length); return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); buf[2] |= 0x10; buf[2] |= 0x08; buf[2] |= 0x04; buf[2] |= 0x01; buf[3] |= 0x80; buf[3] |= 0x10; if (pr_tmpl->pr_aptpl_active) buf[3] |= 0x01; buf[4] |= 0x80; buf[4] |= 0x40; buf[4] |= 0x20; buf[4] |= 0x08; buf[4] |= 0x02; buf[5] |= 0x01; transport_kunmap_data_sg(cmd); return 0; } static sense_reason_t core_scsi3_pri_read_full_status(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_node_acl *se_nacl; struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_tmp; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; u32 off = 8; int format_code = 0; if (cmd->data_length < 8) { printk("\001" "3" "PRIN SA READ_FULL_STATUS SCSI Data Length: %u" " too small\n", cmd->data_length) ; return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[3] = (dev->t10_pr.pr_generation & 0xff); spin_lock(&pr_tmpl->registration_lock); for (pr_reg = ({ const typeof( ((typeof(*pr_reg) *)0)->pr_reg_list ) *__mptr = ((&pr_tmpl->registration_list)->next); (typeof(*pr_reg) *)( (char *)__mptr - __builtin_offsetof(typeof(*pr_reg),pr_reg_list) );}), pr_reg_tmp = ({ const typeof( ((typeof(*pr_reg) *)0)->pr_reg_list ) *__mptr = (pr_reg->pr_reg_list.next); (typeof(*pr_reg) *)( (char *)__mptr - __builtin_offsetof(typeof(*pr_reg),pr_reg_list) );}); &pr_reg->pr_reg_list != (&pr_tmpl->registration_list); pr_reg = pr_reg_tmp, pr_reg_tmp = ({ const typeof( ((typeof(*pr_reg_tmp) *)0)->pr_reg_list ) *__mptr = (pr_reg_tmp->pr_reg_list.next); (typeof(*pr_reg_tmp) *)( (char *)__mptr - __builtin_offsetof(typeof(*pr_reg_tmp),pr_reg_list) );})) { se_nacl = pr_reg->pr_reg_nacl; se_tpg = pr_reg->pr_reg_nacl->se_tpg; add_desc_len = 0; atomic_add(1, &pr_reg->pr_res_holders); spin_unlock(&pr_tmpl->registration_lock); exp_desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id_len( se_tpg, se_nacl, pr_reg, &format_code); if ((exp_desc_len + add_len) > cmd->data_length) { printk("\001" "4" "SPC-3 PRIN READ_FULL_STATUS ran" " out of buffer: %d\n", cmd->data_length) ; spin_lock(&pr_tmpl->registration_lock); atomic_sub(1, &pr_reg->pr_res_holders); break; } buf[off++] = ((pr_reg->pr_res_key >> 56) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 48) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 40) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 32) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 24) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 16) & 0xff); buf[off++] = ((pr_reg->pr_res_key >> 8) & 0xff); buf[off++] = (pr_reg->pr_res_key & 0xff); off += 4; if (pr_reg->pr_reg_all_tg_pt) buf[off] = 0x02; if (pr_reg->pr_res_holder) { buf[off++] |= 0x01; buf[off++] = (pr_reg->pr_res_scope & 0xf0) | (pr_reg->pr_res_type & 0x0f); } else off += 2; off += 4; if (!pr_reg->pr_reg_all_tg_pt) { struct se_port *port = pr_reg->pr_reg_tg_pt_lun->lun_sep; buf[off++] = ((port->sep_rtpi >> 8) & 0xff); buf[off++] = (port->sep_rtpi & 0xff); } else off += 2; desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id(se_tpg, se_nacl, pr_reg, &format_code, &buf[off+4]); spin_lock(&pr_tmpl->registration_lock); atomic_sub(1, &pr_reg->pr_res_holders); buf[off++] = ((desc_len >> 24) & 0xff); buf[off++] = ((desc_len >> 16) & 0xff); buf[off++] = ((desc_len >> 8) & 0xff); buf[off++] = (desc_len & 0xff); add_desc_len = (24 + desc_len); off += desc_len; add_len += add_desc_len; } spin_unlock(&pr_tmpl->registration_lock); buf[4] = ((add_len >> 24) & 0xff); buf[5] = ((add_len >> 16) & 0xff); buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); transport_kunmap_data_sg(cmd); return 0; } sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *cmd) { sense_reason_t ret; if (cmd->se_dev->dev_reservation_flags & 0x00000001) { printk("\001" "3" "Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); return TCM_RESERVATION_CONFLICT; } switch (cmd->t_task_cdb[1] & 0x1f) { case 0x00: ret = core_scsi3_pri_read_keys(cmd); break; case 0x01: ret = core_scsi3_pri_read_reservation(cmd); break; case 0x02: ret = core_scsi3_pri_report_capabilities(cmd); break; case 0x03: ret = core_scsi3_pri_read_full_status(cmd); break; default: printk("\001" "3" "Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f) ; return TCM_INVALID_CDB_FIELD; } if (!ret) target_complete_cmd(cmd, 0x00); return ret; }