Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'slab-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab

Pull slab fix from Vlastimil Babka:

- A stable fix for performance regression in tests that perform
kmem_cache_destroy() a lot, due to unnecessarily wide scope of
kvfree_rcu_barrier() (Harry Yoo)

* tag 'slab-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab:
mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction

+76 -41
+7
include/linux/slab.h
··· 1150 1150 rcu_barrier(); 1151 1151 } 1152 1152 1153 + static inline void kvfree_rcu_barrier_on_cache(struct kmem_cache *s) 1154 + { 1155 + rcu_barrier(); 1156 + } 1157 + 1153 1158 static inline void kfree_rcu_scheduler_running(void) { } 1154 1159 #else 1155 1160 void kvfree_rcu_barrier(void); 1161 + 1162 + void kvfree_rcu_barrier_on_cache(struct kmem_cache *s); 1156 1163 1157 1164 void kfree_rcu_scheduler_running(void); 1158 1165 #endif
+1
mm/slab.h
··· 422 422 423 423 bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj); 424 424 void flush_all_rcu_sheaves(void); 425 + void flush_rcu_sheaves_on_cache(struct kmem_cache *s); 425 426 426 427 #define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | \ 427 428 SLAB_CACHE_DMA32 | SLAB_PANIC | \
+37 -15
mm/slab_common.c
··· 492 492 return; 493 493 494 494 /* in-flight kfree_rcu()'s may include objects from our cache */ 495 - kvfree_rcu_barrier(); 495 + kvfree_rcu_barrier_on_cache(s); 496 496 497 497 if (IS_ENABLED(CONFIG_SLUB_RCU_DEBUG) && 498 498 (s->flags & SLAB_TYPESAFE_BY_RCU)) { ··· 2038 2038 } 2039 2039 EXPORT_SYMBOL_GPL(kvfree_call_rcu); 2040 2040 2041 - /** 2042 - * kvfree_rcu_barrier - Wait until all in-flight kvfree_rcu() complete. 2043 - * 2044 - * Note that a single argument of kvfree_rcu() call has a slow path that 2045 - * triggers synchronize_rcu() following by freeing a pointer. It is done 2046 - * before the return from the function. Therefore for any single-argument 2047 - * call that will result in a kfree() to a cache that is to be destroyed 2048 - * during module exit, it is developer's responsibility to ensure that all 2049 - * such calls have returned before the call to kmem_cache_destroy(). 2050 - */ 2051 - void kvfree_rcu_barrier(void) 2041 + static inline void __kvfree_rcu_barrier(void) 2052 2042 { 2053 2043 struct kfree_rcu_cpu_work *krwp; 2054 2044 struct kfree_rcu_cpu *krcp; 2055 2045 bool queued; 2056 2046 int i, cpu; 2057 - 2058 - flush_all_rcu_sheaves(); 2059 2047 2060 2048 /* 2061 2049 * Firstly we detach objects and queue them over an RCU-batch ··· 2106 2118 } 2107 2119 } 2108 2120 } 2121 + 2122 + /** 2123 + * kvfree_rcu_barrier - Wait until all in-flight kvfree_rcu() complete. 2124 + * 2125 + * Note that a single argument of kvfree_rcu() call has a slow path that 2126 + * triggers synchronize_rcu() following by freeing a pointer. It is done 2127 + * before the return from the function. Therefore for any single-argument 2128 + * call that will result in a kfree() to a cache that is to be destroyed 2129 + * during module exit, it is developer's responsibility to ensure that all 2130 + * such calls have returned before the call to kmem_cache_destroy(). 2131 + */ 2132 + void kvfree_rcu_barrier(void) 2133 + { 2134 + flush_all_rcu_sheaves(); 2135 + __kvfree_rcu_barrier(); 2136 + } 2109 2137 EXPORT_SYMBOL_GPL(kvfree_rcu_barrier); 2138 + 2139 + /** 2140 + * kvfree_rcu_barrier_on_cache - Wait for in-flight kvfree_rcu() calls on a 2141 + * specific slab cache. 2142 + * @s: slab cache to wait for 2143 + * 2144 + * See the description of kvfree_rcu_barrier() for details. 2145 + */ 2146 + void kvfree_rcu_barrier_on_cache(struct kmem_cache *s) 2147 + { 2148 + if (s->cpu_sheaves) 2149 + flush_rcu_sheaves_on_cache(s); 2150 + /* 2151 + * TODO: Introduce a version of __kvfree_rcu_barrier() that works 2152 + * on a specific slab cache. 2153 + */ 2154 + __kvfree_rcu_barrier(); 2155 + } 2156 + EXPORT_SYMBOL_GPL(kvfree_rcu_barrier_on_cache); 2110 2157 2111 2158 static unsigned long 2112 2159 kfree_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc) ··· 2238 2215 } 2239 2216 2240 2217 #endif /* CONFIG_KVFREE_RCU_BATCHED */ 2241 -
+31 -26
mm/slub.c
··· 4122 4122 4123 4123 4124 4124 /* needed for kvfree_rcu_barrier() */ 4125 - void flush_all_rcu_sheaves(void) 4125 + void flush_rcu_sheaves_on_cache(struct kmem_cache *s) 4126 4126 { 4127 4127 struct slub_flush_work *sfw; 4128 - struct kmem_cache *s; 4129 4128 unsigned int cpu; 4129 + 4130 + mutex_lock(&flush_lock); 4131 + 4132 + for_each_online_cpu(cpu) { 4133 + sfw = &per_cpu(slub_flush, cpu); 4134 + 4135 + /* 4136 + * we don't check if rcu_free sheaf exists - racing 4137 + * __kfree_rcu_sheaf() might have just removed it. 4138 + * by executing flush_rcu_sheaf() on the cpu we make 4139 + * sure the __kfree_rcu_sheaf() finished its call_rcu() 4140 + */ 4141 + 4142 + INIT_WORK(&sfw->work, flush_rcu_sheaf); 4143 + sfw->s = s; 4144 + queue_work_on(cpu, flushwq, &sfw->work); 4145 + } 4146 + 4147 + for_each_online_cpu(cpu) { 4148 + sfw = &per_cpu(slub_flush, cpu); 4149 + flush_work(&sfw->work); 4150 + } 4151 + 4152 + mutex_unlock(&flush_lock); 4153 + } 4154 + 4155 + void flush_all_rcu_sheaves(void) 4156 + { 4157 + struct kmem_cache *s; 4130 4158 4131 4159 cpus_read_lock(); 4132 4160 mutex_lock(&slab_mutex); ··· 4162 4134 list_for_each_entry(s, &slab_caches, list) { 4163 4135 if (!s->cpu_sheaves) 4164 4136 continue; 4165 - 4166 - mutex_lock(&flush_lock); 4167 - 4168 - for_each_online_cpu(cpu) { 4169 - sfw = &per_cpu(slub_flush, cpu); 4170 - 4171 - /* 4172 - * we don't check if rcu_free sheaf exists - racing 4173 - * __kfree_rcu_sheaf() might have just removed it. 4174 - * by executing flush_rcu_sheaf() on the cpu we make 4175 - * sure the __kfree_rcu_sheaf() finished its call_rcu() 4176 - */ 4177 - 4178 - INIT_WORK(&sfw->work, flush_rcu_sheaf); 4179 - sfw->s = s; 4180 - queue_work_on(cpu, flushwq, &sfw->work); 4181 - } 4182 - 4183 - for_each_online_cpu(cpu) { 4184 - sfw = &per_cpu(slub_flush, cpu); 4185 - flush_work(&sfw->work); 4186 - } 4187 - 4188 - mutex_unlock(&flush_lock); 4137 + flush_rcu_sheaves_on_cache(s); 4189 4138 } 4190 4139 4191 4140 mutex_unlock(&slab_mutex);