From 28135cc28c6b3b52668ae0411eae94811f4e1437 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 19 Sep 2010 09:43:09 -0700 Subject: [PATCH] kernel - Correct bug in malloc_type ks_memuse/ks_inuse management * The new kfree() was improperly adjust ks_memuse/ks_inuse for the wrong cpu, leading to MP races which could cause the memory statistics to go negative and trigger a panic. * When calculating loosememuse it is possible to race another cpu and come up with an incorrect value. The race itself is ok, loosememuse is not supposed to be 100% deterministic, but even so do not allow the value to underflow or we will wind up asserting. --- sys/kern/kern_slaballoc.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_slaballoc.c b/sys/kern/kern_slaballoc.c index 41ccd6e..a04b209 100644 --- a/sys/kern/kern_slaballoc.c +++ b/sys/kern/kern_slaballoc.c @@ -502,6 +502,8 @@ kmalloc(unsigned long size, struct malloc_type *type, int flags) for (i = ttl = 0; i < ncpus; ++i) ttl += type->ks_memuse[i]; type->ks_loosememuse = ttl; /* not MP synchronized */ + if ((ssize_t)ttl < 0) /* deal with occassional race */ + ttl = 0; if (ttl >= type->ks_limit) { if (flags & M_NULLOK) { logmemory(malloc_end, NULL, type, size, flags); @@ -1110,11 +1112,13 @@ kfree(void *ptr, struct malloc_type *type) /* * Making these adjustments now allow us to avoid passing (type) * to the remote cpu. Note that ks_inuse/ks_memuse is being - * adjusted on a different cpu, but it should all still sum up - * properly and cancel out. + * adjusted on OUR cpu, not the zone cpu, but it should all still + * sum up properly and cancel out. */ - --type->ks_inuse[z->z_Cpu]; - type->ks_memuse[z->z_Cpu] -= z->z_ChunkSize; + crit_enter(); + --type->ks_inuse[gd->gd_cpuid]; + type->ks_memuse[gd->gd_cpuid] -= z->z_ChunkSize; + crit_exit(); /* * WARNING! This code competes with other cpus. Once we -- 1.7.7.2