kernel - kmemstatistics list wasn't MPSAFE master
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 17 Jan 2017 22:52:22 +0000 (14:52 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 17 Jan 2017 22:52:22 +0000 (14:52 -0800)
* Put a spinlock around the kmemstatistics list.  This list is modified
  whenever a kmalloc area is created or destroyed, and this generally does
  not happen concurrently except with kernels run by expert hackers like
  us and get scared.

* ...Or if a machine is running synth and/or doing a lot of concurrent
  tmpfs mounts and unmounts.

Reported-by: swildner
sys/kern/kern_slaballoc.c

index 7e0de63..d0b3fff 100644 (file)
@@ -236,6 +236,9 @@ static int SlabFreeToTail;
 SYSCTL_INT(_kern, OID_AUTO, slab_freetotail, CTLFLAG_RW,
            &SlabFreeToTail, 0, "");
 
+static struct spinlock kmemstat_spin =
+                       SPINLOCK_INITIALIZER(&kmemstat_spin, "malinit");
+
 /*
  * Returns the kernel memory size limit for the purposes of initializing
  * various subsystem caches.  The smaller of available memory and the KVM
@@ -340,8 +343,10 @@ malloc_init(void *data)
     limsize = kmem_lim_size() * (1024 * 1024);
     type->ks_limit = limsize / 10;
 
+    spin_lock(&kmemstat_spin);
     type->ks_next = kmemstatistics;
     kmemstatistics = type;
+    spin_unlock(&kmemstat_spin);
 }
 
 void
@@ -379,6 +384,7 @@ malloc_uninit(void *data)
            ttl, type->ks_shortdesc, i);
     }
 #endif
+    spin_lock(&kmemstat_spin);
     if (type == kmemstatistics) {
        kmemstatistics = type->ks_next;
     } else {
@@ -391,6 +397,7 @@ malloc_uninit(void *data)
     }
     type->ks_next = NULL;
     type->ks_limit = 0;
+    spin_unlock(&kmemstat_spin);
 }
 
 /*