: Add support for UNIT_ATTENTION conditions
PATCH 1/2 : Add support for UNIT_ATTENTION conditions
Quoted 1 line
From
2fed7603d2b4b8f0fb7a6bd1f3087eb6cbe0d21aMon Sep 17 00:00:00 2001
From: Nicholas Bellinger <[email protected]>
Date: Tue, 24 Mar 2009 22:14:27 -0700
Subject: [PATCH 1/2] [Target_Core_Mod]: Add support for UNIT_ATTENTION conditions
This patch adds support for UNIT_ATTENTION and ua_intlck_ctrl emulation following spc4r17, section 7.4.6 Control Mode Page, Table 349.
Upon reception of a REQUEST_SENSE, this patch will report and release a UNIT_ATTENTION condition for a given I_T Nexus. It adds a se_ua_t structure defs, and new UA related structure members to se_dev_entry_t in se_node_acl->device_list[] coming from se_lun_acl_t mapped se_lun_t objects. Upon release of mapped target_core_mod LUN ACL, this patch will release all associated UNIT ATTENTION conditions.
By default, this patch uses ua_intlck_ctrl code 00b, and clears UNIT ATTENTION conditions by sending CHECK_CONDITION with a SENSE KEY of UNIT ATTENTION + the associated highest priority ASC+ASCQ when a UNIT ATTENTION condition has been established. Note that this is the current behaviour of Linux/SCSI and linux/drivers/scsi midlayer code for ua_intlck_ctrl.
This patch also supports the optional 2nd and 3rd modes of ua_intlck_ctrl (code 10b and 11b), with the latter using:
target_core_ua.h:ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS.
Both of these modes have been tested with this code and require manual intervention with sg_requests and REQUEST_SENSE for Linux/SCSI Initiator ports to explictly release a target_core_mod established UNIT ATTENTION condition.
--- drivers/lio-core/Makefile | 1 + drivers/lio-core/target_core_base.h | 13 ++ drivers/lio-core/target_core_configfs.c | 4 + drivers/lio-core/target_core_device.c | 27 +++- drivers/lio-core/target_core_device.h | 1 + drivers/lio-core/target_core_tpg.c | 10 + drivers/lio-core/target_core_transport.c | 127 ++++++++++-- drivers/lio-core/target_core_transport.h | 2 + drivers/lio-core/target_core_ua.c | 333 ++++++++++++++++++++++++++++++ drivers/lio-core/target_core_ua.h | 36 ++++ 10 files changed, 534 insertions(+), 20 deletions(-) create mode 100644 drivers/lio-core/target_core_ua.c create mode 100644 drivers/lio-core/target_core_ua.h
drivers/lio-core/Makefile +1 -0
@@ -40,6 +40,7 @@ target_core_mod-objs := target_core_configfs.o \ target_core_tmr.o \ target_core_tpg.o \ target_core_transport.o \ + target_core_ua.o \ div64.o ifeq ($(LINUX_IBLOCK), 1)
drivers/lio-core/target_core_base.h +13 -0
@@ -197,6 +197,7 @@#define UNKNOWN_MODE_PAGE 0xb#define WRITE_PROTECTED 0xc#define CHECK_CONDITION_ABORT_CMD 0xd +#define CHECK_CONDITION_UNIT_ATTENTION 0xe typedef struct se_obj_s { atomic_t obj_access_count;
@@ -539,6 +540,14 @@ typedef struct se_tmr_req_s {struct list_head tmr_list; }____cacheline_aligned se_tmr_req_t; +typedef struct se_ua_s { +u8 ua_asc; +u8 ua_ascq; +struct se_node_acl_s *ua_nacl; +struct list_head ua_dev_list; +struct list_head ua_nacl_list; +}____cacheline_aligned se_ua_t ; + typedef struct se_node_acl_s { char initiatorname[TRANSPORT_IQN_LEN]; int nodeacl_flags;
@@ -600,12 +609,16 @@ typedef struct se_dev_entry_s {u64 read_bytes;u64 write_bytes;#endif /* SNMP_SUPPORT */ +atomic_t ua_count; +spinlock_t ua_lock;struct se_lun_s *se_lun; +struct list_head ua_list; }____cacheline_aligned se_dev_entry_t; typedef struct se_dev_attrib_s { int status_thread; int status_thread_tur; + int emulate_ua_intlck_ctrl; int emulate_tas; int emulate_reservations; int emulate_alua;
drivers/lio-core/target_core_configfs.c +4 -0
@@ -478,6 +478,9 @@ SE_DEV_ATTR(status_thread, S_IRUGO | S_IWUSR);DEF_DEV_ATTRIB (status_thread_tur);SE_DEV_ATTR (status_thread_tur,S_IRUGO |S_IWUSR ); +DEF_DEV_ATTRIB (emulate_ua_intlck_ctrl); +SE_DEV_ATTR (emulate_ua_intlck_ctrl,S_IRUGO |S_IWUSR ); +DEF_DEV_ATTRIB (emulate_tas);SE_DEV_ATTR (emulate_tas,S_IRUGO |S_IWUSR );
@@ -507,6 +510,7 @@ CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib_s, da_group);static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_status_thread.attr, &target_core_dev_attrib_status_thread_tur.attr, + &target_core_dev_attrib_emulate_ua_intlck_ctrl.attr, &target_core_dev_attrib_emulate_tas.attr, &target_core_dev_attrib_hw_block_size.attr, &target_core_dev_attrib_block_size.attr,
drivers/lio-core/target_core_device.c +25 -2
@@ -49,6 +49,7 @@#include <target_core_pr.h> #include <target_core_tpg.h> #include <target_core_transport.h> +#include <target_core_ua.h> #include <target_core_fabric_ops.h> #include <target_core_plugin.h> #include <target_core_seobj.h>
@@ -483,12 +484,12 @@ void core_update_device_list_for_node( deve->attach_count++;#endif /* SNMP_SUPPORT */ spin_unlock_bh (&nacl->device_list_lock); -return ; }/* * Disable se_dev_entry_t LUN ACL mapping */ +core_scsi3_ua_release_all (deve); deve->se_lun =NULL ; deve->lun_flags =0 ; deve->creation_time =0 ;
@@ -869,6 +870,7 @@ void se_dev_set_default_attribs(se_device_t *dev) {DEV_ATTRIB (dev)->status_thread =DA_STATUS_THREAD ;DEV_ATTRIB (dev)->status_thread_tur =DA_STATUS_THREAD_TUR ; +DEV_ATTRIB (dev)->emulate_ua_intlck_ctrl =DA_EMULATE_UA_INTLLCK_CTRL ;DEV_ATTRIB (dev)->emulate_tas =DA_EMULATE_TAS ;DEV_ATTRIB (dev)->emulate_reservations =DA_EMULATE_RESERVATIONS ;DEV_ATTRIB (dev)->emulate_alua =DA_EMULATE_ALUA ;
@@ -970,11 +972,32 @@ int se_dev_set_status_thread_tur(se_device_t *dev, int flag)return 0 ; } +int se_dev_set_emulate_ua_intlck_ctrl (se_device_t *dev,int flag) +{ +if ((flag !=0 ) && (flag !=1 ) && (flag !=2 )) { +printk (KERN_ERR "Illegal value %d\n" , flag); +return -1 ; + } + +if (DEV_OBJ_API (dev)->check_count (&dev->dev_export_obj)) { +printk (KERN_ERR "dev[%p]: Unable to change SE Device" +" UA_INTRLCK_CTRL while dev_export_obj: %d count" +" exists\n" , dev, +DEV_OBJ_API (dev)->check_count (&dev->dev_export_obj)); +return -1 ; + } +DEV_ATTRIB (dev)->emulate_ua_intlck_ctrl = flag; +printk (KERN_INFO "dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n" , + dev,DEV_ATTRIB (dev)->emulate_ua_intlck_ctrl); + +return 0 ; +} +int se_dev_set_emulate_tas (se_device_t *dev,int flag) {if ((flag !=0 ) && (flag !=1 )) {printk (KERN_ERR "Illegal value %d\n" , flag); -return 1 ; +return -1 ; }if (DEV_OBJ_API (dev)->check_count (&dev->dev_export_obj)) {
drivers/lio-core/target_core_device.h +1 -0
@@ -62,6 +62,7 @@ extern void se_dev_set_default_attribs(se_device_t *);extern int se_dev_set_task_timeout (se_device_t *,u32 );extern int se_dev_set_status_thread (se_device_t *,int );extern int se_dev_set_status_thread_tur (se_device_t *,int ); +extern int se_dev_set_emulate_ua_intlck_ctrl (se_device_t *,int );extern int se_dev_set_emulate_tas (se_device_t *,int );extern int se_dev_set_queue_depth (se_device_t *,u32 );extern int se_dev_set_max_sectors (se_device_t *,u32 );
drivers/lio-core/target_core_tpg.c +10 -0
@@ -235,6 +235,9 @@ static int core_set_queue_depth_for_node(*/ static int core_create_device_list_for_node (se_node_acl_t *nacl) { +se_dev_entry_t *deve; +int i; + nacl->device_list =kzalloc (sizeof (se_dev_entry_t) *TRANSPORT_MAX_LUNS_PER_TPG ,GFP_KERNEL );if (!(nacl->device_list)) {
@@ -242,6 +245,13 @@ static int core_create_device_list_for_node(se_node_acl_t *nacl) " se_node_acl_t->device_list\n");return -1 ; } +for (i =0 ; i <TRANSPORT_MAX_LUNS_PER_TPG ; i++) { + deve = &nacl->device_list[i]; + +atomic_set (&deve->ua_count,0 ); +spin_lock_init (&deve->ua_lock); +INIT_LIST_HEAD (&deve->ua_list); + }return 0 ; }
drivers/lio-core/target_core_transport.c +109 -18
207 lines not on this page · raw message
drivers/lio-core/target_core_transport.h +2 -0
@@ -102,6 +102,8 @@#define DA_STATUS_THREAD 0/* Disabled by default */ #define DA_STATUS_THREAD_TUR 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/* No Emulation for PSCSI by default */
drivers/lio-core/target_core_ua.c new file +333 -0
333 lines not on this page · raw message
drivers/lio-core/target_core_ua.h new file +36 -0
@@ -0,0 +1,36 @@ +#ifndef TARGET_CORE_UA_H + +/* +* From spc4r17, Table D.1: ASC and ASCQ Assignement +*/ +#define ASCQ_29H_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURED 0x00 +#define ASCQ_29H_POWER_ON_OCCURRED 0x01 +#define ASCQ_29H_SCSI_BUS_RESET_OCCURED 0x02 +#define ASCQ_29H_BUS_DEVICE_RESET_FUNCTION_OCCURRED 0x03 +#define ASCQ_29H_DEVICE_INTERNAL_RESET 0x04 +#define ASCQ_29H_TRANSCEIVER_MODE_CHANGED_TO_SINGLE_ENDED 0x05 +#define ASCQ_29H_TRANSCEIVER_MODE_CHANGED_TO_LVD 0x06 +#define ASCQ_29H_NEXUS_LOSS_OCCURRED 0x07 + +#define ASCQ_2AH_PARAMETERS_CHANGED 0x00 +#define ASCQ_2AH_MODE_PARAMETERS_CHANGED 0x01 +#define ASCQ_2AH_LOG_PARAMETERS_CHANGED 0x02 +#define ASCQ_2AH_RESERVATIONS_PREEMPTED 0x03 +#define ASCQ_2AH_RESERVATIONS_RELEASED 0x04 +#define ASCQ_2AH_REGISTRATIONS_PREEMPTED 0x05 +#define ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED 0x06 +#define ASCQ_2AH_IMPLICT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x07 +#define ASCQ_2AH_PRIORITY_CHANGED 0x08 + +#define ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS 0x09 + +extern struct kmem_cache *se_ua_cache; + +extern int core_scsi3_ua_check (struct se_cmd_s *,unsigned char *); +extern int core_scsi3_ua_allocate (struct se_node_acl_s *,u32 ,u8 ,u8 ); +extern void core_scsi3_ua_release_all (struct se_dev_entry_s *); +extern void core_scsi3_ua_for_check_condition (struct se_cmd_s *,u8 *,u8 *); +extern int core_scsi3_ua_clear_for_request_sense (struct se_cmd_s *, +u8 *,u8 *); + +#endif /* TARGET_CORE_UA_H */
Signature · 1 line
1.5.4.1