zfs/module/spl
Matthew Ahrens d4e04cc145 Missed wakeup when growing kmem cache
When growing the size of a (VMEM or KVMEM) kmem cache, spl_cache_grow()
always does taskq_dispatch(spl_cache_grow_work), and then waits for the
KMC_BIT_GROWING to be cleared by the taskq thread.

The taskq thread (spl_cache_grow_work()) does:
1. allocate new slab and add to list
2. wake_up_all(skc_waitq)
3. clear_bit(KMC_BIT_GROWING)

Therefore, the waiting thread can wake up before GROWING has been
cleared.  It will see that the growing has not yet completed, and go
back to sleep until it hits the 100ms timeout.

This can have an extreme performance impact on workloads that alloc/free
more than fits in the (statically-sized) magazines.  These workloads
allocate and free slabs with high frequency.

The problem can be observed with `funclatency spl_cache_grow`, which on
some workloads shows that 99.5% of the time it takes <64us to allocate
slabs, but we spend ~70% of our time in outliers, waiting for the 100ms
timeout.

The fix is to do `clear_bit(KMC_BIT_GROWING)` before
`wake_up_all(skc_waitq)`.

A future investigation should evaluate if we still actually need to
taskq_dispatch() at all, and if so on which kernel versions.

Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Wilson <gwilson@delphix.com>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #9989
2020-05-12 10:53:32 -07:00
..
Makefile.in Retire unused spl_{mutex,rwlock}_{init_fini} 2019-09-25 11:27:49 -07:00
README.md Update build system and packaging 2018-05-29 16:00:33 -07:00
THIRDPARTYLICENSE.gplv2 Prepare SPL repo to merge with ZFS repo 2018-05-29 14:51:39 -07:00
THIRDPARTYLICENSE.gplv2.descrip Prepare SPL repo to merge with ZFS repo 2018-05-29 14:51:39 -07:00
spl-atomic.c Fix cstyle warnings 2018-02-07 11:49:38 -08:00
spl-condvar.c Fix typos in module/ 2020-01-22 13:48:59 -08:00
spl-cred.c Fix cstyle warnings 2018-02-07 11:49:38 -08:00
spl-err.c Correct snprintf() size argument 2019-04-30 19:41:12 -07:00
spl-generic.c cppcheck: (error) Shifting signed 64-bit value by 63 bits 2020-01-22 13:49:06 -08:00
spl-kmem-cache.c Missed wakeup when growing kmem cache 2020-05-12 10:53:32 -07:00
spl-kmem.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-kobj.c Fix cstyle warnings 2018-02-07 11:49:38 -08:00
spl-kstat.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-proc.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-procfs-list.c Restrict kstats and print real pointers 2019-04-04 18:57:06 -07:00
spl-taskq.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-thread.c Minor style cleanup 2019-09-25 11:27:49 -07:00
spl-tsd.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-vmem.c cppcheck: (error) Uninitialized variable 2020-01-22 13:49:06 -08:00
spl-vnode.c Fix zfs-0.8.3 'make lint' warnings 2020-01-22 13:49:07 -08:00
spl-xdr.c Update build system and packaging 2018-05-29 16:00:33 -07:00
spl-zlib.c Drop KMC_NOEMERGENCY 2020-01-22 13:48:57 -08:00

README.md

The Solaris Porting Layer, SPL, is a Linux kernel module which provides a compatibility layer used by the ZFS on Linux project.

Installation

The latest version of the SPL is maintained as part of this repository. Only when building ZFS version 0.7.x or earlier must an external SPL release be used. These releases can be found at:

Release

The SPL is released under a GPLv2 license.
For more details see the NOTICE and THIRDPARTYLICENSE files; UCRL-CODE-235197