mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 19:19:32 +03:00
Ensure a minimum of one slab is reclaimed
To minimize the chance of triggering an OOM during direct reclaim. The kmem caches have been improved to make a best effort to reclaim at least one slab when a reclaim function is registered. This helps avoid the case where objects are released but they are spread over multiple slabs so no memory gets reclaimed. Care has been taken to avoid deadlocking if the reclaim function is unable to make forward progress. Additionally, the reclaim function may be skipped entirely if there are already free slabs which can be safely reaped. Signed-off-by: Prakash Surya <surya1@llnl.gov> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #107
This commit is contained in:
parent
06089b9e19
commit
b78d4b9d98
@ -1923,8 +1923,38 @@ spl_kmem_cache_reap_now(spl_kmem_cache_t *skc, int count)
|
||||
|
||||
atomic_inc(&skc->skc_ref);
|
||||
|
||||
if (skc->skc_reclaim)
|
||||
skc->skc_reclaim(skc->skc_private);
|
||||
/*
|
||||
* When a reclaim function is available it may be invoked repeatedly
|
||||
* until at least a single slab can be freed. This ensures that we
|
||||
* do free memory back to the system. This helps minimize the chance
|
||||
* of an OOM event when the bulk of memory is used by the slab.
|
||||
*
|
||||
* When free slabs are already available the reclaim callback will be
|
||||
* skipped. Additionally, if no forward progress is detected despite
|
||||
* a reclaim function the cache will be skipped to avoid deadlock.
|
||||
*
|
||||
* Longer term this would be the correct place to add the code which
|
||||
* repacks the slabs in order minimize fragmentation.
|
||||
*/
|
||||
if (skc->skc_reclaim) {
|
||||
uint64_t objects = UINT64_MAX;
|
||||
int do_reclaim;
|
||||
|
||||
do {
|
||||
spin_lock(&skc->skc_lock);
|
||||
do_reclaim =
|
||||
(skc->skc_slab_total > 0) &&
|
||||
((skc->skc_slab_total - skc->skc_slab_alloc) == 0) &&
|
||||
(skc->skc_obj_alloc < objects);
|
||||
|
||||
objects = skc->skc_obj_alloc;
|
||||
spin_unlock(&skc->skc_lock);
|
||||
|
||||
if (do_reclaim)
|
||||
skc->skc_reclaim(skc->skc_private);
|
||||
|
||||
} while (do_reclaim);
|
||||
}
|
||||
|
||||
/* Reclaim from the cache, ignoring it's age and delay. */
|
||||
spl_slab_reclaim(skc, count, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user