Re: [Suggestion] arc: compiler: bug: about an arc compiler's bugwhich is not in gcc main source code.

From: Chen Gang
Date: Thu Oct 31 2013 - 04:51:45 EST


On 10/31/2013 03:48 PM, Vineet Gupta wrote:
> Hi Chen,
>
> Many thanks for all your efforts so far.
>

Since I need provide contribution to Public Open Source, so what I have
done is what I should do. :-)

In fact, I really need improve myself: e.g. how to make negative effect
lowest (e.g. how to let more members pleased with what I have done), how
to improve efficiency (make my waste mail lower) ...


> Most of your patches have already been folded into ARC for 3.13. I will send out
> the patches for some of the cross-arch changes in next development cycle as
> currently I need to finish up a few things for upcoming merge window.
>

OK, thanks.

> We are actively working on toolchain issues and hopefully the fixes will make it
> into next formal release of tools. Please check back in few weeks.
>

OK, I will/should focus.

And for gcc issue #27, I shrank the demo source file is about 1K lines
(shrank from 50K lines to 1K lines), although it is still a big file
which can be shrunk more.

And excuse me, I don't know how to past this file on this website, so I
load it as attachment, please check.


Thanks.
--
Chen Gang
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;
}