forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									63dee3a6c3
								
							
						
					
					
						commit
						1864de94ec
					
				
					 1 changed files with 86 additions and 46 deletions
				
			
		|  | @ -26,9 +26,24 @@ static unsigned int write_buffer_size; | ||||||
| module_param(write_buffer_size, uint, 0644); | module_param(write_buffer_size, uint, 0644); | ||||||
| MODULE_PARM_DESC(write_buffer_size, "number of entries in a write buffer"); | MODULE_PARM_DESC(write_buffer_size, "number of entries in a write buffer"); | ||||||
| 
 | 
 | ||||||
| static struct kmem_cache *pblk_ws_cache, *pblk_rec_cache, *pblk_g_rq_cache, | struct pblk_global_caches { | ||||||
| 				*pblk_w_rq_cache; | 	struct kmem_cache	*ws; | ||||||
| static DECLARE_RWSEM(pblk_lock); | 	struct kmem_cache	*rec; | ||||||
|  | 	struct kmem_cache	*g_rq; | ||||||
|  | 	struct kmem_cache	*w_rq; | ||||||
|  | 
 | ||||||
|  | 	struct kref		kref; | ||||||
|  | 
 | ||||||
|  | 	struct mutex		mutex; /* Ensures consistency between
 | ||||||
|  | 					* caches and kref | ||||||
|  | 					*/ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct pblk_global_caches pblk_caches = { | ||||||
|  | 	.mutex = __MUTEX_INITIALIZER(pblk_caches.mutex), | ||||||
|  | 	.kref = KREF_INIT(0), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct bio_set pblk_bio_set; | struct bio_set pblk_bio_set; | ||||||
| 
 | 
 | ||||||
| static int pblk_rw_io(struct request_queue *q, struct pblk *pblk, | static int pblk_rw_io(struct request_queue *q, struct pblk *pblk, | ||||||
|  | @ -307,53 +322,80 @@ static int pblk_set_addrf(struct pblk *pblk) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int pblk_init_global_caches(struct pblk *pblk) | static int pblk_create_global_caches(void) | ||||||
| { | { | ||||||
| 	down_write(&pblk_lock); | 
 | ||||||
| 	pblk_ws_cache = kmem_cache_create("pblk_blk_ws", | 	pblk_caches.ws = kmem_cache_create("pblk_blk_ws", | ||||||
| 				sizeof(struct pblk_line_ws), 0, 0, NULL); | 				sizeof(struct pblk_line_ws), 0, 0, NULL); | ||||||
| 	if (!pblk_ws_cache) { | 	if (!pblk_caches.ws) | ||||||
| 		up_write(&pblk_lock); |  | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	pblk_rec_cache = kmem_cache_create("pblk_rec", | 	pblk_caches.rec = kmem_cache_create("pblk_rec", | ||||||
| 				sizeof(struct pblk_rec_ctx), 0, 0, NULL); | 				sizeof(struct pblk_rec_ctx), 0, 0, NULL); | ||||||
| 	if (!pblk_rec_cache) { | 	if (!pblk_caches.rec) | ||||||
| 		kmem_cache_destroy(pblk_ws_cache); | 		goto fail_destroy_ws; | ||||||
| 		up_write(&pblk_lock); |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	pblk_g_rq_cache = kmem_cache_create("pblk_g_rq", pblk_g_rq_size, | 	pblk_caches.g_rq = kmem_cache_create("pblk_g_rq", pblk_g_rq_size, | ||||||
| 				0, 0, NULL); | 				0, 0, NULL); | ||||||
| 	if (!pblk_g_rq_cache) { | 	if (!pblk_caches.g_rq) | ||||||
| 		kmem_cache_destroy(pblk_ws_cache); | 		goto fail_destroy_rec; | ||||||
| 		kmem_cache_destroy(pblk_rec_cache); |  | ||||||
| 		up_write(&pblk_lock); |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	pblk_w_rq_cache = kmem_cache_create("pblk_w_rq", pblk_w_rq_size, | 	pblk_caches.w_rq = kmem_cache_create("pblk_w_rq", pblk_w_rq_size, | ||||||
| 				0, 0, NULL); | 				0, 0, NULL); | ||||||
| 	if (!pblk_w_rq_cache) { | 	if (!pblk_caches.w_rq) | ||||||
| 		kmem_cache_destroy(pblk_ws_cache); | 		goto fail_destroy_g_rq; | ||||||
| 		kmem_cache_destroy(pblk_rec_cache); |  | ||||||
| 		kmem_cache_destroy(pblk_g_rq_cache); |  | ||||||
| 		up_write(&pblk_lock); |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	} |  | ||||||
| 	up_write(&pblk_lock); |  | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | 
 | ||||||
|  | fail_destroy_g_rq: | ||||||
|  | 	kmem_cache_destroy(pblk_caches.g_rq); | ||||||
|  | fail_destroy_rec: | ||||||
|  | 	kmem_cache_destroy(pblk_caches.rec); | ||||||
|  | fail_destroy_ws: | ||||||
|  | 	kmem_cache_destroy(pblk_caches.ws); | ||||||
|  | 
 | ||||||
|  | 	return -ENOMEM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void pblk_free_global_caches(struct pblk *pblk) | static int pblk_get_global_caches(void) | ||||||
| { | { | ||||||
| 	kmem_cache_destroy(pblk_ws_cache); | 	int ret; | ||||||
| 	kmem_cache_destroy(pblk_rec_cache); | 
 | ||||||
| 	kmem_cache_destroy(pblk_g_rq_cache); | 	mutex_lock(&pblk_caches.mutex); | ||||||
| 	kmem_cache_destroy(pblk_w_rq_cache); | 
 | ||||||
|  | 	if (kref_read(&pblk_caches.kref) > 0) { | ||||||
|  | 		kref_get(&pblk_caches.kref); | ||||||
|  | 		mutex_unlock(&pblk_caches.mutex); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = pblk_create_global_caches(); | ||||||
|  | 
 | ||||||
|  | 	if (!ret) | ||||||
|  | 		kref_get(&pblk_caches.kref); | ||||||
|  | 
 | ||||||
|  | 	mutex_unlock(&pblk_caches.mutex); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void pblk_destroy_global_caches(struct kref *ref) | ||||||
|  | { | ||||||
|  | 	struct pblk_global_caches *c; | ||||||
|  | 
 | ||||||
|  | 	c = container_of(ref, struct pblk_global_caches, kref); | ||||||
|  | 
 | ||||||
|  | 	kmem_cache_destroy(c->ws); | ||||||
|  | 	kmem_cache_destroy(c->rec); | ||||||
|  | 	kmem_cache_destroy(c->g_rq); | ||||||
|  | 	kmem_cache_destroy(c->w_rq); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void pblk_put_global_caches(void) | ||||||
|  | { | ||||||
|  | 	mutex_lock(&pblk_caches.mutex); | ||||||
|  | 	kref_put(&pblk_caches.kref, pblk_destroy_global_caches); | ||||||
|  | 	mutex_unlock(&pblk_caches.mutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int pblk_core_init(struct pblk *pblk) | static int pblk_core_init(struct pblk *pblk) | ||||||
|  | @ -382,7 +424,7 @@ static int pblk_core_init(struct pblk *pblk) | ||||||
| 	if (!pblk->pad_dist) | 	if (!pblk->pad_dist) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	if (pblk_init_global_caches(pblk)) | 	if (pblk_get_global_caches()) | ||||||
| 		goto fail_free_pad_dist; | 		goto fail_free_pad_dist; | ||||||
| 
 | 
 | ||||||
| 	/* Internal bios can be at most the sectors signaled by the device. */ | 	/* Internal bios can be at most the sectors signaled by the device. */ | ||||||
|  | @ -391,27 +433,27 @@ static int pblk_core_init(struct pblk *pblk) | ||||||
| 		goto free_global_caches; | 		goto free_global_caches; | ||||||
| 
 | 
 | ||||||
| 	ret = mempool_init_slab_pool(&pblk->gen_ws_pool, PBLK_GEN_WS_POOL_SIZE, | 	ret = mempool_init_slab_pool(&pblk->gen_ws_pool, PBLK_GEN_WS_POOL_SIZE, | ||||||
| 				     pblk_ws_cache); | 				     pblk_caches.ws); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto free_page_bio_pool; | 		goto free_page_bio_pool; | ||||||
| 
 | 
 | ||||||
| 	ret = mempool_init_slab_pool(&pblk->rec_pool, geo->all_luns, | 	ret = mempool_init_slab_pool(&pblk->rec_pool, geo->all_luns, | ||||||
| 				     pblk_rec_cache); | 				     pblk_caches.rec); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto free_gen_ws_pool; | 		goto free_gen_ws_pool; | ||||||
| 
 | 
 | ||||||
| 	ret = mempool_init_slab_pool(&pblk->r_rq_pool, geo->all_luns, | 	ret = mempool_init_slab_pool(&pblk->r_rq_pool, geo->all_luns, | ||||||
| 				     pblk_g_rq_cache); | 				     pblk_caches.g_rq); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto free_rec_pool; | 		goto free_rec_pool; | ||||||
| 
 | 
 | ||||||
| 	ret = mempool_init_slab_pool(&pblk->e_rq_pool, geo->all_luns, | 	ret = mempool_init_slab_pool(&pblk->e_rq_pool, geo->all_luns, | ||||||
| 				     pblk_g_rq_cache); | 				     pblk_caches.g_rq); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto free_r_rq_pool; | 		goto free_r_rq_pool; | ||||||
| 
 | 
 | ||||||
| 	ret = mempool_init_slab_pool(&pblk->w_rq_pool, geo->all_luns, | 	ret = mempool_init_slab_pool(&pblk->w_rq_pool, geo->all_luns, | ||||||
| 				     pblk_w_rq_cache); | 				     pblk_caches.w_rq); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto free_e_rq_pool; | 		goto free_e_rq_pool; | ||||||
| 
 | 
 | ||||||
|  | @ -457,7 +499,7 @@ static int pblk_core_init(struct pblk *pblk) | ||||||
| free_page_bio_pool: | free_page_bio_pool: | ||||||
| 	mempool_exit(&pblk->page_bio_pool); | 	mempool_exit(&pblk->page_bio_pool); | ||||||
| free_global_caches: | free_global_caches: | ||||||
| 	pblk_free_global_caches(pblk); | 	pblk_put_global_caches(); | ||||||
| fail_free_pad_dist: | fail_free_pad_dist: | ||||||
| 	kfree(pblk->pad_dist); | 	kfree(pblk->pad_dist); | ||||||
| 	return -ENOMEM; | 	return -ENOMEM; | ||||||
|  | @ -481,7 +523,7 @@ static void pblk_core_free(struct pblk *pblk) | ||||||
| 	mempool_exit(&pblk->e_rq_pool); | 	mempool_exit(&pblk->e_rq_pool); | ||||||
| 	mempool_exit(&pblk->w_rq_pool); | 	mempool_exit(&pblk->w_rq_pool); | ||||||
| 
 | 
 | ||||||
| 	pblk_free_global_caches(pblk); | 	pblk_put_global_caches(); | ||||||
| 	kfree(pblk->pad_dist); | 	kfree(pblk->pad_dist); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1074,7 +1116,6 @@ static void pblk_exit(void *private, bool graceful) | ||||||
| { | { | ||||||
| 	struct pblk *pblk = private; | 	struct pblk *pblk = private; | ||||||
| 
 | 
 | ||||||
| 	down_write(&pblk_lock); |  | ||||||
| 	pblk_gc_exit(pblk, graceful); | 	pblk_gc_exit(pblk, graceful); | ||||||
| 	pblk_tear_down(pblk, graceful); | 	pblk_tear_down(pblk, graceful); | ||||||
| 
 | 
 | ||||||
|  | @ -1083,7 +1124,6 @@ static void pblk_exit(void *private, bool graceful) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	pblk_free(pblk); | 	pblk_free(pblk); | ||||||
| 	up_write(&pblk_lock); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static sector_t pblk_capacity(void *private) | static sector_t pblk_capacity(void *private) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Hans Holmberg
						Hans Holmberg