aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Kennedy <richard@rsk.demon.co.uk>2010-10-21 05:29:19 -0400
committerPekka Enberg <penberg@kernel.org>2010-11-06 03:04:33 -0400
commit4a92379bdfb48680a5e6775dd53a586df7b6b0b1 (patch)
tree5ca6d2ace37b081a2b00d22014fcd27c6ad74c46
parent0d24db337e6d81c0c620ab65cc6947bd6553f742 (diff)
slub tracing: move trace calls out of always inlined functions to reduce kernel code size
Having the trace calls defined in the always inlined kmalloc functions in include/linux/slub_def.h causes a lot of code duplication as the trace functions get instantiated for each kamalloc call site. This can simply be removed by pushing the trace calls down into the functions in slub.c. On my x86_64 built this patch shrinks the code size of the kernel by approx 36K and also shrinks the code size of many modules -- too many to list here ;) size vmlinux (2.6.36) reports text data bss dec hex filename 5410611 743172 828928 6982711 6a8c37 vmlinux 5373738 744244 828928 6946910 6a005e vmlinux + patch The resulting kernel has had some testing & kmalloc trace still seems to work. This patch - moves trace_kmalloc out of the inlined kmalloc() and pushes it down into kmem_cache_alloc_trace() so this it only get instantiated once. - rename kmem_cache_alloc_notrace() to kmem_cache_alloc_trace() to indicate that now is does have tracing. (maybe this would better being called something like kmalloc_kmem_cache ?) - adds a new function kmalloc_order() to handle allocation and tracing of large allocations of page order. - removes tracing from the inlined kmalloc_large() replacing them with a call to kmalloc_order(); - move tracing out of inlined kmalloc_node() and pushing it down into kmem_cache_alloc_node_trace - rename kmem_cache_alloc_node_notrace() to kmem_cache_alloc_node_trace() - removes the include of trace/events/kmem.h from slub_def.h. v2 - keep kmalloc_order_trace inline when !CONFIG_TRACE Signed-off-by: Richard Kennedy <richard@rsk.demon.co.uk> Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--include/linux/slub_def.h55
-rw-r--r--mm/slub.c30
2 files changed, 49 insertions, 36 deletions
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index e4f5ed180b9b..8b6e8ae5d5ca 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -10,9 +10,8 @@
10#include <linux/gfp.h> 10#include <linux/gfp.h>
11#include <linux/workqueue.h> 11#include <linux/workqueue.h>
12#include <linux/kobject.h> 12#include <linux/kobject.h>
13#include <linux/kmemleak.h>
14 13
15#include <trace/events/kmem.h> 14#include <linux/kmemleak.h>
16 15
17enum stat_item { 16enum stat_item {
18 ALLOC_FASTPATH, /* Allocation from cpu slab */ 17 ALLOC_FASTPATH, /* Allocation from cpu slab */
@@ -216,31 +215,40 @@ static __always_inline struct kmem_cache *kmalloc_slab(size_t size)
216void *kmem_cache_alloc(struct kmem_cache *, gfp_t); 215void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
217void *__kmalloc(size_t size, gfp_t flags); 216void *__kmalloc(size_t size, gfp_t flags);
218 217
218static __always_inline void *
219kmalloc_order(size_t size, gfp_t flags, unsigned int order)
220{
221 void *ret = (void *) __get_free_pages(flags | __GFP_COMP, order);
222 kmemleak_alloc(ret, size, 1, flags);
223 return ret;
224}
225
219#ifdef CONFIG_TRACING 226#ifdef CONFIG_TRACING
220extern void *kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags); 227extern void *
228kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size);
229extern void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order);
221#else 230#else
222static __always_inline void * 231static __always_inline void *
223kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags) 232kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
224{ 233{
225 return kmem_cache_alloc(s, gfpflags); 234 return kmem_cache_alloc(s, gfpflags);
226} 235}
236
237static __always_inline void *
238kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
239{
240 return kmalloc_order(size, flags, order);
241}
227#endif 242#endif
228 243
229static __always_inline void *kmalloc_large(size_t size, gfp_t flags) 244static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
230{ 245{
231 unsigned int order = get_order(size); 246 unsigned int order = get_order(size);
232 void *ret = (void *) __get_free_pages(flags | __GFP_COMP, order); 247 return kmalloc_order_trace(size, flags, order);
233
234 kmemleak_alloc(ret, size, 1, flags);
235 trace_kmalloc(_THIS_IP_, ret, size, PAGE_SIZE << order, flags);
236
237 return ret;
238} 248}
239 249
240static __always_inline void *kmalloc(size_t size, gfp_t flags) 250static __always_inline void *kmalloc(size_t size, gfp_t flags)
241{ 251{
242 void *ret;
243
244 if (__builtin_constant_p(size)) { 252 if (__builtin_constant_p(size)) {
245 if (size > SLUB_MAX_SIZE) 253 if (size > SLUB_MAX_SIZE)
246 return kmalloc_large(size, flags); 254 return kmalloc_large(size, flags);
@@ -251,11 +259,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
251 if (!s) 259 if (!s)
252 return ZERO_SIZE_PTR; 260 return ZERO_SIZE_PTR;
253 261
254 ret = kmem_cache_alloc_notrace(s, flags); 262 return kmem_cache_alloc_trace(s, flags, size);
255
256 trace_kmalloc(_THIS_IP_, ret, size, s->size, flags);
257
258 return ret;
259 } 263 }
260 } 264 }
261 return __kmalloc(size, flags); 265 return __kmalloc(size, flags);
@@ -266,14 +270,14 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node);
266void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); 270void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
267 271
268#ifdef CONFIG_TRACING 272#ifdef CONFIG_TRACING
269extern void *kmem_cache_alloc_node_notrace(struct kmem_cache *s, 273extern void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
270 gfp_t gfpflags, 274 gfp_t gfpflags,
271 int node); 275 int node, size_t size);
272#else 276#else
273static __always_inline void * 277static __always_inline void *
274kmem_cache_alloc_node_notrace(struct kmem_cache *s, 278kmem_cache_alloc_node_trace(struct kmem_cache *s,
275 gfp_t gfpflags, 279 gfp_t gfpflags,
276 int node) 280 int node, size_t size)
277{ 281{
278 return kmem_cache_alloc_node(s, gfpflags, node); 282 return kmem_cache_alloc_node(s, gfpflags, node);
279} 283}
@@ -281,8 +285,6 @@ kmem_cache_alloc_node_notrace(struct kmem_cache *s,
281 285
282static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) 286static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
283{ 287{
284 void *ret;
285
286 if (__builtin_constant_p(size) && 288 if (__builtin_constant_p(size) &&
287 size <= SLUB_MAX_SIZE && !(flags & SLUB_DMA)) { 289 size <= SLUB_MAX_SIZE && !(flags & SLUB_DMA)) {
288 struct kmem_cache *s = kmalloc_slab(size); 290 struct kmem_cache *s = kmalloc_slab(size);
@@ -290,12 +292,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
290 if (!s) 292 if (!s)
291 return ZERO_SIZE_PTR; 293 return ZERO_SIZE_PTR;
292 294
293 ret = kmem_cache_alloc_node_notrace(s, flags, node); 295 return kmem_cache_alloc_node_trace(s, flags, node, size);
294
295 trace_kmalloc_node(_THIS_IP_, ret,
296 size, s->size, flags, node);
297
298 return ret;
299 } 296 }
300 return __kmalloc_node(size, flags, node); 297 return __kmalloc_node(size, flags, node);
301} 298}
diff --git a/mm/slub.c b/mm/slub.c
index 8fd5401bb071..7e657aa19475 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -28,6 +28,8 @@
28#include <linux/math64.h> 28#include <linux/math64.h>
29#include <linux/fault-inject.h> 29#include <linux/fault-inject.h>
30 30
31#include <trace/events/kmem.h>
32
31/* 33/*
32 * Lock order: 34 * Lock order:
33 * 1. slab_lock(page) 35 * 1. slab_lock(page)
@@ -1774,11 +1776,21 @@ void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
1774EXPORT_SYMBOL(kmem_cache_alloc); 1776EXPORT_SYMBOL(kmem_cache_alloc);
1775 1777
1776#ifdef CONFIG_TRACING 1778#ifdef CONFIG_TRACING
1777void *kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags) 1779void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
1780{
1781 void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_);
1782 trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags);
1783 return ret;
1784}
1785EXPORT_SYMBOL(kmem_cache_alloc_trace);
1786
1787void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
1778{ 1788{
1779 return slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); 1789 void *ret = kmalloc_order(size, flags, order);
1790 trace_kmalloc(_RET_IP_, ret, size, PAGE_SIZE << order, flags);
1791 return ret;
1780} 1792}
1781EXPORT_SYMBOL(kmem_cache_alloc_notrace); 1793EXPORT_SYMBOL(kmalloc_order_trace);
1782#endif 1794#endif
1783 1795
1784#ifdef CONFIG_NUMA 1796#ifdef CONFIG_NUMA
@@ -1794,13 +1806,17 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
1794EXPORT_SYMBOL(kmem_cache_alloc_node); 1806EXPORT_SYMBOL(kmem_cache_alloc_node);
1795 1807
1796#ifdef CONFIG_TRACING 1808#ifdef CONFIG_TRACING
1797void *kmem_cache_alloc_node_notrace(struct kmem_cache *s, 1809void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
1798 gfp_t gfpflags, 1810 gfp_t gfpflags,
1799 int node) 1811 int node, size_t size)
1800{ 1812{
1801 return slab_alloc(s, gfpflags, node, _RET_IP_); 1813 void *ret = slab_alloc(s, gfpflags, node, _RET_IP_);
1814
1815 trace_kmalloc_node(_RET_IP_, ret,
1816 size, s->size, gfpflags, node);
1817 return ret;
1802} 1818}
1803EXPORT_SYMBOL(kmem_cache_alloc_node_notrace); 1819EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
1804#endif 1820#endif
1805#endif 1821#endif
1806 1822