Implement memory and CPU hotplug

ZFS currently doesn't react to hotplugging cpu or memory into the 
system in any way. This patch changes that by adding logic to the ARC 
that allows the system to take advantage of new memory that is added 
for caching purposes. It also adds logic to the taskq infrastructure 
to support dynamically expanding the number of threads allocated to a 
taskq.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Matthew Ahrens <matthew.ahrens@delphix.com>
Co-authored-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Paul Dagnelie <pcd@delphix.com>
Closes #11212
This commit is contained in:
Paul Dagnelie
2020-12-10 14:09:23 -08:00
committed by GitHub
parent f483daa870
commit 60a4c7d2a2
14 changed files with 290 additions and 36 deletions
+77 -11
View File
@@ -48,6 +48,8 @@
#include <sys/vmsystm.h>
#include <sys/zpl.h>
#include <linux/page_compat.h>
#include <linux/notifier.h>
#include <linux/memory.h>
#endif
#include <sys/callb.h>
#include <sys/kstat.h>
@@ -73,6 +75,9 @@
*/
int zfs_arc_shrinker_limit = 10000;
#ifdef CONFIG_MEMORY_HOTPLUG
static struct notifier_block arc_hotplug_callback_mem_nb;
#endif
/*
* Return a default max arc size based on the amount of physical memory.
@@ -278,18 +283,9 @@ arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg)
return (0);
}
void
arc_lowmem_init(void)
static void
arc_set_sys_free(uint64_t allmem)
{
uint64_t allmem = arc_all_memory();
/*
* Register a shrinker to support synchronous (direct) memory
* reclaim from the arc. This is done to prevent kswapd from
* swapping out pages when it is preferable to shrink the arc.
*/
spl_register_shrinker(&arc_shrinker);
/*
* The ARC tries to keep at least this much memory available for the
* system. This gives the ARC time to shrink in response to memory
@@ -342,6 +338,20 @@ arc_lowmem_init(void)
arc_sys_free = wmark * 3 + allmem / 32;
}
void
arc_lowmem_init(void)
{
uint64_t allmem = arc_all_memory();
/*
* Register a shrinker to support synchronous (direct) memory
* reclaim from the arc. This is done to prevent kswapd from
* swapping out pages when it is preferable to shrink the arc.
*/
spl_register_shrinker(&arc_shrinker);
arc_set_sys_free(allmem);
}
void
arc_lowmem_fini(void)
{
@@ -375,6 +385,52 @@ param_set_arc_int(const char *buf, zfs_kernel_param_t *kp)
return (0);
}
#ifdef CONFIG_MEMORY_HOTPLUG
/* ARGSUSED */
static int
arc_hotplug_callback(struct notifier_block *self, unsigned long action,
void *arg)
{
uint64_t allmem = arc_all_memory();
if (action != MEM_ONLINE)
return (NOTIFY_OK);
arc_set_limits(allmem);
#ifdef __LP64__
if (zfs_dirty_data_max_max == 0)
zfs_dirty_data_max_max = MIN(4ULL * 1024 * 1024 * 1024,
allmem * zfs_dirty_data_max_max_percent / 100);
#else
if (zfs_dirty_data_max_max == 0)
zfs_dirty_data_max_max = MIN(1ULL * 1024 * 1024 * 1024,
allmem * zfs_dirty_data_max_max_percent / 100);
#endif
arc_set_sys_free(allmem);
return (NOTIFY_OK);
}
#endif
void
arc_register_hotplug(void)
{
#ifdef CONFIG_MEMORY_HOTPLUG
arc_hotplug_callback_mem_nb.notifier_call = arc_hotplug_callback;
/* There is no significance to the value 100 */
arc_hotplug_callback_mem_nb.priority = 100;
register_memory_notifier(&arc_hotplug_callback_mem_nb);
#endif
}
void
arc_unregister_hotplug(void)
{
#ifdef CONFIG_MEMORY_HOTPLUG
unregister_memory_notifier(&arc_hotplug_callback_mem_nb);
#endif
}
#else /* _KERNEL */
int64_t
arc_available_memory(void)
@@ -405,6 +461,16 @@ arc_free_memory(void)
{
return (spa_get_random(arc_all_memory() * 20 / 100));
}
void
arc_register_hotplug(void)
{
}
void
arc_unregister_hotplug(void)
{
}
#endif /* _KERNEL */
/*