From 1a6ae4b3ebf0b1bf2625bc88b84658d2dc082321 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Fri, 30 Aug 2024 15:53:50 +0200 Subject: [PATCH] LU-18086 sec: do not allocate empty pools If the node does not have enough memory, we might end up allocating empty pools at some orders. Prevent empty pools as they are useless and the rest of the code expect valid pools. Signed-off-by: Sebastien Buisson Change-Id: I9c5d9eeb557df0c91efecd6871654d1e48e5662a Reviewed-by: Sergey Cheremencev Reviewed-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56271 Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/obdclass/page_pools.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/lustre/obdclass/page_pools.c b/lustre/obdclass/page_pools.c index d639a47..0626ebb 100644 --- a/lustre/obdclass/page_pools.c +++ b/lustre/obdclass/page_pools.c @@ -134,11 +134,16 @@ static struct obd_page_pool { static struct shrinker **pool_shrinkers; +/* We try to allocate POOLS_COUNT pools, + * unless the node's memory is too short. + */ +static int pools_count = POOLS_COUNT; + static inline int get_pool_index(struct shrinker *shrinker) { int i; - for (i = 0; i < POOLS_COUNT; i++) + for (i = 0; i < pools_count; i++) if (pool_shrinkers[i] == shrinker) return i; @@ -221,7 +226,7 @@ int page_pools_seq_show(struct seq_file *m, void *v) "pools:\n", cfs_totalram_pages()); - for (pool_order = 0; pool_order < POOLS_COUNT; pool_order++) { + for (pool_order = 0; pool_order < pools_count; pool_order++) { pool = page_pools[pool_order]; if (!pool->opp_st_access) continue; @@ -705,6 +710,14 @@ static inline int __obd_pool_get_objects(void *array, unsigned int count, if (!array || count <= 0 || count > page_pool->opp_max_objects) return -EINVAL; + if (order >= pools_count) { + CDEBUG(D_SEC, + "Requested pool order %d too big, max allocated order %d (chunk size %lu): %d\n", + order, pools_count - 1, PAGE_SIZE << (pools_count - 1), + rc); + return -EINVAL; + } + spin_lock(&page_pool->opp_lock); page_pool->opp_st_access++; @@ -866,7 +879,7 @@ static int __obd_pool_put_objects(void *array, unsigned int count, int p_idx, g_idx; int i, rc = 0; - LASSERTF(order < POOLS_COUNT, "count %u, pool %u\n", + LASSERTF(order < pools_count, "count %u, pool %u\n", count, order); if (!array) { CERROR("Faled to put %u objects, from pool %u\n", @@ -1081,6 +1094,17 @@ int obd_pool_init(void) pool->opp_max_ptr_pages = nobjects_to_nptr_pages(pool->opp_max_objects); + /* If opp_max_ptr_pages is 0, it means there is not enough + * memory on the node to allocate all the pools. So stop the + * loop here to avoid having empty pools. + */ + if (!pool->opp_max_ptr_pages) { + CWARN("Cannot allocate pool %i, not enough memory. Max available compression chunk is %lu.\n", + pool_order, PAGE_SIZE << (pool_order - 1)); + pools_count = pool_order; + OBD_FREE(pool, sizeof(**page_pools)); + break; + } init_waitqueue_head(&pool->opp_waitq); pool->opp_last_shrink = ktime_get_seconds(); @@ -1137,7 +1161,7 @@ void obd_pool_fini(void) int pool_order; struct obd_page_pool *pool; - for (pool_order = 0; pool_order < POOLS_COUNT; pool_order++) { + for (pool_order = 0; pool_order < pools_count; pool_order++) { pool = page_pools[pool_order]; shrinker_free(pool->pool_shrinker); LASSERT(pool->opp_ptr_pages); -- 1.8.3.1