aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slob.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /mm/slob.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'mm/slob.c')
-rw-r--r--mm/slob.c259
1 files changed, 165 insertions, 94 deletions
diff --git a/mm/slob.c b/mm/slob.c
index a99fdf7a090..bf391818716 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -28,8 +28,9 @@
28 * from kmalloc are prepended with a 4-byte header with the kmalloc size. 28 * from kmalloc are prepended with a 4-byte header with the kmalloc size.
29 * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls 29 * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
30 * alloc_pages() directly, allocating compound pages so the page order 30 * alloc_pages() directly, allocating compound pages so the page order
31 * does not have to be separately tracked. 31 * does not have to be separately tracked, and also stores the exact
32 * These objects are detected in kfree() because PageSlab() 32 * allocation size in page->private so that it can be used to accurately
33 * provide ksize(). These objects are detected in kfree() because slob_page()
33 * is false for them. 34 * is false for them.
34 * 35 *
35 * SLAB is emulated on top of SLOB by simply calling constructors and 36 * SLAB is emulated on top of SLOB by simply calling constructors and
@@ -58,12 +59,11 @@
58 59
59#include <linux/kernel.h> 60#include <linux/kernel.h>
60#include <linux/slab.h> 61#include <linux/slab.h>
61
62#include <linux/mm.h> 62#include <linux/mm.h>
63#include <linux/swap.h> /* struct reclaim_state */ 63#include <linux/swap.h> /* struct reclaim_state */
64#include <linux/cache.h> 64#include <linux/cache.h>
65#include <linux/init.h> 65#include <linux/init.h>
66#include <linux/export.h> 66#include <linux/module.h>
67#include <linux/rcupdate.h> 67#include <linux/rcupdate.h>
68#include <linux/list.h> 68#include <linux/list.h>
69#include <linux/kmemleak.h> 69#include <linux/kmemleak.h>
@@ -72,7 +72,6 @@
72 72
73#include <linux/atomic.h> 73#include <linux/atomic.h>
74 74
75#include "slab.h"
76/* 75/*
77 * slob_block has a field 'units', which indicates size of block if +ve, 76 * slob_block has a field 'units', which indicates size of block if +ve,
78 * or offset of next block if -ve (in SLOB_UNITs). 77 * or offset of next block if -ve (in SLOB_UNITs).
@@ -93,6 +92,36 @@ struct slob_block {
93typedef struct slob_block slob_t; 92typedef struct slob_block slob_t;
94 93
95/* 94/*
95 * We use struct page fields to manage some slob allocation aspects,
96 * however to avoid the horrible mess in include/linux/mm_types.h, we'll
97 * just define our own struct page type variant here.
98 */
99struct slob_page {
100 union {
101 struct {
102 unsigned long flags; /* mandatory */
103 atomic_t _count; /* mandatory */
104 slobidx_t units; /* free units left in page */
105 unsigned long pad[2];
106 slob_t *free; /* first free slob_t in page */
107 struct list_head list; /* linked list of free pages */
108 };
109 struct page page;
110 };
111};
112static inline void struct_slob_page_wrong_size(void)
113{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); }
114
115/*
116 * free_slob_page: call before a slob_page is returned to the page allocator.
117 */
118static inline void free_slob_page(struct slob_page *sp)
119{
120 reset_page_mapcount(&sp->page);
121 sp->page.mapping = NULL;
122}
123
124/*
96 * All partially free slob pages go on these lists. 125 * All partially free slob pages go on these lists.
97 */ 126 */
98#define SLOB_BREAK1 256 127#define SLOB_BREAK1 256
@@ -102,27 +131,51 @@ static LIST_HEAD(free_slob_medium);
102static LIST_HEAD(free_slob_large); 131static LIST_HEAD(free_slob_large);
103 132
104/* 133/*
134 * is_slob_page: True for all slob pages (false for bigblock pages)
135 */
136static inline int is_slob_page(struct slob_page *sp)
137{
138 return PageSlab((struct page *)sp);
139}
140
141static inline void set_slob_page(struct slob_page *sp)
142{
143 __SetPageSlab((struct page *)sp);
144}
145
146static inline void clear_slob_page(struct slob_page *sp)
147{
148 __ClearPageSlab((struct page *)sp);
149}
150
151static inline struct slob_page *slob_page(const void *addr)
152{
153 return (struct slob_page *)virt_to_page(addr);
154}
155
156/*
105 * slob_page_free: true for pages on free_slob_pages list. 157 * slob_page_free: true for pages on free_slob_pages list.
106 */ 158 */
107static inline int slob_page_free(struct page *sp) 159static inline int slob_page_free(struct slob_page *sp)
108{ 160{
109 return PageSlobFree(sp); 161 return PageSlobFree((struct page *)sp);
110} 162}
111 163
112static void set_slob_page_free(struct page *sp, struct list_head *list) 164static void set_slob_page_free(struct slob_page *sp, struct list_head *list)
113{ 165{
114 list_add(&sp->list, list); 166 list_add(&sp->list, list);
115 __SetPageSlobFree(sp); 167 __SetPageSlobFree((struct page *)sp);
116} 168}
117 169
118static inline void clear_slob_page_free(struct page *sp) 170static inline void clear_slob_page_free(struct slob_page *sp)
119{ 171{
120 list_del(&sp->list); 172 list_del(&sp->list);
121 __ClearPageSlobFree(sp); 173 __ClearPageSlobFree((struct page *)sp);
122} 174}
123 175
124#define SLOB_UNIT sizeof(slob_t) 176#define SLOB_UNIT sizeof(slob_t)
125#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT) 177#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
178#define SLOB_ALIGN L1_CACHE_BYTES
126 179
127/* 180/*
128 * struct slob_rcu is inserted at the tail of allocated slob blocks, which 181 * struct slob_rcu is inserted at the tail of allocated slob blocks, which
@@ -192,7 +245,7 @@ static void *slob_new_pages(gfp_t gfp, int order, int node)
192 void *page; 245 void *page;
193 246
194#ifdef CONFIG_NUMA 247#ifdef CONFIG_NUMA
195 if (node != NUMA_NO_NODE) 248 if (node != -1)
196 page = alloc_pages_exact_node(node, gfp, order); 249 page = alloc_pages_exact_node(node, gfp, order);
197 else 250 else
198#endif 251#endif
@@ -214,12 +267,12 @@ static void slob_free_pages(void *b, int order)
214/* 267/*
215 * Allocate a slob block within a given slob_page sp. 268 * Allocate a slob block within a given slob_page sp.
216 */ 269 */
217static void *slob_page_alloc(struct page *sp, size_t size, int align) 270static void *slob_page_alloc(struct slob_page *sp, size_t size, int align)
218{ 271{
219 slob_t *prev, *cur, *aligned = NULL; 272 slob_t *prev, *cur, *aligned = NULL;
220 int delta = 0, units = SLOB_UNITS(size); 273 int delta = 0, units = SLOB_UNITS(size);
221 274
222 for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { 275 for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) {
223 slobidx_t avail = slob_units(cur); 276 slobidx_t avail = slob_units(cur);
224 277
225 if (align) { 278 if (align) {
@@ -243,12 +296,12 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
243 if (prev) 296 if (prev)
244 set_slob(prev, slob_units(prev), next); 297 set_slob(prev, slob_units(prev), next);
245 else 298 else
246 sp->freelist = next; 299 sp->free = next;
247 } else { /* fragment */ 300 } else { /* fragment */
248 if (prev) 301 if (prev)
249 set_slob(prev, slob_units(prev), cur + units); 302 set_slob(prev, slob_units(prev), cur + units);
250 else 303 else
251 sp->freelist = cur + units; 304 sp->free = cur + units;
252 set_slob(cur + units, avail - units, next); 305 set_slob(cur + units, avail - units, next);
253 } 306 }
254 307
@@ -267,7 +320,7 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
267 */ 320 */
268static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) 321static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
269{ 322{
270 struct page *sp; 323 struct slob_page *sp;
271 struct list_head *prev; 324 struct list_head *prev;
272 struct list_head *slob_list; 325 struct list_head *slob_list;
273 slob_t *b = NULL; 326 slob_t *b = NULL;
@@ -288,7 +341,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
288 * If there's a node specification, search for a partial 341 * If there's a node specification, search for a partial
289 * page with a matching node id in the freelist. 342 * page with a matching node id in the freelist.
290 */ 343 */
291 if (node != NUMA_NO_NODE && page_to_nid(sp) != node) 344 if (node != -1 && page_to_nid(&sp->page) != node)
292 continue; 345 continue;
293#endif 346#endif
294 /* Enough room on this page? */ 347 /* Enough room on this page? */
@@ -316,12 +369,12 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
316 b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); 369 b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node);
317 if (!b) 370 if (!b)
318 return NULL; 371 return NULL;
319 sp = virt_to_page(b); 372 sp = slob_page(b);
320 __SetPageSlab(sp); 373 set_slob_page(sp);
321 374
322 spin_lock_irqsave(&slob_lock, flags); 375 spin_lock_irqsave(&slob_lock, flags);
323 sp->units = SLOB_UNITS(PAGE_SIZE); 376 sp->units = SLOB_UNITS(PAGE_SIZE);
324 sp->freelist = b; 377 sp->free = b;
325 INIT_LIST_HEAD(&sp->list); 378 INIT_LIST_HEAD(&sp->list);
326 set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); 379 set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
327 set_slob_page_free(sp, slob_list); 380 set_slob_page_free(sp, slob_list);
@@ -339,7 +392,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
339 */ 392 */
340static void slob_free(void *block, int size) 393static void slob_free(void *block, int size)
341{ 394{
342 struct page *sp; 395 struct slob_page *sp;
343 slob_t *prev, *next, *b = (slob_t *)block; 396 slob_t *prev, *next, *b = (slob_t *)block;
344 slobidx_t units; 397 slobidx_t units;
345 unsigned long flags; 398 unsigned long flags;
@@ -349,7 +402,7 @@ static void slob_free(void *block, int size)
349 return; 402 return;
350 BUG_ON(!size); 403 BUG_ON(!size);
351 404
352 sp = virt_to_page(block); 405 sp = slob_page(block);
353 units = SLOB_UNITS(size); 406 units = SLOB_UNITS(size);
354 407
355 spin_lock_irqsave(&slob_lock, flags); 408 spin_lock_irqsave(&slob_lock, flags);
@@ -359,8 +412,8 @@ static void slob_free(void *block, int size)
359 if (slob_page_free(sp)) 412 if (slob_page_free(sp))
360 clear_slob_page_free(sp); 413 clear_slob_page_free(sp);
361 spin_unlock_irqrestore(&slob_lock, flags); 414 spin_unlock_irqrestore(&slob_lock, flags);
362 __ClearPageSlab(sp); 415 clear_slob_page(sp);
363 reset_page_mapcount(sp); 416 free_slob_page(sp);
364 slob_free_pages(b, 0); 417 slob_free_pages(b, 0);
365 return; 418 return;
366 } 419 }
@@ -368,7 +421,7 @@ static void slob_free(void *block, int size)
368 if (!slob_page_free(sp)) { 421 if (!slob_page_free(sp)) {
369 /* This slob page is about to become partially free. Easy! */ 422 /* This slob page is about to become partially free. Easy! */
370 sp->units = units; 423 sp->units = units;
371 sp->freelist = b; 424 sp->free = b;
372 set_slob(b, units, 425 set_slob(b, units,
373 (void *)((unsigned long)(b + 426 (void *)((unsigned long)(b +
374 SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); 427 SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
@@ -388,15 +441,15 @@ static void slob_free(void *block, int size)
388 */ 441 */
389 sp->units += units; 442 sp->units += units;
390 443
391 if (b < (slob_t *)sp->freelist) { 444 if (b < sp->free) {
392 if (b + units == sp->freelist) { 445 if (b + units == sp->free) {
393 units += slob_units(sp->freelist); 446 units += slob_units(sp->free);
394 sp->freelist = slob_next(sp->freelist); 447 sp->free = slob_next(sp->free);
395 } 448 }
396 set_slob(b, units, sp->freelist); 449 set_slob(b, units, sp->free);
397 sp->freelist = b; 450 sp->free = b;
398 } else { 451 } else {
399 prev = sp->freelist; 452 prev = sp->free;
400 next = slob_next(prev); 453 next = slob_next(prev);
401 while (b > next) { 454 while (b > next) {
402 prev = next; 455 prev = next;
@@ -423,11 +476,10 @@ out:
423 * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend. 476 * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
424 */ 477 */
425 478
426static __always_inline void * 479void *__kmalloc_node(size_t size, gfp_t gfp, int node)
427__do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
428{ 480{
429 unsigned int *m; 481 unsigned int *m;
430 int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); 482 int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
431 void *ret; 483 void *ret;
432 484
433 gfp &= gfp_allowed_mask; 485 gfp &= gfp_allowed_mask;
@@ -445,7 +497,7 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
445 *m = size; 497 *m = size;
446 ret = (void *)m + align; 498 ret = (void *)m + align;
447 499
448 trace_kmalloc_node(caller, ret, 500 trace_kmalloc_node(_RET_IP_, ret,
449 size, size + align, gfp, node); 501 size, size + align, gfp, node);
450 } else { 502 } else {
451 unsigned int order = get_order(size); 503 unsigned int order = get_order(size);
@@ -453,39 +505,24 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
453 if (likely(order)) 505 if (likely(order))
454 gfp |= __GFP_COMP; 506 gfp |= __GFP_COMP;
455 ret = slob_new_pages(gfp, order, node); 507 ret = slob_new_pages(gfp, order, node);
508 if (ret) {
509 struct page *page;
510 page = virt_to_page(ret);
511 page->private = size;
512 }
456 513
457 trace_kmalloc_node(caller, ret, 514 trace_kmalloc_node(_RET_IP_, ret,
458 size, PAGE_SIZE << order, gfp, node); 515 size, PAGE_SIZE << order, gfp, node);
459 } 516 }
460 517
461 kmemleak_alloc(ret, size, 1, gfp); 518 kmemleak_alloc(ret, size, 1, gfp);
462 return ret; 519 return ret;
463} 520}
464
465void *__kmalloc_node(size_t size, gfp_t gfp, int node)
466{
467 return __do_kmalloc_node(size, gfp, node, _RET_IP_);
468}
469EXPORT_SYMBOL(__kmalloc_node); 521EXPORT_SYMBOL(__kmalloc_node);
470 522
471#ifdef CONFIG_TRACING
472void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller)
473{
474 return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller);
475}
476
477#ifdef CONFIG_NUMA
478void *__kmalloc_node_track_caller(size_t size, gfp_t gfp,
479 int node, unsigned long caller)
480{
481 return __do_kmalloc_node(size, gfp, node, caller);
482}
483#endif
484#endif
485
486void kfree(const void *block) 523void kfree(const void *block)
487{ 524{
488 struct page *sp; 525 struct slob_page *sp;
489 526
490 trace_kfree(_RET_IP_, block); 527 trace_kfree(_RET_IP_, block);
491 528
@@ -493,46 +530,81 @@ void kfree(const void *block)
493 return; 530 return;
494 kmemleak_free(block); 531 kmemleak_free(block);
495 532
496 sp = virt_to_page(block); 533 sp = slob_page(block);
497 if (PageSlab(sp)) { 534 if (is_slob_page(sp)) {
498 int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); 535 int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
499 unsigned int *m = (unsigned int *)(block - align); 536 unsigned int *m = (unsigned int *)(block - align);
500 slob_free(m, *m + align); 537 slob_free(m, *m + align);
501 } else 538 } else
502 __free_pages(sp, compound_order(sp)); 539 put_page(&sp->page);
503} 540}
504EXPORT_SYMBOL(kfree); 541EXPORT_SYMBOL(kfree);
505 542
506/* can't use ksize for kmem_cache_alloc memory, only kmalloc */ 543/* can't use ksize for kmem_cache_alloc memory, only kmalloc */
507size_t ksize(const void *block) 544size_t ksize(const void *block)
508{ 545{
509 struct page *sp; 546 struct slob_page *sp;
510 int align;
511 unsigned int *m;
512 547
513 BUG_ON(!block); 548 BUG_ON(!block);
514 if (unlikely(block == ZERO_SIZE_PTR)) 549 if (unlikely(block == ZERO_SIZE_PTR))
515 return 0; 550 return 0;
516 551
517 sp = virt_to_page(block); 552 sp = slob_page(block);
518 if (unlikely(!PageSlab(sp))) 553 if (is_slob_page(sp)) {
519 return PAGE_SIZE << compound_order(sp); 554 int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
520 555 unsigned int *m = (unsigned int *)(block - align);
521 align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); 556 return SLOB_UNITS(*m) * SLOB_UNIT;
522 m = (unsigned int *)(block - align); 557 } else
523 return SLOB_UNITS(*m) * SLOB_UNIT; 558 return sp->page.private;
524} 559}
525EXPORT_SYMBOL(ksize); 560EXPORT_SYMBOL(ksize);
526 561
527int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) 562struct kmem_cache {
563 unsigned int size, align;
564 unsigned long flags;
565 const char *name;
566 void (*ctor)(void *);
567};
568
569struct kmem_cache *kmem_cache_create(const char *name, size_t size,
570 size_t align, unsigned long flags, void (*ctor)(void *))
528{ 571{
529 if (flags & SLAB_DESTROY_BY_RCU) { 572 struct kmem_cache *c;
530 /* leave room for rcu footer at the end of object */ 573
531 c->size += sizeof(struct slob_rcu); 574 c = slob_alloc(sizeof(struct kmem_cache),
532 } 575 GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1);
533 c->flags = flags; 576
534 return 0; 577 if (c) {
578 c->name = name;
579 c->size = size;
580 if (flags & SLAB_DESTROY_BY_RCU) {
581 /* leave room for rcu footer at the end of object */
582 c->size += sizeof(struct slob_rcu);
583 }
584 c->flags = flags;
585 c->ctor = ctor;
586 /* ignore alignment unless it's forced */
587 c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
588 if (c->align < ARCH_SLAB_MINALIGN)
589 c->align = ARCH_SLAB_MINALIGN;
590 if (c->align < align)
591 c->align = align;
592 } else if (flags & SLAB_PANIC)
593 panic("Cannot create slab cache %s\n", name);
594
595 kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
596 return c;
597}
598EXPORT_SYMBOL(kmem_cache_create);
599
600void kmem_cache_destroy(struct kmem_cache *c)
601{
602 kmemleak_free(c);
603 if (c->flags & SLAB_DESTROY_BY_RCU)
604 rcu_barrier();
605 slob_free(c, sizeof(struct kmem_cache));
535} 606}
607EXPORT_SYMBOL(kmem_cache_destroy);
536 608
537void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) 609void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
538{ 610{
@@ -544,12 +616,12 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
544 616
545 if (c->size < PAGE_SIZE) { 617 if (c->size < PAGE_SIZE) {
546 b = slob_alloc(c->size, flags, c->align, node); 618 b = slob_alloc(c->size, flags, c->align, node);
547 trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, 619 trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
548 SLOB_UNITS(c->size) * SLOB_UNIT, 620 SLOB_UNITS(c->size) * SLOB_UNIT,
549 flags, node); 621 flags, node);
550 } else { 622 } else {
551 b = slob_new_pages(flags, get_order(c->size), node); 623 b = slob_new_pages(flags, get_order(c->size), node);
552 trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, 624 trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
553 PAGE_SIZE << get_order(c->size), 625 PAGE_SIZE << get_order(c->size),
554 flags, node); 626 flags, node);
555 } 627 }
@@ -594,11 +666,11 @@ void kmem_cache_free(struct kmem_cache *c, void *b)
594} 666}
595EXPORT_SYMBOL(kmem_cache_free); 667EXPORT_SYMBOL(kmem_cache_free);
596 668
597int __kmem_cache_shutdown(struct kmem_cache *c) 669unsigned int kmem_cache_size(struct kmem_cache *c)
598{ 670{
599 /* No way to check for remaining objects */ 671 return c->size;
600 return 0;
601} 672}
673EXPORT_SYMBOL(kmem_cache_size);
602 674
603int kmem_cache_shrink(struct kmem_cache *d) 675int kmem_cache_shrink(struct kmem_cache *d)
604{ 676{
@@ -606,20 +678,19 @@ int kmem_cache_shrink(struct kmem_cache *d)
606} 678}
607EXPORT_SYMBOL(kmem_cache_shrink); 679EXPORT_SYMBOL(kmem_cache_shrink);
608 680
609struct kmem_cache kmem_cache_boot = { 681static unsigned int slob_ready __read_mostly;
610 .name = "kmem_cache", 682
611 .size = sizeof(struct kmem_cache), 683int slab_is_available(void)
612 .flags = SLAB_PANIC, 684{
613 .align = ARCH_KMALLOC_MINALIGN, 685 return slob_ready;
614}; 686}
615 687
616void __init kmem_cache_init(void) 688void __init kmem_cache_init(void)
617{ 689{
618 kmem_cache = &kmem_cache_boot; 690 slob_ready = 1;
619 slab_state = UP;
620} 691}
621 692
622void __init kmem_cache_init_late(void) 693void __init kmem_cache_init_late(void)
623{ 694{
624 slab_state = FULL; 695 /* Nothing to do */
625} 696}