Skip to content

Commit 4d784c0

Browse files
bvanasschejgunthorpe
authored andcommitted
RDMA/srpt: Make slab cache names unique
Since commit 4c39529 ("slab: Warn on duplicate cache names when DEBUG_VM=y"), slab complains about duplicate cache names. Hence this patch. The approach is as follows: - Maintain an xarray with the slab size as index and a reference count and a kmem_cache pointer as contents. Use srpt-${slab_size} as kmem cache name. - Use 512-byte alignment for all slabs instead of only for some of the slabs. - Increment the reference count instead of calling kmem_cache_create(). - Decrement the reference count instead of calling kmem_cache_destroy(). Fixes: 5dabcd0 ("RDMA/srpt: Add support for immediate data") Link: https://patch.msgid.link/r/[email protected] Reported-by: Shinichiro Kawasaki <[email protected]> Closes: https://lore.kernel.org/linux-block/xpe6bea7rakpyoyfvspvin2dsozjmjtjktpph7rep3h25tv7fb@ooz4cu5z6bq6/ Suggested-by: Jason Gunthorpe <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> Tested-by: Shin'ichiro Kawasaki <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 8cddfa5 commit 4d784c0

File tree

1 file changed

+68
-12
lines changed

1 file changed

+68
-12
lines changed

drivers/infiniband/ulp/srpt/ib_srpt.c

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ MODULE_LICENSE("Dual BSD/GPL");
6868
static u64 srpt_service_guid;
6969
static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */
7070
static LIST_HEAD(srpt_dev_list); /* List of srpt_device structures. */
71+
static DEFINE_MUTEX(srpt_mc_mutex); /* Protects srpt_memory_caches. */
72+
static DEFINE_XARRAY(srpt_memory_caches); /* See also srpt_memory_cache_entry */
7173

7274
static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
7375
module_param(srp_max_req_size, int, 0444);
@@ -105,6 +107,63 @@ static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc);
105107
static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc);
106108
static void srpt_process_wait_list(struct srpt_rdma_ch *ch);
107109

110+
/* Type of the entries in srpt_memory_caches. */
111+
struct srpt_memory_cache_entry {
112+
refcount_t ref;
113+
struct kmem_cache *c;
114+
};
115+
116+
static struct kmem_cache *srpt_cache_get(unsigned int object_size)
117+
{
118+
struct srpt_memory_cache_entry *e;
119+
char name[32];
120+
void *res;
121+
122+
guard(mutex)(&srpt_mc_mutex);
123+
e = xa_load(&srpt_memory_caches, object_size);
124+
if (e) {
125+
refcount_inc(&e->ref);
126+
return e->c;
127+
}
128+
snprintf(name, sizeof(name), "srpt-%u", object_size);
129+
e = kmalloc(sizeof(*e), GFP_KERNEL);
130+
if (!e)
131+
return NULL;
132+
refcount_set(&e->ref, 1);
133+
e->c = kmem_cache_create(name, object_size, /*align=*/512, 0, NULL);
134+
if (!e->c)
135+
goto free_entry;
136+
res = xa_store(&srpt_memory_caches, object_size, e, GFP_KERNEL);
137+
if (xa_is_err(res))
138+
goto destroy_cache;
139+
return e->c;
140+
141+
destroy_cache:
142+
kmem_cache_destroy(e->c);
143+
144+
free_entry:
145+
kfree(e);
146+
return NULL;
147+
}
148+
149+
static void srpt_cache_put(struct kmem_cache *c)
150+
{
151+
struct srpt_memory_cache_entry *e = NULL;
152+
unsigned long object_size;
153+
154+
guard(mutex)(&srpt_mc_mutex);
155+
xa_for_each(&srpt_memory_caches, object_size, e)
156+
if (e->c == c)
157+
break;
158+
if (WARN_ON_ONCE(!e))
159+
return;
160+
if (!refcount_dec_and_test(&e->ref))
161+
return;
162+
WARN_ON_ONCE(xa_erase(&srpt_memory_caches, object_size) != e);
163+
kmem_cache_destroy(e->c);
164+
kfree(e);
165+
}
166+
108167
/*
109168
* The only allowed channel state changes are those that change the channel
110169
* state into a state with a higher numerical value. Hence the new > prev test.
@@ -2119,13 +2178,13 @@ static void srpt_release_channel_work(struct work_struct *w)
21192178
ch->sport->sdev, ch->rq_size,
21202179
ch->rsp_buf_cache, DMA_TO_DEVICE);
21212180

2122-
kmem_cache_destroy(ch->rsp_buf_cache);
2181+
srpt_cache_put(ch->rsp_buf_cache);
21232182

21242183
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring,
21252184
sdev, ch->rq_size,
21262185
ch->req_buf_cache, DMA_FROM_DEVICE);
21272186

2128-
kmem_cache_destroy(ch->req_buf_cache);
2187+
srpt_cache_put(ch->req_buf_cache);
21292188

21302189
kref_put(&ch->kref, srpt_free_ch);
21312190
}
@@ -2245,8 +2304,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
22452304
INIT_LIST_HEAD(&ch->cmd_wait_list);
22462305
ch->max_rsp_size = ch->sport->port_attrib.srp_max_rsp_size;
22472306

2248-
ch->rsp_buf_cache = kmem_cache_create("srpt-rsp-buf", ch->max_rsp_size,
2249-
512, 0, NULL);
2307+
ch->rsp_buf_cache = srpt_cache_get(ch->max_rsp_size);
22502308
if (!ch->rsp_buf_cache)
22512309
goto free_ch;
22522310

@@ -2280,8 +2338,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
22802338
alignment_offset = round_up(imm_data_offset, 512) -
22812339
imm_data_offset;
22822340
req_sz = alignment_offset + imm_data_offset + srp_max_req_size;
2283-
ch->req_buf_cache = kmem_cache_create("srpt-req-buf", req_sz,
2284-
512, 0, NULL);
2341+
ch->req_buf_cache = srpt_cache_get(req_sz);
22852342
if (!ch->req_buf_cache)
22862343
goto free_rsp_ring;
22872344

@@ -2478,15 +2535,15 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
24782535
ch->req_buf_cache, DMA_FROM_DEVICE);
24792536

24802537
free_recv_cache:
2481-
kmem_cache_destroy(ch->req_buf_cache);
2538+
srpt_cache_put(ch->req_buf_cache);
24822539

24832540
free_rsp_ring:
24842541
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
24852542
ch->sport->sdev, ch->rq_size,
24862543
ch->rsp_buf_cache, DMA_TO_DEVICE);
24872544

24882545
free_rsp_cache:
2489-
kmem_cache_destroy(ch->rsp_buf_cache);
2546+
srpt_cache_put(ch->rsp_buf_cache);
24902547

24912548
free_ch:
24922549
if (rdma_cm_id)
@@ -3055,7 +3112,7 @@ static void srpt_free_srq(struct srpt_device *sdev)
30553112
srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
30563113
sdev->srq_size, sdev->req_buf_cache,
30573114
DMA_FROM_DEVICE);
3058-
kmem_cache_destroy(sdev->req_buf_cache);
3115+
srpt_cache_put(sdev->req_buf_cache);
30593116
sdev->srq = NULL;
30603117
}
30613118

@@ -3082,8 +3139,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
30823139
pr_debug("create SRQ #wr= %d max_allow=%d dev= %s\n", sdev->srq_size,
30833140
sdev->device->attrs.max_srq_wr, dev_name(&device->dev));
30843141

3085-
sdev->req_buf_cache = kmem_cache_create("srpt-srq-req-buf",
3086-
srp_max_req_size, 0, 0, NULL);
3142+
sdev->req_buf_cache = srpt_cache_get(srp_max_req_size);
30873143
if (!sdev->req_buf_cache)
30883144
goto free_srq;
30893145

@@ -3105,7 +3161,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
31053161
return 0;
31063162

31073163
free_cache:
3108-
kmem_cache_destroy(sdev->req_buf_cache);
3164+
srpt_cache_put(sdev->req_buf_cache);
31093165

31103166
free_srq:
31113167
ib_destroy_srq(srq);

0 commit comments

Comments
 (0)