@@ -208,6 +208,7 @@ struct fcloop_lport {
208
208
struct nvme_fc_local_port * localport ;
209
209
struct list_head lport_list ;
210
210
struct completion unreg_done ;
211
+ refcount_t ref ;
211
212
};
212
213
213
214
struct fcloop_lport_priv {
@@ -994,6 +995,27 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
994
995
}
995
996
}
996
997
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
+
997
1019
static void
998
1020
fcloop_nport_put (struct fcloop_nport * nport )
999
1021
{
@@ -1017,6 +1039,8 @@ fcloop_localport_delete(struct nvme_fc_local_port *localport)
1017
1039
1018
1040
/* release any threads waiting for the unreg to complete */
1019
1041
complete (& lport -> unreg_done );
1042
+
1043
+ fcloop_lport_put (lport );
1020
1044
}
1021
1045
1022
1046
static void
@@ -1128,6 +1152,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
1128
1152
1129
1153
lport -> localport = localport ;
1130
1154
INIT_LIST_HEAD (& lport -> lport_list );
1155
+ refcount_set (& lport -> ref , 1 );
1131
1156
1132
1157
spin_lock_irqsave (& fcloop_lock , flags );
1133
1158
list_add_tail (& lport -> lport_list , & fcloop_lports );
@@ -1144,13 +1169,6 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
1144
1169
return ret ? ret : count ;
1145
1170
}
1146
1171
1147
-
1148
- static void
1149
- __unlink_local_port (struct fcloop_lport * lport )
1150
- {
1151
- list_del (& lport -> lport_list );
1152
- }
1153
-
1154
1172
static int
1155
1173
__wait_localport_unreg (struct fcloop_lport * lport )
1156
1174
{
@@ -1163,8 +1181,6 @@ __wait_localport_unreg(struct fcloop_lport *lport)
1163
1181
if (!ret )
1164
1182
wait_for_completion (& lport -> unreg_done );
1165
1183
1166
- kfree (lport );
1167
-
1168
1184
return ret ;
1169
1185
}
1170
1186
@@ -1187,8 +1203,9 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
1187
1203
list_for_each_entry (tlport , & fcloop_lports , lport_list ) {
1188
1204
if (tlport -> localport -> node_name == nodename &&
1189
1205
tlport -> localport -> port_name == portname ) {
1206
+ if (!fcloop_lport_get (tlport ))
1207
+ break ;
1190
1208
lport = tlport ;
1191
- __unlink_local_port (lport );
1192
1209
break ;
1193
1210
}
1194
1211
}
@@ -1198,6 +1215,7 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
1198
1215
return - ENOENT ;
1199
1216
1200
1217
ret = __wait_localport_unreg (lport );
1218
+ fcloop_lport_put (lport );
1201
1219
1202
1220
return ret ? ret : count ;
1203
1221
}
@@ -1625,17 +1643,17 @@ static void __exit fcloop_exit(void)
1625
1643
for (;;) {
1626
1644
lport = list_first_entry_or_null (& fcloop_lports ,
1627
1645
typeof (* lport ), lport_list );
1628
- if (!lport )
1646
+ if (!lport || ! fcloop_lport_get ( lport ) )
1629
1647
break ;
1630
1648
1631
- __unlink_local_port (lport );
1632
-
1633
1649
spin_unlock_irqrestore (& fcloop_lock , flags );
1634
1650
1635
1651
ret = __wait_localport_unreg (lport );
1636
1652
if (ret )
1637
1653
pr_warn ("%s: Failed deleting local port\n" , __func__ );
1638
1654
1655
+ fcloop_lport_put (lport );
1656
+
1639
1657
spin_lock_irqsave (& fcloop_lock , flags );
1640
1658
}
1641
1659
0 commit comments