@@ -1677,6 +1677,13 @@ static const char *iscsi_session_state_name(int state)
16771677 return name ;
16781678}
16791679
1680+ static char * iscsi_session_target_state_name [] = {
1681+ [ISCSI_SESSION_TARGET_UNBOUND ] = "UNBOUND" ,
1682+ [ISCSI_SESSION_TARGET_ALLOCATED ] = "ALLOCATED" ,
1683+ [ISCSI_SESSION_TARGET_SCANNED ] = "SCANNED" ,
1684+ [ISCSI_SESSION_TARGET_UNBINDING ] = "UNBINDING" ,
1685+ };
1686+
16801687int iscsi_session_chkready (struct iscsi_cls_session * session )
16811688{
16821689 int err ;
@@ -1786,9 +1793,13 @@ static int iscsi_user_scan_session(struct device *dev, void *data)
17861793 if ((scan_data -> channel == SCAN_WILD_CARD ||
17871794 scan_data -> channel == 0 ) &&
17881795 (scan_data -> id == SCAN_WILD_CARD ||
1789- scan_data -> id == id ))
1796+ scan_data -> id == id )) {
17901797 scsi_scan_target (& session -> dev , 0 , id ,
17911798 scan_data -> lun , scan_data -> rescan );
1799+ spin_lock_irqsave (& session -> lock , flags );
1800+ session -> target_state = ISCSI_SESSION_TARGET_SCANNED ;
1801+ spin_unlock_irqrestore (& session -> lock , flags );
1802+ }
17921803 }
17931804
17941805user_scan_exit :
@@ -1961,31 +1972,41 @@ static void __iscsi_unbind_session(struct work_struct *work)
19611972 struct iscsi_cls_host * ihost = shost -> shost_data ;
19621973 unsigned long flags ;
19631974 unsigned int target_id ;
1975+ bool remove_target = true;
19641976
19651977 ISCSI_DBG_TRANS_SESSION (session , "Unbinding session\n" );
19661978
19671979 /* Prevent new scans and make sure scanning is not in progress */
19681980 mutex_lock (& ihost -> mutex );
19691981 spin_lock_irqsave (& session -> lock , flags );
1970- if (session -> target_id == ISCSI_MAX_TARGET ) {
1982+ if (session -> target_state == ISCSI_SESSION_TARGET_ALLOCATED ) {
1983+ remove_target = false;
1984+ } else if (session -> target_state != ISCSI_SESSION_TARGET_SCANNED ) {
19711985 spin_unlock_irqrestore (& session -> lock , flags );
19721986 mutex_unlock (& ihost -> mutex );
1973- goto unbind_session_exit ;
1987+ ISCSI_DBG_TRANS_SESSION (session ,
1988+ "Skipping target unbinding: Session is unbound/unbinding.\n" );
1989+ return ;
19741990 }
19751991
1992+ session -> target_state = ISCSI_SESSION_TARGET_UNBINDING ;
19761993 target_id = session -> target_id ;
19771994 session -> target_id = ISCSI_MAX_TARGET ;
19781995 spin_unlock_irqrestore (& session -> lock , flags );
19791996 mutex_unlock (& ihost -> mutex );
19801997
1981- scsi_remove_target (& session -> dev );
1998+ if (remove_target )
1999+ scsi_remove_target (& session -> dev );
19822000
19832001 if (session -> ida_used )
19842002 ida_free (& iscsi_sess_ida , target_id );
19852003
1986- unbind_session_exit :
19872004 iscsi_session_event (session , ISCSI_KEVENT_UNBIND_SESSION );
19882005 ISCSI_DBG_TRANS_SESSION (session , "Completed target removal\n" );
2006+
2007+ spin_lock_irqsave (& session -> lock , flags );
2008+ session -> target_state = ISCSI_SESSION_TARGET_UNBOUND ;
2009+ spin_unlock_irqrestore (& session -> lock , flags );
19892010}
19902011
19912012static void __iscsi_destroy_session (struct work_struct * work )
@@ -2062,6 +2083,9 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
20622083 session -> ida_used = true;
20632084 } else
20642085 session -> target_id = target_id ;
2086+ spin_lock_irqsave (& session -> lock , flags );
2087+ session -> target_state = ISCSI_SESSION_TARGET_ALLOCATED ;
2088+ spin_unlock_irqrestore (& session -> lock , flags );
20652089
20662090 dev_set_name (& session -> dev , "session%u" , session -> sid );
20672091 err = device_add (& session -> dev );
@@ -4369,6 +4393,19 @@ iscsi_session_attr(def_taskmgmt_tmo, ISCSI_PARAM_DEF_TASKMGMT_TMO, 0);
43694393iscsi_session_attr (discovery_parent_idx , ISCSI_PARAM_DISCOVERY_PARENT_IDX , 0 );
43704394iscsi_session_attr (discovery_parent_type , ISCSI_PARAM_DISCOVERY_PARENT_TYPE , 0 );
43714395
4396+ static ssize_t
4397+ show_priv_session_target_state (struct device * dev , struct device_attribute * attr ,
4398+ char * buf )
4399+ {
4400+ struct iscsi_cls_session * session = iscsi_dev_to_session (dev -> parent );
4401+
4402+ return sysfs_emit (buf , "%s\n" ,
4403+ iscsi_session_target_state_name [session -> target_state ]);
4404+ }
4405+
4406+ static ISCSI_CLASS_ATTR (priv_sess , target_state , S_IRUGO ,
4407+ show_priv_session_target_state , NULL) ;
4408+
43724409static ssize_t
43734410show_priv_session_state (struct device * dev , struct device_attribute * attr ,
43744411 char * buf )
@@ -4471,6 +4508,7 @@ static struct attribute *iscsi_session_attrs[] = {
44714508 & dev_attr_sess_boot_target .attr ,
44724509 & dev_attr_priv_sess_recovery_tmo .attr ,
44734510 & dev_attr_priv_sess_state .attr ,
4511+ & dev_attr_priv_sess_target_state .attr ,
44744512 & dev_attr_priv_sess_creator .attr ,
44754513 & dev_attr_sess_chap_out_idx .attr ,
44764514 & dev_attr_sess_chap_in_idx .attr ,
@@ -4584,6 +4622,8 @@ static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
45844622 return S_IRUGO | S_IWUSR ;
45854623 else if (attr == & dev_attr_priv_sess_state .attr )
45864624 return S_IRUGO ;
4625+ else if (attr == & dev_attr_priv_sess_target_state .attr )
4626+ return S_IRUGO ;
45874627 else if (attr == & dev_attr_priv_sess_creator .attr )
45884628 return S_IRUGO ;
45894629 else if (attr == & dev_attr_priv_sess_target_id .attr )
0 commit comments