diff options
author | mav <mav@FreeBSD.org> | 2013-11-23 13:42:56 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2013-11-23 13:42:56 +0000 |
commit | 21d101ccc523a786a6b5d18d7d784eae8017e9c5 (patch) | |
tree | 52dae21b6c37b3368ba2d3cc5847d47d8231d4ce /sys/vm | |
parent | c68617cf155ff030a33c997841409093543a3d6d (diff) | |
download | FreeBSD-src-21d101ccc523a786a6b5d18d7d784eae8017e9c5.zip FreeBSD-src-21d101ccc523a786a6b5d18d7d784eae8017e9c5.tar.gz |
When purging per-CPU UMA caches do not return empty buckets into the global
full bucket cache to not trigger assertion if allocation happen before that
global cache get purged.
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/uma_core.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 2b32a3e..62c2c52 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -701,25 +701,37 @@ static void cache_drain_safe_cpu(uma_zone_t zone) { uma_cache_t cache; + uma_bucket_t b1, b2; if (zone->uz_flags & UMA_ZFLAG_INTERNAL) return; + b1 = b2 = NULL; ZONE_LOCK(zone); critical_enter(); cache = &zone->uz_cpu[curcpu]; if (cache->uc_allocbucket) { - LIST_INSERT_HEAD(&zone->uz_buckets, cache->uc_allocbucket, - ub_link); + if (cache->uc_allocbucket->ub_cnt != 0) + LIST_INSERT_HEAD(&zone->uz_buckets, + cache->uc_allocbucket, ub_link); + else + b1 = cache->uc_allocbucket; cache->uc_allocbucket = NULL; } if (cache->uc_freebucket) { - LIST_INSERT_HEAD(&zone->uz_buckets, cache->uc_freebucket, - ub_link); + if (cache->uc_freebucket->ub_cnt != 0) + LIST_INSERT_HEAD(&zone->uz_buckets, + cache->uc_freebucket, ub_link); + else + b2 = cache->uc_freebucket; cache->uc_freebucket = NULL; } critical_exit(); ZONE_UNLOCK(zone); + if (b1) + bucket_free(zone, b1, NULL); + if (b2) + bucket_free(zone, b2, NULL); } /* |