diff options
author | Brian Behlendorf <[email protected]> | 2012-05-01 14:27:29 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2012-05-07 11:54:28 -0700 |
commit | b78d4b9d98b8486199ba9072d7fc345121a4601f (patch) | |
tree | b20e09d5a518c10af2f28d591169b372d83d7ab3 /module/spl/spl-kmem.c | |
parent | 06089b9e1929440e07a9eb7a11e68197a4ab40f2 (diff) |
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 <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #107
Diffstat (limited to 'module/spl/spl-kmem.c')
-rw-r--r-- | module/spl/spl-kmem.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c index f7d5f7e86..e1d74d3c0 100644 --- a/module/spl/spl-kmem.c +++ b/module/spl/spl-kmem.c @@ -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); |