Skip to content

Commit 3c6ae37

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: iscsi: Release endpoint ID when its freed
We can't release the endpoint ID until all references to the endpoint have been dropped or it could be allocated while in use. This has us use an idr instead of looping over all conns to find a free ID and then free the ID when all references have been dropped instead of when the device is only deleted. Link: https://lore.kernel.org/r/20220408001314.5014-4-michael.christie@oracle.com Tested-by: Manish Rangankar <mrangankar@marvell.com> Reviewed-by: Lee Duncan <lduncan@suse.com> Reviewed-by: Chris Leech <cleech@redhat.com> Reviewed-by: Wu Bo <wubo40@huawei.com> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent cbd2283 commit 3c6ae37

File tree

2 files changed

+36
-37
lines changed

2 files changed

+36
-37
lines changed

drivers/scsi/scsi_transport_iscsi.c

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ struct iscsi_internal {
8686
struct transport_container session_cont;
8787
};
8888

89+
static DEFINE_IDR(iscsi_ep_idr);
90+
static DEFINE_MUTEX(iscsi_ep_idr_mutex);
91+
8992
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
9093

9194
static struct workqueue_struct *iscsi_conn_cleanup_workq;
@@ -168,6 +171,11 @@ struct device_attribute dev_attr_##_prefix##_##_name = \
168171
static void iscsi_endpoint_release(struct device *dev)
169172
{
170173
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
174+
175+
mutex_lock(&iscsi_ep_idr_mutex);
176+
idr_remove(&iscsi_ep_idr, ep->id);
177+
mutex_unlock(&iscsi_ep_idr_mutex);
178+
171179
kfree(ep);
172180
}
173181

@@ -180,7 +188,7 @@ static ssize_t
180188
show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
181189
{
182190
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
183-
return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id);
191+
return sysfs_emit(buf, "%d\n", ep->id);
184192
}
185193
static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
186194

@@ -193,48 +201,32 @@ static struct attribute_group iscsi_endpoint_group = {
193201
.attrs = iscsi_endpoint_attrs,
194202
};
195203

196-
#define ISCSI_MAX_EPID -1
197-
198-
static int iscsi_match_epid(struct device *dev, const void *data)
199-
{
200-
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
201-
const uint64_t *epid = data;
202-
203-
return *epid == ep->id;
204-
}
205-
206204
struct iscsi_endpoint *
207205
iscsi_create_endpoint(int dd_size)
208206
{
209-
struct device *dev;
210207
struct iscsi_endpoint *ep;
211-
uint64_t id;
212-
int err;
213-
214-
for (id = 1; id < ISCSI_MAX_EPID; id++) {
215-
dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
216-
iscsi_match_epid);
217-
if (!dev)
218-
break;
219-
else
220-
put_device(dev);
221-
}
222-
if (id == ISCSI_MAX_EPID) {
223-
printk(KERN_ERR "Too many connections. Max supported %u\n",
224-
ISCSI_MAX_EPID - 1);
225-
return NULL;
226-
}
208+
int err, id;
227209

228210
ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
229211
if (!ep)
230212
return NULL;
231213

214+
mutex_lock(&iscsi_ep_idr_mutex);
215+
id = idr_alloc(&iscsi_ep_idr, ep, 0, -1, GFP_NOIO);
216+
if (id < 0) {
217+
mutex_unlock(&iscsi_ep_idr_mutex);
218+
printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n",
219+
id);
220+
goto free_ep;
221+
}
222+
mutex_unlock(&iscsi_ep_idr_mutex);
223+
232224
ep->id = id;
233225
ep->dev.class = &iscsi_endpoint_class;
234-
dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
226+
dev_set_name(&ep->dev, "ep-%d", id);
235227
err = device_register(&ep->dev);
236228
if (err)
237-
goto free_ep;
229+
goto free_id;
238230

239231
err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
240232
if (err)
@@ -248,6 +240,10 @@ iscsi_create_endpoint(int dd_size)
248240
device_unregister(&ep->dev);
249241
return NULL;
250242

243+
free_id:
244+
mutex_lock(&iscsi_ep_idr_mutex);
245+
idr_remove(&iscsi_ep_idr, id);
246+
mutex_unlock(&iscsi_ep_idr_mutex);
251247
free_ep:
252248
kfree(ep);
253249
return NULL;
@@ -275,14 +271,17 @@ EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
275271
*/
276272
struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
277273
{
278-
struct device *dev;
274+
struct iscsi_endpoint *ep;
279275

280-
dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
281-
iscsi_match_epid);
282-
if (!dev)
283-
return NULL;
276+
mutex_lock(&iscsi_ep_idr_mutex);
277+
ep = idr_find(&iscsi_ep_idr, handle);
278+
if (!ep)
279+
goto unlock;
284280

285-
return iscsi_dev_to_endpoint(dev);
281+
get_device(&ep->dev);
282+
unlock:
283+
mutex_unlock(&iscsi_ep_idr_mutex);
284+
return ep;
286285
}
287286
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
288287

include/scsi/scsi_transport_iscsi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
295295
struct iscsi_endpoint {
296296
void *dd_data; /* LLD private data */
297297
struct device dev;
298-
uint64_t id;
298+
int id;
299299
struct iscsi_cls_conn *conn;
300300
};
301301

0 commit comments

Comments
 (0)