diff options
author | Hans Holmberg <hans.holmberg@cnexlabs.com> | 2018-10-09 07:11:58 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-10-09 10:25:07 -0400 |
commit | 1864de94ec9d6e1ae4d481212847374df9b1be41 (patch) | |
tree | 05bf1d0ff69e95206cd7b6950380ff558e24af11 /drivers/lightnvm | |
parent | 63dee3a6c39a5bfa5f299ebb314f2e3e0273092b (diff) |
lightnvm: pblk: stop recreating global caches
Pblk should not create a set of global caches every time
a pblk instance is created. The global caches should be
made available only when there is one or more pblk instances.
This patch bundles the global caches together with a kref
keeping track of whether the caches should be available or not.
Also, turn the global pblk lock into a mutex that explicitly
protects the caches (as this was the only purpose of the lock).
Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm')
-rw-r--r-- | drivers/lightnvm/pblk-init.c | 132 |
1 files changed, 86 insertions, 46 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index 9aebdee8e4c9..fb66bc84d5ca 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c | |||
@@ -26,9 +26,24 @@ static unsigned int write_buffer_size; | |||
26 | module_param(write_buffer_size, uint, 0644); | 26 | module_param(write_buffer_size, uint, 0644); |
27 | MODULE_PARM_DESC(write_buffer_size, "number of entries in a write buffer"); | 27 | MODULE_PARM_DESC(write_buffer_size, "number of entries in a write buffer"); |
28 | 28 | ||
29 | static struct kmem_cache *pblk_ws_cache, *pblk_rec_cache, *pblk_g_rq_cache, | 29 | struct pblk_global_caches { |
30 | *pblk_w_rq_cache; | 30 | struct kmem_cache *ws; |
31 | static DECLARE_RWSEM(pblk_lock); | 31 | struct kmem_cache *rec; |
32 | struct kmem_cache *g_rq; | ||
33 | struct kmem_cache *w_rq; | ||
34 | |||
35 | struct kref kref; | ||
36 | |||
37 | struct mutex mutex; /* Ensures consistency between | ||
38 | * caches and kref | ||
39 | */ | ||
40 | }; | ||
41 | |||
42 | static struct pblk_global_caches pblk_caches = { | ||
43 | .mutex = __MUTEX_INITIALIZER(pblk_caches.mutex), | ||
44 | .kref = KREF_INIT(0), | ||
45 | }; | ||
46 | |||
32 | struct bio_set pblk_bio_set; | 47 | struct bio_set pblk_bio_set; |
33 | 48 | ||
34 | static int pblk_rw_io(struct request_queue *q, struct pblk *pblk, | 49 | static int pblk_rw_io(struct request_queue *q, struct pblk *pblk, |
@@ -307,53 +322,80 @@ static int pblk_set_addrf(struct pblk *pblk) | |||
307 | return 0; | 322 | return 0; |
308 | } | 323 | } |
309 | 324 | ||
310 | static int pblk_init_global_caches(struct pblk *pblk) | 325 | static int pblk_create_global_caches(void) |
311 | { | 326 | { |
312 | down_write(&pblk_lock); | 327 | |
313 | pblk_ws_cache = kmem_cache_create("pblk_blk_ws", | 328 | pblk_caches.ws = kmem_cache_create("pblk_blk_ws", |
314 | sizeof(struct pblk_line_ws), 0, 0, NULL); | 329 | sizeof(struct pblk_line_ws), 0, 0, NULL); |
315 | if (!pblk_ws_cache) { | 330 | if (!pblk_caches.ws) |
316 | up_write(&pblk_lock); | ||
317 | return -ENOMEM; | 331 | return -ENOMEM; |
318 | } | ||
319 | 332 | ||
320 | pblk_rec_cache = kmem_cache_create("pblk_rec", | 333 | pblk_caches.rec = kmem_cache_create("pblk_rec", |
321 | sizeof(struct pblk_rec_ctx), 0, 0, NULL); | 334 | sizeof(struct pblk_rec_ctx), 0, 0, NULL); |
322 | if (!pblk_rec_cache) { | 335 | if (!pblk_caches.rec) |
323 | kmem_cache_destroy(pblk_ws_cache); | 336 | goto fail_destroy_ws; |
324 | up_write(&pblk_lock); | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | 337 | ||
328 | pblk_g_rq_cache = kmem_cache_create("pblk_g_rq", pblk_g_rq_size, | 338 | pblk_caches.g_rq = kmem_cache_create("pblk_g_rq", pblk_g_rq_size, |
329 | 0, 0, NULL); | 339 | 0, 0, NULL); |
330 | if (!pblk_g_rq_cache) { | 340 | if (!pblk_caches.g_rq) |
331 | kmem_cache_destroy(pblk_ws_cache); | 341 | goto fail_destroy_rec; |
332 | kmem_cache_destroy(pblk_rec_cache); | ||
333 | up_write(&pblk_lock); | ||
334 | return -ENOMEM; | ||
335 | } | ||
336 | 342 | ||
337 | pblk_w_rq_cache = kmem_cache_create("pblk_w_rq", pblk_w_rq_size, | 343 | pblk_caches.w_rq = kmem_cache_create("pblk_w_rq", pblk_w_rq_size, |
338 | 0, 0, NULL); | 344 | 0, 0, NULL); |
339 | if (!pblk_w_rq_cache) { | 345 | if (!pblk_caches.w_rq) |
340 | kmem_cache_destroy(pblk_ws_cache); | 346 | goto fail_destroy_g_rq; |
341 | kmem_cache_destroy(pblk_rec_cache); | ||
342 | kmem_cache_destroy(pblk_g_rq_cache); | ||
343 | up_write(&pblk_lock); | ||
344 | return -ENOMEM; | ||
345 | } | ||
346 | up_write(&pblk_lock); | ||
347 | 347 | ||
348 | return 0; | 348 | return 0; |
349 | |||
350 | fail_destroy_g_rq: | ||
351 | kmem_cache_destroy(pblk_caches.g_rq); | ||
352 | fail_destroy_rec: | ||
353 | kmem_cache_destroy(pblk_caches.rec); | ||
354 | fail_destroy_ws: | ||
355 | kmem_cache_destroy(pblk_caches.ws); | ||
356 | |||
357 | return -ENOMEM; | ||
358 | } | ||
359 | |||
360 | static int pblk_get_global_caches(void) | ||
361 | { | ||
362 | int ret; | ||
363 | |||
364 | mutex_lock(&pblk_caches.mutex); | ||
365 | |||
366 | if (kref_read(&pblk_caches.kref) > 0) { | ||
367 | kref_get(&pblk_caches.kref); | ||
368 | mutex_unlock(&pblk_caches.mutex); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | ret = pblk_create_global_caches(); | ||
373 | |||
374 | if (!ret) | ||
375 | kref_get(&pblk_caches.kref); | ||
376 | |||
377 | mutex_unlock(&pblk_caches.mutex); | ||
378 | |||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static void pblk_destroy_global_caches(struct kref *ref) | ||
383 | { | ||
384 | struct pblk_global_caches *c; | ||
385 | |||
386 | c = container_of(ref, struct pblk_global_caches, kref); | ||
387 | |||
388 | kmem_cache_destroy(c->ws); | ||
389 | kmem_cache_destroy(c->rec); | ||
390 | kmem_cache_destroy(c->g_rq); | ||
391 | kmem_cache_destroy(c->w_rq); | ||
349 | } | 392 | } |
350 | 393 | ||
351 | static void pblk_free_global_caches(struct pblk *pblk) | 394 | static void pblk_put_global_caches(void) |
352 | { | 395 | { |
353 | kmem_cache_destroy(pblk_ws_cache); | 396 | mutex_lock(&pblk_caches.mutex); |
354 | kmem_cache_destroy(pblk_rec_cache); | 397 | kref_put(&pblk_caches.kref, pblk_destroy_global_caches); |
355 | kmem_cache_destroy(pblk_g_rq_cache); | 398 | mutex_unlock(&pblk_caches.mutex); |
356 | kmem_cache_destroy(pblk_w_rq_cache); | ||
357 | } | 399 | } |
358 | 400 | ||
359 | static int pblk_core_init(struct pblk *pblk) | 401 | static int pblk_core_init(struct pblk *pblk) |
@@ -382,7 +424,7 @@ static int pblk_core_init(struct pblk *pblk) | |||
382 | if (!pblk->pad_dist) | 424 | if (!pblk->pad_dist) |
383 | return -ENOMEM; | 425 | return -ENOMEM; |
384 | 426 | ||
385 | if (pblk_init_global_caches(pblk)) | 427 | if (pblk_get_global_caches()) |
386 | goto fail_free_pad_dist; | 428 | goto fail_free_pad_dist; |
387 | 429 | ||
388 | /* Internal bios can be at most the sectors signaled by the device. */ | 430 | /* Internal bios can be at most the sectors signaled by the device. */ |
@@ -391,27 +433,27 @@ static int pblk_core_init(struct pblk *pblk) | |||
391 | goto free_global_caches; | 433 | goto free_global_caches; |
392 | 434 | ||
393 | ret = mempool_init_slab_pool(&pblk->gen_ws_pool, PBLK_GEN_WS_POOL_SIZE, | 435 | ret = mempool_init_slab_pool(&pblk->gen_ws_pool, PBLK_GEN_WS_POOL_SIZE, |
394 | pblk_ws_cache); | 436 | pblk_caches.ws); |
395 | if (ret) | 437 | if (ret) |
396 | goto free_page_bio_pool; | 438 | goto free_page_bio_pool; |
397 | 439 | ||
398 | ret = mempool_init_slab_pool(&pblk->rec_pool, geo->all_luns, | 440 | ret = mempool_init_slab_pool(&pblk->rec_pool, geo->all_luns, |
399 | pblk_rec_cache); | 441 | pblk_caches.rec); |
400 | if (ret) | 442 | if (ret) |
401 | goto free_gen_ws_pool; | 443 | goto free_gen_ws_pool; |
402 | 444 | ||
403 | ret = mempool_init_slab_pool(&pblk->r_rq_pool, geo->all_luns, | 445 | ret = mempool_init_slab_pool(&pblk->r_rq_pool, geo->all_luns, |
404 | pblk_g_rq_cache); | 446 | pblk_caches.g_rq); |
405 | if (ret) | 447 | if (ret) |
406 | goto free_rec_pool; | 448 | goto free_rec_pool; |
407 | 449 | ||
408 | ret = mempool_init_slab_pool(&pblk->e_rq_pool, geo->all_luns, | 450 | ret = mempool_init_slab_pool(&pblk->e_rq_pool, geo->all_luns, |
409 | pblk_g_rq_cache); | 451 | pblk_caches.g_rq); |
410 | if (ret) | 452 | if (ret) |
411 | goto free_r_rq_pool; | 453 | goto free_r_rq_pool; |
412 | 454 | ||
413 | ret = mempool_init_slab_pool(&pblk->w_rq_pool, geo->all_luns, | 455 | ret = mempool_init_slab_pool(&pblk->w_rq_pool, geo->all_luns, |
414 | pblk_w_rq_cache); | 456 | pblk_caches.w_rq); |
415 | if (ret) | 457 | if (ret) |
416 | goto free_e_rq_pool; | 458 | goto free_e_rq_pool; |
417 | 459 | ||
@@ -457,7 +499,7 @@ free_gen_ws_pool: | |||
457 | free_page_bio_pool: | 499 | free_page_bio_pool: |
458 | mempool_exit(&pblk->page_bio_pool); | 500 | mempool_exit(&pblk->page_bio_pool); |
459 | free_global_caches: | 501 | free_global_caches: |
460 | pblk_free_global_caches(pblk); | 502 | pblk_put_global_caches(); |
461 | fail_free_pad_dist: | 503 | fail_free_pad_dist: |
462 | kfree(pblk->pad_dist); | 504 | kfree(pblk->pad_dist); |
463 | return -ENOMEM; | 505 | return -ENOMEM; |
@@ -481,7 +523,7 @@ static void pblk_core_free(struct pblk *pblk) | |||
481 | mempool_exit(&pblk->e_rq_pool); | 523 | mempool_exit(&pblk->e_rq_pool); |
482 | mempool_exit(&pblk->w_rq_pool); | 524 | mempool_exit(&pblk->w_rq_pool); |
483 | 525 | ||
484 | pblk_free_global_caches(pblk); | 526 | pblk_put_global_caches(); |
485 | kfree(pblk->pad_dist); | 527 | kfree(pblk->pad_dist); |
486 | } | 528 | } |
487 | 529 | ||
@@ -1074,7 +1116,6 @@ static void pblk_exit(void *private, bool graceful) | |||
1074 | { | 1116 | { |
1075 | struct pblk *pblk = private; | 1117 | struct pblk *pblk = private; |
1076 | 1118 | ||
1077 | down_write(&pblk_lock); | ||
1078 | pblk_gc_exit(pblk, graceful); | 1119 | pblk_gc_exit(pblk, graceful); |
1079 | pblk_tear_down(pblk, graceful); | 1120 | pblk_tear_down(pblk, graceful); |
1080 | 1121 | ||
@@ -1083,7 +1124,6 @@ static void pblk_exit(void *private, bool graceful) | |||
1083 | #endif | 1124 | #endif |
1084 | 1125 | ||
1085 | pblk_free(pblk); | 1126 | pblk_free(pblk); |
1086 | up_write(&pblk_lock); | ||
1087 | } | 1127 | } |
1088 | 1128 | ||
1089 | static sector_t pblk_capacity(void *private) | 1129 | static sector_t pblk_capacity(void *private) |