@@ -208,6 +208,7 @@ struct fcloop_lport {
208208 struct nvme_fc_local_port * localport ;
209209 struct list_head lport_list ;
210210 struct completion unreg_done ;
211+ refcount_t ref ;
211212};
212213
213214struct fcloop_lport_priv {
@@ -994,6 +995,27 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
994995 }
995996}
996997
998+ static void
999+ fcloop_lport_put (struct fcloop_lport * lport )
1000+ {
1001+ unsigned long flags ;
1002+
1003+ if (!refcount_dec_and_test (& lport -> ref ))
1004+ return ;
1005+
1006+ spin_lock_irqsave (& fcloop_lock , flags );
1007+ list_del (& lport -> lport_list );
1008+ spin_unlock_irqrestore (& fcloop_lock , flags );
1009+
1010+ kfree (lport );
1011+ }
1012+
1013+ static int
1014+ fcloop_lport_get (struct fcloop_lport * lport )
1015+ {
1016+ return refcount_inc_not_zero (& lport -> ref );
1017+ }
1018+
9971019static void
9981020fcloop_nport_put (struct fcloop_nport * nport )
9991021{
@@ -1017,6 +1039,8 @@ fcloop_localport_delete(struct nvme_fc_local_port *localport)
10171039
10181040 /* release any threads waiting for the unreg to complete */
10191041 complete (& lport -> unreg_done );
1042+
1043+ fcloop_lport_put (lport );
10201044}
10211045
10221046static void
@@ -1128,6 +1152,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
11281152
11291153 lport -> localport = localport ;
11301154 INIT_LIST_HEAD (& lport -> lport_list );
1155+ refcount_set (& lport -> ref , 1 );
11311156
11321157 spin_lock_irqsave (& fcloop_lock , flags );
11331158 list_add_tail (& lport -> lport_list , & fcloop_lports );
@@ -1144,13 +1169,6 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
11441169 return ret ? ret : count ;
11451170}
11461171
1147-
1148- static void
1149- __unlink_local_port (struct fcloop_lport * lport )
1150- {
1151- list_del (& lport -> lport_list );
1152- }
1153-
11541172static int
11551173__wait_localport_unreg (struct fcloop_lport * lport )
11561174{
@@ -1163,8 +1181,6 @@ __wait_localport_unreg(struct fcloop_lport *lport)
11631181 if (!ret )
11641182 wait_for_completion (& lport -> unreg_done );
11651183
1166- kfree (lport );
1167-
11681184 return ret ;
11691185}
11701186
@@ -1187,8 +1203,9 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
11871203 list_for_each_entry (tlport , & fcloop_lports , lport_list ) {
11881204 if (tlport -> localport -> node_name == nodename &&
11891205 tlport -> localport -> port_name == portname ) {
1206+ if (!fcloop_lport_get (tlport ))
1207+ break ;
11901208 lport = tlport ;
1191- __unlink_local_port (lport );
11921209 break ;
11931210 }
11941211 }
@@ -1198,6 +1215,7 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
11981215 return - ENOENT ;
11991216
12001217 ret = __wait_localport_unreg (lport );
1218+ fcloop_lport_put (lport );
12011219
12021220 return ret ? ret : count ;
12031221}
@@ -1625,17 +1643,17 @@ static void __exit fcloop_exit(void)
16251643 for (;;) {
16261644 lport = list_first_entry_or_null (& fcloop_lports ,
16271645 typeof (* lport ), lport_list );
1628- if (!lport )
1646+ if (!lport || ! fcloop_lport_get ( lport ) )
16291647 break ;
16301648
1631- __unlink_local_port (lport );
1632-
16331649 spin_unlock_irqrestore (& fcloop_lock , flags );
16341650
16351651 ret = __wait_localport_unreg (lport );
16361652 if (ret )
16371653 pr_warn ("%s: Failed deleting local port\n" , __func__ );
16381654
1655+ fcloop_lport_put (lport );
1656+
16391657 spin_lock_irqsave (& fcloop_lock , flags );
16401658 }
16411659
0 commit comments