scst: make tgt_dev per-CPU array directly referenced

Modern distributions come with kernels configured for thousands CPUs
(NR_CPUS), which leads to per-CPU array of SGV pool references in each
tgt_dev exceed tens of KB requiring high order page allocations that are
not reliable on aged systems leading to inabilities to create new
sessions.

Reported-by: Jose Martins <jose.martins2307@gmail.com>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7373 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2018-02-16 05:27:51 +00:00
parent fa153f9b96
commit 464b87730c
3 changed files with 48 additions and 54 deletions

View File

@@ -3148,11 +3148,7 @@ struct scst_tgt_dev {
gfp_t tgt_dev_gfp_mask;
/* SGV pool from which buffers of this tgt_dev's cmds should be allocated */
#ifdef CONFIG_CPUMASK_OFFSTACK
struct sgv_pool **pools;
#else
struct sgv_pool *pools[NR_CPUS];
#endif
/* Max number of allowed in this tgt_dev SG segments */
int max_sg_cnt;

View File

@@ -5276,16 +5276,6 @@ static int scst_alloc_add_tgt_dev(struct scst_session *sess,
else
clear_bit(SCST_TGT_DEV_BLACK_HOLE, &tgt_dev->tgt_dev_flags);
#ifdef CONFIG_CPUMASK_OFFSTACK
tgt_dev->pools = kzalloc_node(sizeof(tgt_dev->pools[0])*NR_CPUS,
GFP_KERNEL, dev->dev_numa_node_id);
if (tgt_dev->pools == NULL) {
PRINT_ERROR("Unable to alloc tgt_dev->pools (size %zd)",
sizeof(tgt_dev->pools[0])*NR_CPUS);
goto out_free;
}
#endif
scst_sgv_pool_use_norm(tgt_dev);
if (dev->scsi_dev != NULL) {
@@ -5406,11 +5396,7 @@ out_dec_free:
out_free_ua:
scst_free_all_UA(tgt_dev);
#ifdef CONFIG_CPUMASK_OFFSTACK
kfree(tgt_dev->pools);
out_free:
#endif
kmem_cache_free(scst_tgtd_cachep, tgt_dev);
goto out;
}
@@ -5468,10 +5454,6 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
scst_tgt_dev_stop_threads(tgt_dev);
#ifdef CONFIG_CPUMASK_OFFSTACK
kfree(tgt_dev->pools);
#endif
kmem_cache_free(scst_tgtd_cachep, tgt_dev);
TRACE_EXIT();

View File

@@ -46,6 +46,12 @@ static struct sgv_pool *sgv_dma_pool_per_cpu[NR_CPUS];
static struct sgv_pool *sgv_norm_clust_pool_per_cpu[NR_CPUS];
static struct sgv_pool *sgv_norm_pool_per_cpu[NR_CPUS];
static struct sgv_pool *sgv_dma_pool_global[NR_CPUS];
static struct sgv_pool *sgv_norm_clust_pool_global[NR_CPUS];
static struct sgv_pool *sgv_norm_pool_global[NR_CPUS];
static struct sgv_pool *sgv_norm_clust_pool_main, *sgv_norm_pool_main, *sgv_dma_pool_main;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#if defined(CONFIG_LOCKDEP) && !defined(CONFIG_SCST_PROC)
static struct lock_class_key scst_pool_key;
@@ -54,8 +60,6 @@ static struct lockdep_map scst_pool_dep_map =
#endif
#endif
static struct sgv_pool *sgv_norm_clust_pool, *sgv_norm_pool, *sgv_dma_pool;
#ifndef CONFIG_SCST_NO_TOTAL_MEM_CHECKS
static atomic_t sgv_pages_total = ATOMIC_INIT(0);
#endif
@@ -103,39 +107,33 @@ static inline bool sgv_pool_clustered(const struct sgv_pool *pool)
void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev)
{
int i;
tgt_dev->tgt_dev_gfp_mask = __GFP_NOWARN;
for (i = 0; i < NR_CPUS; i++)
if (!scst_force_global_sgv_pool)
tgt_dev->pools[i] = sgv_norm_pool_per_cpu[i];
else
tgt_dev->pools[i] = sgv_norm_pool;
if (!scst_force_global_sgv_pool)
tgt_dev->pools = sgv_norm_pool_per_cpu;
else
tgt_dev->pools = sgv_norm_pool_global;
tgt_dev->tgt_dev_clust_pool = 0;
}
void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev)
{
int i;
TRACE_MEM("%s", "Use clustering");
tgt_dev->tgt_dev_gfp_mask = __GFP_NOWARN;
for (i = 0; i < NR_CPUS; i++)
if (!scst_force_global_sgv_pool)
tgt_dev->pools[i] = sgv_norm_clust_pool_per_cpu[i];
else
tgt_dev->pools[i] = sgv_norm_clust_pool;
if (!scst_force_global_sgv_pool)
tgt_dev->pools = sgv_norm_clust_pool_per_cpu;
else
tgt_dev->pools = sgv_norm_clust_pool_global;
tgt_dev->tgt_dev_clust_pool = 1;
}
void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev)
{
int i;
TRACE_MEM("%s", "Use ISA DMA memory");
tgt_dev->tgt_dev_gfp_mask = __GFP_NOWARN | GFP_DMA;
for (i = 0; i < NR_CPUS; i++)
if (!scst_force_global_sgv_pool)
tgt_dev->pools[i] = sgv_dma_pool_per_cpu[i];
else
tgt_dev->pools[i] = sgv_dma_pool;
if (!scst_force_global_sgv_pool)
tgt_dev->pools = sgv_dma_pool_per_cpu;
else
tgt_dev->pools = sgv_dma_pool_global;
tgt_dev->tgt_dev_clust_pool = 0;
}
@@ -1760,18 +1758,18 @@ int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
sgv_evaluate_local_max_pages();
sgv_norm_pool = sgv_pool_create("sgv", sgv_no_clustering, 0, false, 0);
if (sgv_norm_pool == NULL)
sgv_norm_pool_main = sgv_pool_create("sgv", sgv_no_clustering, 0, false, 0);
if (sgv_norm_pool_main == NULL)
goto out_free_pool;
sgv_norm_clust_pool = sgv_pool_create("sgv-clust",
sgv_norm_clust_pool_main = sgv_pool_create("sgv-clust",
sgv_full_clustering, 0, false, 0);
if (sgv_norm_clust_pool == NULL)
if (sgv_norm_clust_pool_main == NULL)
goto out_free_norm;
sgv_dma_pool = sgv_pool_create("sgv-dma", sgv_no_clustering, 0,
sgv_dma_pool_main = sgv_pool_create("sgv-dma", sgv_no_clustering, 0,
false, 0);
if (sgv_dma_pool == NULL)
if (sgv_dma_pool_main == NULL)
goto out_free_clust;
/*
@@ -1779,6 +1777,15 @@ int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
* callbacks must be installed!
*/
for (i = 0; i < NR_CPUS; i++)
sgv_norm_pool_global[i] = sgv_norm_pool_main;
for (i = 0; i < NR_CPUS; i++)
sgv_norm_clust_pool_global[i] = sgv_norm_clust_pool_main;
for (i = 0; i < NR_CPUS; i++)
sgv_dma_pool_global[i] = sgv_dma_pool_main;
for (i = 0; i < NR_CPUS; i++) {
char name[60];
if (!cpu_online(i))
@@ -1844,13 +1851,13 @@ out_free_per_cpu_norm:
if (sgv_norm_pool_per_cpu[i] != NULL)
sgv_pool_destroy(sgv_norm_pool_per_cpu[i]);
sgv_pool_destroy(sgv_dma_pool);
sgv_pool_destroy(sgv_dma_pool_main);
out_free_clust:
sgv_pool_destroy(sgv_norm_clust_pool);
sgv_pool_destroy(sgv_norm_clust_pool_main);
out_free_norm:
sgv_pool_destroy(sgv_norm_pool);
sgv_pool_destroy(sgv_norm_pool_main);
out_free_pool:
kmem_cache_destroy(sgv_pool_cachep);
@@ -1872,21 +1879,30 @@ void scst_sgv_pools_deinit(void)
unregister_shrinker(&sgv_shrinker);
#endif
sgv_pool_destroy(sgv_dma_pool);
sgv_pool_destroy(sgv_dma_pool_main);
for (i = 0; i < NR_CPUS; i++)
if (sgv_dma_pool_per_cpu[i] != NULL)
sgv_pool_destroy(sgv_dma_pool_per_cpu[i]);
sgv_pool_destroy(sgv_norm_pool);
sgv_pool_destroy(sgv_norm_pool_main);
for (i = 0; i < NR_CPUS; i++)
if (sgv_norm_pool_per_cpu[i] != NULL)
sgv_pool_destroy(sgv_norm_pool_per_cpu[i]);
sgv_pool_destroy(sgv_norm_clust_pool);
sgv_pool_destroy(sgv_norm_clust_pool_main);
for (i = 0; i < NR_CPUS; i++)
if (sgv_norm_clust_pool_per_cpu[i] != NULL)
sgv_pool_destroy(sgv_norm_clust_pool_per_cpu[i]);
for (i = 0; i < NR_CPUS; i++)
sgv_norm_pool_global[i] = NULL;
for (i = 0; i < NR_CPUS; i++)
sgv_norm_clust_pool_global[i] = NULL;
for (i = 0; i < NR_CPUS; i++)
sgv_dma_pool_global[i] = NULL;
kmem_cache_destroy(sgv_pool_cachep);
TRACE_EXIT();