blob: 0ea5b38137e17572f42a6b1a1502a216879a66bf [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * SLOB Allocator: Simple List Of Blocks
3 *
4 * Matt Mackall <mpm@selenic.com> 12/30/03
5 *
6 * NUMA support by Paul Mundt, 2007.
7 *
8 * How SLOB works:
9 *
10 * The core of SLOB is a traditional K&R style heap allocator, with
11 * support for returning aligned objects. The granularity of this
12 * allocator is as little as 2 bytes, however typically most architectures
13 * will require 4 bytes on 32-bit and 8 bytes on 64-bit.
14 *
15 * The slob heap is a set of linked list of pages from alloc_pages(),
16 * and within each page, there is a singly-linked list of free blocks
17 * (slob_t). The heap is grown on demand. To reduce fragmentation,
18 * heap pages are segregated into three lists, with objects less than
19 * 256 bytes, objects less than 1024 bytes, and all other objects.
20 *
21 * Allocation from heap involves first searching for a page with
22 * sufficient free blocks (using a next-fit-like approach) followed by
23 * a first-fit scan of the page. Deallocation inserts objects back
24 * into the free list in address order, so this is effectively an
25 * address-ordered first fit.
26 *
27 * Above this is an implementation of kmalloc/kfree. Blocks returned
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
30 * alloc_pages() directly, allocating compound pages so the page order
31 * does not have to be separately tracked, and also stores the exact
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()
34 * is false for them.
35 *
36 * SLAB is emulated on top of SLOB by simply calling constructors and
37 * destructors for every SLAB allocation. Objects are returned with the
38 * 4-byte alignment unless the SLAB_HWCACHE_ALIGN flag is set, in which
39 * case the low-level allocator will fragment blocks to create the proper
40 * alignment. Again, objects of page-size or greater are allocated by
41 * calling alloc_pages(). As SLAB objects know their size, no separate
42 * size bookkeeping is necessary and there is essentially no allocation
43 * space overhead, and compound pages aren't needed for multi-page
44 * allocations.
45 *
46 * NUMA support in SLOB is fairly simplistic, pushing most of the real
47 * logic down to the page allocator, and simply doing the node accounting
48 * on the upper levels. In the event that a node id is explicitly
49 * provided, alloc_pages_exact_node() with the specified node id is used
50 * instead. The common case (or when the node id isn't explicitly provided)
51 * will default to the current node, as per numa_node_id().
52 *
53 * Node aware pages are still inserted in to the global freelist, and
54 * these are scanned for by matching against the node id encoded in the
55 * page flags. As a result, block allocations that can be satisfied from
56 * the freelist will only be done so on pages residing on the same node,
57 * in order to prevent random node placement.
58 */
59
60#include <linux/kernel.h>
61#include <linux/slab.h>
62#include <linux/mm.h>
63#include <linux/swap.h> /* struct reclaim_state */
64#include <linux/cache.h>
65#include <linux/init.h>
66#include <linux/export.h>
67#include <linux/rcupdate.h>
68#include <linux/list.h>
69#include <linux/kmemleak.h>
70
71#include <trace/events/kmem.h>
72
73#include <linux/atomic.h>
74
75#ifdef CONFIG_KMALLOC_TRACKER
76#include <linux/mem_tracker_def.h>
77#endif
78
79#ifdef CONFIG_DEBUG_SLOB_MARK_HEAD
80
81#define BYTES_PER_RECORD (sizeof(void *))
82#define RECORD_MAGIC 0xdeaddead
83#define RECORD_COUNT 4
84
85static void **dbg_userrecord(void *mem,int index)
86{
87 return (void **)(mem + index * BYTES_PER_RECORD);
88}
89
90static void **dbg_userhead(void *mem)
91{
92 return (void **)(mem - RECORD_COUNT * BYTES_PER_RECORD);
93}
94#endif
95
96/*
97 * slob_block has a field 'units', which indicates size of block if +ve,
98 * or offset of next block if -ve (in SLOB_UNITs).
99 *
100 * Free blocks of size 1 unit simply contain the offset of the next block.
101 * Those with larger size contain their size in the first SLOB_UNIT of
102 * memory, and the offset of the next free block in the second SLOB_UNIT.
103 */
104#if PAGE_SIZE <= (32767 * 2)
105typedef s16 slobidx_t;
106#else
107typedef s32 slobidx_t;
108#endif
109
110struct slob_block {
111 slobidx_t units;
112};
113typedef struct slob_block slob_t;
114
115/*
116 * We use struct page fields to manage some slob allocation aspects,
117 * however to avoid the horrible mess in include/linux/mm_types.h, we'll
118 * just define our own struct page type variant here.
119 */
120struct slob_page {
121 union {
122 struct {
123 unsigned long flags; /* mandatory */
124 unsigned long index; /* mandatory */
125 slobidx_t units; /* free units left in page */
126 unsigned long pad[2];
127 slob_t *free; /* first free slob_t in page */
128 struct list_head list; /* linked list of free pages */
129 };
130 struct page page;
131 };
132};
133
134unsigned int g_slob_kmalloc_pages;
135unsigned int g_slob_kmem_cache_pages;
136raw_spinlock_t g_slob_kmalloc_spin_lock = (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER (g_slob_kmalloc_spin_lock);
137raw_spinlock_t g_slob_kmem_cache_spin_lock = (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER (g_slob_kmem_cache_spin_lock);
138
139static inline void struct_slob_page_wrong_size(void)
140{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); }
141
142/*
143 * free_slob_page: call before a slob_page is returned to the page allocator.
144 */
145static inline void free_slob_page(struct slob_page *sp)
146{
147 reset_page_mapcount(&sp->page);
148 sp->page.mapping = NULL;
149}
150
151/*
152 * All partially free slob pages go on these lists.
153 */
154#define SLOB_BREAK1 256
155#define SLOB_BREAK2 1024
156static LIST_HEAD(free_slob_small);
157static LIST_HEAD(free_slob_medium);
158static LIST_HEAD(free_slob_large);
159
160/*
161 * is_slob_page: True for all slob pages (false for bigblock pages)
162 */
163static inline int is_slob_page(struct slob_page *sp)
164{
165 return PageSlab((struct page *)sp);
166}
167
168static inline void set_slob_page(struct slob_page *sp)
169{
170 __SetPageSlab((struct page *)sp);
171}
172
173static inline void clear_slob_page(struct slob_page *sp)
174{
175 __ClearPageSlab((struct page *)sp);
176}
177
178static inline struct slob_page *slob_page(const void *addr)
179{
180 return (struct slob_page *)virt_to_page(addr);
181}
182
183/*
184 * slob_page_free: true for pages on free_slob_pages list.
185 */
186static inline int slob_page_free(struct slob_page *sp)
187{
188 return PageSlobFree((struct page *)sp);
189}
190
191static void set_slob_page_free(struct slob_page *sp, struct list_head *list)
192{
193 list_add(&sp->list, list);
194 __SetPageSlobFree((struct page *)sp);
195}
196
197static inline void clear_slob_page_free(struct slob_page *sp)
198{
199 list_del(&sp->list);
200 __ClearPageSlobFree((struct page *)sp);
201}
202
203#ifdef CONFIG_SLOB_OPT
204#define SLOB_CHUNK_SHIFT (L1_CACHE_SHIFT)
205#define SLOB_CHUNK_SIZE (1 << (SLOB_CHUNK_SHIFT))
206#define SLOB_LIST_NUM (PAGE_SIZE >> (SLOB_CHUNK_SHIFT))
207#define SLOB_LIST_LIMIT (0)
208
209
210struct slob_item_info
211{
212 struct list_head slob_list;
213 int count;
214};
215struct slob_item_info slob_sizes[SLOB_LIST_NUM];
216#else
217#define SLOB_CHUNK_SHIFT (L1_CACHE_SHIFT)
218#define SLOB_CHUNK_SIZE (1 << (SLOB_CHUNK_SHIFT))
219#define SLOB_LIST_NUM ((PAGE_SIZE >> (SLOB_CHUNK_SHIFT)))
220struct list_head slob_sizes[SLOB_LIST_NUM];
221#endif
222static inline void set_slob_page_list_index(struct slob_page *sp, unsigned long index)
223{
224 sp->index = index;
225}
226#ifdef CONFIG_SLOB_OPT
227static inline struct slob_item_info *get_slob_page_list_head(struct slob_page *sp)
228{
229 return &slob_sizes[sp->index];
230}
231#else
232static inline struct list_head *get_slob_page_list_head(struct slob_page *sp)
233{
234 return &slob_sizes[sp->index];
235}
236#endif
237static inline void clear_slob_page_list_index(struct slob_page *sp)
238{
239 sp->index = 0;
240}
241
242#define SLOB_UNIT sizeof(slob_t)
243#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
244#define SLOB_ALIGN L1_CACHE_BYTES
245
246/*
247 * struct slob_rcu is inserted at the tail of allocated slob blocks, which
248 * were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free
249 * the block using call_rcu.
250 */
251struct slob_rcu {
252 struct rcu_head head;
253 int size;
254};
255
256/*
257 * slob_lock protects all slob allocator structures.
258 */
259static DEFINE_SPINLOCK(slob_lock);
260
261/*
262 * Encode the given size and next info into a free slob block s.
263 */
264static void set_slob(slob_t *s, slobidx_t size, slob_t *next)
265{
266 slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
267 slobidx_t offset = next - base;
268
269 if (size > 1) {
270 s[0].units = size;
271 s[1].units = offset;
272 } else
273 s[0].units = -offset;
274}
275
276/*
277 * Return the size of a slob block.
278 */
279static slobidx_t slob_units(slob_t *s)
280{
281 if (s->units > 0)
282 return s->units;
283 return 1;
284}
285
286/*
287 * Return the next free slob block pointer after this one.
288 */
289static slob_t *slob_next(slob_t *s)
290{
291 slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
292 slobidx_t next;
293
294 if (s[0].units < 0)
295 next = -s[0].units;
296 else
297 next = s[1].units;
298 return base+next;
299}
300
301/*
302 * Returns true if s is the last free block in its page.
303 */
304static int slob_last(slob_t *s)
305{
306 return !((unsigned long)slob_next(s) & ~PAGE_MASK);
307}
308
309static void *slob_new_pages(gfp_t gfp, int order, int node)
310{
311 void *page;
312
313#ifdef CONFIG_NUMA
314 if (node != -1)
315 page = alloc_pages_exact_node(node, gfp, order);
316 else
317#endif
318 page = alloc_pages(gfp, order);
319
320 if (!page)
321 return NULL;
322
323 return page_address(page);
324}
325
326static void slob_free_pages(void *b, int order)
327{
328 if (current->reclaim_state)
329 current->reclaim_state->reclaimed_slab += 1 << order;
330 free_pages((unsigned long)b, order);
331}
332
333/*
334 * Allocate a slob block within a given slob_page sp.
335 */
336static void *slob_page_alloc(struct slob_page *sp, size_t size, int align)
337{
338 slob_t *prev, *cur, *aligned = NULL;
339 int delta = 0, units = SLOB_UNITS(size);
340
341 for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) {
342 slobidx_t avail = slob_units(cur);
343
344 if (align) {
345 aligned = (slob_t *)ALIGN((unsigned long)cur, align);
346 delta = aligned - cur;
347 }
348 if (avail >= units + delta) { /* room enough? */
349 slob_t *next;
350
351 if (delta) { /* need to fragment head to align? */
352 next = slob_next(cur);
353 set_slob(aligned, avail - delta, next);
354 set_slob(cur, delta, aligned);
355 prev = cur;
356 cur = aligned;
357 avail = slob_units(cur);
358 }
359
360 next = slob_next(cur);
361 if (avail == units) { /* exact fit? unlink. */
362 if (prev)
363 set_slob(prev, slob_units(prev), next);
364 else
365 sp->free = next;
366 } else { /* fragment */
367 if (prev)
368 set_slob(prev, slob_units(prev), cur + units);
369 else
370 sp->free = cur + units;
371 set_slob(cur + units, avail - units, next);
372 }
373
374 sp->units -= units;
375 if (!sp->units
376#ifdef CONFIG_SLOB_OPT
377 && size != PAGE_SIZE
378#endif
379 )
380 clear_slob_page_free(sp);
381 return cur;
382 }
383 if (slob_last(cur))
384 return NULL;
385 }
386}
387
388void slob_sizes_init(void)
389{
390 int i;
391
392 for (i = 0; i < SLOB_LIST_NUM; i++)
393 {
394#ifdef CONFIG_SLOB_OPT
395 INIT_LIST_HEAD(&slob_sizes[i].slob_list);
396#else
397 INIT_LIST_HEAD(&slob_sizes[i]);
398#endif
399 }
400
401}
402
403static struct list_head *find_general_slob_list(size_t size, size_t *general_size, unsigned long *index)
404{
405 int slob_index = 0;
406
407 if (size & (SLOB_CHUNK_SIZE - 1))
408 slob_index = size >> SLOB_CHUNK_SHIFT;
409 else
410 slob_index = (size >> SLOB_CHUNK_SHIFT) - 1;
411
412 *general_size = (slob_index + 1) << SLOB_CHUNK_SHIFT;
413 *index = slob_index;
414 return &(slob_sizes[slob_index]);
415}
416
417/*
418 * slob_alloc: entry point into the slob allocator.
419 */
420static void *slob_alloc_general(size_t size, gfp_t gfp, int align, int node)
421{
422 unsigned long index;
423 size_t general_size;
424 struct slob_page *sp;
425 struct list_head *prev;
426#ifdef CONFIG_SLOB_OPT
427 struct slob_item_info *slob_list;
428#else
429 struct list_head *slob_list;
430#endif
431 slob_t *b = NULL;
432 unsigned long flags;
433
434 if (size < PAGE_SIZE)
435 slob_list = find_general_slob_list(size, &general_size, &index);
436 else
437 panic("slob alloc error");
438
439 size = general_size;
440 spin_lock_irqsave(&slob_lock, flags);
441 /* Iterate through each partially free page, try to find room */
442#ifdef CONFIG_SLOB_OPT
443 if (size ==PAGE_SIZE && slob_list->count ==0 )
444 goto alloc_out;
445
446 list_for_each_entry(sp, &(slob_list->slob_list), list) {
447#else
448 list_for_each_entry(sp, slob_list, list) {
449#endif
450#ifdef CONFIG_NUMA
451 /*
452 * If there's a node specification, search for a partial
453 * page with a matching node id in the freelist.
454 */
455 if (node != -1 && page_to_nid(&sp->page) != node)
456 continue;
457#endif
458 /* Enough room on this page? */
459 if (sp->units < SLOB_UNITS(size))
460 continue;
461
462#ifdef CONFIG_SLOB_OPT
463 /*if it is a free block,count--*/
464 if (sp->units == SLOB_UNITS(PAGE_SIZE))
465 slob_list->count--;
466#endif
467 /* Attempt to alloc */
468 prev = sp->list.prev;
469 b = slob_page_alloc(sp, size, align);
470 if (!b)
471 continue;
472
473 /* Improve fragment distribution and reduce our average
474 * search time by starting our next search here. (see
475 * Knuth vol 1, sec 2.5, pg 449) */
476#ifdef CONFIG_SLOB_OPT
477 if (prev != slob_list->slob_list.prev &&
478 slob_list->slob_list.next != prev->next)
479 list_move_tail(&(slob_list->slob_list), prev->next);
480#else
481 if (prev != slob_list->prev &&
482 slob_list->next != prev->next)
483 list_move_tail(slob_list, prev->next);
484#endif
485 break;
486 }
487alloc_out:
488 spin_unlock_irqrestore(&slob_lock, flags);
489
490 /* Not enough space: must allocate a new page */
491 if (!b) {
492 b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node);
493 if (!b)
494 return NULL;
495 raw_spin_lock_irqsave(&g_slob_kmalloc_spin_lock, flags);
496 g_slob_kmalloc_pages++;
497 raw_spin_unlock_irqrestore(&g_slob_kmalloc_spin_lock, flags);
498 sp = slob_page(b);
499 set_slob_page(sp);
500
501 spin_lock_irqsave(&slob_lock, flags);
502 sp->units = SLOB_UNITS(PAGE_SIZE);
503 sp->free = b;
504 INIT_LIST_HEAD(&sp->list);
505 set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
506#ifdef CONFIG_SLOB_OPT
507 set_slob_page_free(sp, &(slob_list->slob_list));
508#else
509 set_slob_page_free(sp, slob_list);
510#endif
511 b = slob_page_alloc(sp, size, align);
512 BUG_ON(!b);
513 set_slob_page_list_index(sp, index);
514 spin_unlock_irqrestore(&slob_lock, flags);
515 }
516 if (unlikely((gfp & __GFP_ZERO) && b))
517 memset(b, 0, size);
518 return b;
519}
520
521static size_t slob_find_general_size(struct slob_page *sp)
522{
523 return (sp->index + 1) << SLOB_CHUNK_SHIFT;
524}
525
526/*
527 * slob_free: entry point into the slob allocator.
528 */
529static void slob_free_general(const void *block, struct slob_page *sp)
530{
531 size_t size;
532 slob_t *prev, *next, *b = (slob_t *)block;
533 slobidx_t units;
534 unsigned long flags;
535#ifdef CONFIG_SLOB_OPT
536 struct slob_item_info *slob_list;
537#else
538 struct list_head *slob_list;
539#endif
540 if (unlikely(ZERO_OR_NULL_PTR(block)))
541 return;
542
543 slob_list = get_slob_page_list_head(sp);
544 size = slob_find_general_size(sp);
545
546 units = SLOB_UNITS(size);
547
548 spin_lock_irqsave(&slob_lock, flags);
549
550 if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
551#ifdef CONFIG_SLOB_OPT
552 if (slob_list->count < SLOB_LIST_LIMIT && slob_page_free(sp)){
553 sp->units += units;
554 sp->free = page_address((struct page *)sp);
555 set_slob(sp->free, SLOB_UNITS(PAGE_SIZE), sp->free + SLOB_UNITS(PAGE_SIZE));
556 slob_list->count++;
557 // if (slob_list->slob_list.next != &sp->list)
558 // list_move(&sp->list, &(slob_list->slob_list));
559
560 spin_unlock_irqrestore(&slob_lock, flags);
561 return;
562 }
563#endif
564 /* Go directly to page allocator. Do not pass slob allocator */
565 if (slob_page_free(sp))
566 clear_slob_page_free(sp);
567 spin_unlock_irqrestore(&slob_lock, flags);
568 clear_slob_page(sp);
569 clear_slob_page_list_index(sp);
570 free_slob_page(sp);
571 slob_free_pages(b, 0);
572 raw_spin_lock_irqsave(&g_slob_kmalloc_spin_lock, flags);
573 g_slob_kmalloc_pages--;
574 raw_spin_unlock_irqrestore(&g_slob_kmalloc_spin_lock, flags);
575 return;
576 }
577
578 if (!slob_page_free(sp)) {
579 /* This slob page is about to become partially free. Easy! */
580 sp->units = units;
581 sp->free = b;
582 set_slob(b, units,
583 (void *)((unsigned long)(b +
584 SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
585#ifdef CONFIG_SLOB_OPT
586 set_slob_page_free(sp, &(slob_list->slob_list));
587#else
588 set_slob_page_free(sp, slob_list);
589#endif
590 goto out;
591 }
592
593 /*
594 * Otherwise the page is already partially free, so find reinsertion
595 * point.
596 */
597 sp->units += units;
598
599 if (b < sp->free) {
600 if (b + units == sp->free) {
601 units += slob_units(sp->free);
602 sp->free = slob_next(sp->free);
603 }
604 set_slob(b, units, sp->free);
605 sp->free = b;
606 } else {
607 prev = sp->free;
608 next = slob_next(prev);
609 while (b > next) {
610 prev = next;
611 next = slob_next(prev);
612 }
613
614 if (unlikely((b == prev) || (b == next)))
615 panic("slob: double free error!\n");
616
617 if (!slob_last(prev) && b + units == next) {
618 units += slob_units(next);
619 set_slob(b, units, slob_next(next));
620 } else
621 set_slob(b, units, next);
622
623 if (prev + slob_units(prev) == b) {
624 units = slob_units(b) + slob_units(prev);
625 set_slob(prev, units, slob_next(b));
626 } else
627 set_slob(prev, slob_units(prev), b);
628 }
629#ifdef CONFIG_SLOB_OPT
630 if (slob_list->slob_list.next != &sp->list)
631 list_move(&sp->list, &(slob_list->slob_list));
632#else
633 if (slob_list->next != &sp->list)
634 list_move(&sp->list, slob_list);
635#endif
636out:
637 spin_unlock_irqrestore(&slob_lock, flags);
638}
639
640static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
641{
642 struct slob_page *sp;
643 struct list_head *prev;
644 struct list_head *slob_list;
645 slob_t *b = NULL;
646 unsigned long flags;
647
648 if (size < SLOB_BREAK1)
649 slob_list = &free_slob_small;
650 else if (size < SLOB_BREAK2)
651 slob_list = &free_slob_medium;
652 else
653 slob_list = &free_slob_large;
654
655 spin_lock_irqsave(&slob_lock, flags);
656 /* Iterate through each partially free page, try to find room */
657 list_for_each_entry(sp, slob_list, list) {
658#ifdef CONFIG_NUMA
659 /*
660 * If there's a node specification, search for a partial
661 * page with a matching node id in the freelist.
662 */
663 if (node != -1 && page_to_nid(&sp->page) != node)
664 continue;
665#endif
666 /* Enough room on this page? */
667 if (sp->units < SLOB_UNITS(size))
668 continue;
669
670 /* Attempt to alloc */
671 prev = sp->list.prev;
672 b = slob_page_alloc(sp, size, align);
673 if (!b)
674 continue;
675
676 /* Improve fragment distribution and reduce our average
677 * search time by starting our next search here. (see
678 * Knuth vol 1, sec 2.5, pg 449) */
679 if (prev != slob_list->prev &&
680 slob_list->next != prev->next)
681 list_move_tail(slob_list, prev->next);
682 break;
683 }
684 spin_unlock_irqrestore(&slob_lock, flags);
685
686 /* Not enough space: must allocate a new page */
687 if (!b) {
688 b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node);
689 if (!b)
690 return NULL;
691 raw_spin_lock_irqsave(&g_slob_kmem_cache_spin_lock, flags);
692 g_slob_kmem_cache_pages++;
693 raw_spin_unlock_irqrestore(&g_slob_kmem_cache_spin_lock, flags);
694 sp = slob_page(b);
695 set_slob_page(sp);
696
697 spin_lock_irqsave(&slob_lock, flags);
698 sp->units = SLOB_UNITS(PAGE_SIZE);
699 sp->free = b;
700 INIT_LIST_HEAD(&sp->list);
701 set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
702 set_slob_page_free(sp, slob_list);
703 b = slob_page_alloc(sp, size, align);
704 BUG_ON(!b);
705 spin_unlock_irqrestore(&slob_lock, flags);
706 }
707 if (unlikely((gfp & __GFP_ZERO) && b))
708 memset(b, 0, size);
709 return b;
710}
711
712/*
713 * slob_free: entry point into the slob allocator.
714 */
715static void slob_free(void *block, int size)
716{
717 struct slob_page *sp;
718 slob_t *prev, *next, *b = (slob_t *)block;
719 slobidx_t units;
720 unsigned long flags;
721 struct list_head *slob_list;
722
723 if (unlikely(ZERO_OR_NULL_PTR(block)))
724 return;
725 BUG_ON(!size);
726
727 sp = slob_page(block);
728 units = SLOB_UNITS(size);
729
730 spin_lock_irqsave(&slob_lock, flags);
731
732 if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
733 /* Go directly to page allocator. Do not pass slob allocator */
734 if (slob_page_free(sp))
735 clear_slob_page_free(sp);
736 spin_unlock_irqrestore(&slob_lock, flags);
737 clear_slob_page(sp);
738 free_slob_page(sp);
739 slob_free_pages(b, 0);
740 raw_spin_lock_irqsave(&g_slob_kmem_cache_spin_lock, flags);
741 g_slob_kmem_cache_pages--;
742 raw_spin_unlock_irqrestore(&g_slob_kmem_cache_spin_lock, flags);
743 return;
744 }
745
746 if (!slob_page_free(sp)) {
747 /* This slob page is about to become partially free. Easy! */
748 sp->units = units;
749 sp->free = b;
750 set_slob(b, units,
751 (void *)((unsigned long)(b +
752 SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
753 if (size < SLOB_BREAK1)
754 slob_list = &free_slob_small;
755 else if (size < SLOB_BREAK2)
756 slob_list = &free_slob_medium;
757 else
758 slob_list = &free_slob_large;
759 set_slob_page_free(sp, slob_list);
760 goto out;
761 }
762
763 /*
764 * Otherwise the page is already partially free, so find reinsertion
765 * point.
766 */
767 sp->units += units;
768
769 if (b < sp->free) {
770 if (b + units == sp->free) {
771 units += slob_units(sp->free);
772 sp->free = slob_next(sp->free);
773 }
774 set_slob(b, units, sp->free);
775 sp->free = b;
776 } else {
777 prev = sp->free;
778 next = slob_next(prev);
779 while (b > next) {
780 prev = next;
781 next = slob_next(prev);
782 }
783
784 if (!slob_last(prev) && b + units == next) {
785 units += slob_units(next);
786 set_slob(b, units, slob_next(next));
787 } else
788 set_slob(b, units, next);
789
790 if (prev + slob_units(prev) == b) {
791 units = slob_units(b) + slob_units(prev);
792 set_slob(prev, units, slob_next(b));
793 } else
794 set_slob(prev, slob_units(prev), b);
795 }
796out:
797 spin_unlock_irqrestore(&slob_lock, flags);
798}
799
800/*
801 * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
802 */
803
804void *__kmalloc_node(size_t size, gfp_t gfp, int node)
805{
806 int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
807 void *ret;
808 unsigned long flags;
809
810 if (!size)
811 return ZERO_SIZE_PTR;
812
813 gfp &= gfp_allowed_mask;
814
815 lockdep_trace_alloc(gfp);
816
817#ifdef CONFIG_DEBUG_SLOB_MARK_HEAD
818 if (size < PAGE_SIZE)
819 size += RECORD_COUNT * BYTES_PER_RECORD;
820#endif
821
822#ifdef CONFIG_KMALLOC_TRACKER
823 size += HEAP_SUFFIX_SIZE;
824#endif
825
826 if (size < PAGE_SIZE) {
827 if (!size)
828 return ZERO_SIZE_PTR;
829
830 ret = slob_alloc_general(size, gfp, align, node);
831
832 trace_kmalloc_node(_RET_IP_, ret,
833 size, size, gfp, node);
834
835#ifdef CONFIG_DEBUG_SLOB_MARK_HEAD
836 if (ret) {
837 *dbg_userrecord(ret,0) = (void *)RECORD_MAGIC;
838 *dbg_userrecord(ret,1) = __builtin_return_address(0);
839 *dbg_userrecord(ret,2) = current;
840 ret = (void *)dbg_userrecord(ret,RECORD_COUNT);
841 }
842
843#endif
844
845#ifdef CONFIG_KMALLOC_TRACKER
846 if (ret) {
847 kmalloc_alloc_tracker(ret, KMALLOC_ORIGINAL_SIZE(size));
848 return KMALLOC_SETUP(ret);
849 }
850#endif
851 } else {
852 unsigned int order = get_order(size);
853
854 if (likely(order))
855 gfp |= __GFP_COMP;
856 ret = slob_new_pages(gfp, order, node);
857 if (ret) {
858 struct page *page;
859 page = virt_to_page(ret);
860 page->private = size;
861 raw_spin_lock_irqsave(&g_slob_kmalloc_spin_lock, flags);
862 g_slob_kmalloc_pages += (1 << order);
863 raw_spin_unlock_irqrestore(&g_slob_kmalloc_spin_lock, flags);
864 }
865
866 trace_kmalloc_node(_RET_IP_, ret,
867 size, PAGE_SIZE << order, gfp, node);
868 }
869
870 kmemleak_alloc(ret, size, 1, gfp);
871 return ret;
872}
873EXPORT_SYMBOL(__kmalloc_node);
874
875void kfree(const void *block)
876{
877 struct slob_page *sp;
878 unsigned long flags;
879
880 trace_kfree(_RET_IP_, block);
881
882 if (unlikely(ZERO_OR_NULL_PTR(block)))
883 return;
884 kmemleak_free(block);
885
886#ifdef CONFIG_KMALLOC_TRACKER
887 int entry = 0;
888 void *mem = NULL;
889
890 sp = slob_page(block);
891 if (is_slob_page(sp)) {
892
893 mem = KMALLOC_BASE(block);
894 entry = *(size_t *)(mem);
895
896 if ((entry != 0) && (MEM_TRUE == check_node_entry(entry))) {
897 mem_free_tracker((void *)entry, MEM_TRACKER_TYPE_KMALLOC);
898 }else
899 panic("mem out!!");
900 slob_free_general(mem, sp);
lh758261d2023-07-13 05:52:04 -0700901 } else {
902 struct page *page;
903 unsigned int order;
904 page = &sp->page;
905 order = get_order(page->private);
906 raw_spin_lock_irqsave(&g_slob_kmalloc_spin_lock, flags);
907 g_slob_kmalloc_pages -= (1 << order);
908 raw_spin_unlock_irqrestore(&g_slob_kmalloc_spin_lock, flags);
lh9ed821d2023-04-07 01:36:19 -0700909 put_page(&sp->page);
lh758261d2023-07-13 05:52:04 -0700910 }
lh9ed821d2023-04-07 01:36:19 -0700911#else
912 sp = slob_page(block);
913 if (is_slob_page(sp)) {
914#ifdef CONFIG_DEBUG_SLOB_MARK_HEAD
915 if (*dbg_userhead(block) == (void *)RECORD_MAGIC) {
916 block = (void *)dbg_userhead(block);
917 } else
918 panic("memmory corruption!!");
919#endif
920 slob_free_general(block, sp);
921 } else {
922 struct page *page;
923 unsigned int order;
924 page = &sp->page;
925 order = get_order(page->private);
926 raw_spin_lock_irqsave(&g_slob_kmalloc_spin_lock, flags);
927 g_slob_kmalloc_pages -= (1 << order);
928 raw_spin_unlock_irqrestore(&g_slob_kmalloc_spin_lock, flags);
929 put_page(&sp->page);
930 }
931#endif
932
933}
934EXPORT_SYMBOL(kfree);
935
936/* can't use ksize for kmem_cache_alloc memory, only kmalloc */
937size_t ksize(const void *block)
938{
939 struct slob_page *sp;
940
941 BUG_ON(!block);
942 if (unlikely(block == ZERO_SIZE_PTR))
943 return 0;
944
945 sp = slob_page(block);
946 if (is_slob_page(sp)) {
947#ifdef CONFIG_SLOB_OPT
948 struct slob_item_info *slob_list;
949#else
950 struct list_head *slob_list;
951#endif
952 slob_list = get_slob_page_list_head(sp);
953
954#ifdef CONFIG_KMALLOC_TRACKER
xf.libe704612024-05-28 19:09:12 -0700955 return (slob_find_general_size(sp) - HEAP_SUFFIX_SIZE);
lh9ed821d2023-04-07 01:36:19 -0700956#endif
957
958#ifdef CONFIG_DEBUG_SLOB_MARK_HEAD
959 return (slob_find_general_size(sp) - RECORD_COUNT * BYTES_PER_RECORD);
960#else
961 return slob_find_general_size(sp);
962#endif
963
964 } else
965 return sp->page.private;
966}
967EXPORT_SYMBOL(ksize);
968
969struct kmem_cache {
970 unsigned int size, align;
971 unsigned long flags;
972 const char *name;
973 void (*ctor)(void *);
974};
975
976struct kmem_cache *kmem_cache_create(const char *name, size_t size,
977 size_t align, unsigned long flags, void (*ctor)(void *))
978{
979 struct kmem_cache *c;
980
981 c = slob_alloc(sizeof(struct kmem_cache),
982 GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1);
983
984 if (c) {
985 c->name = name;
986 c->size = size;
987 if (flags & SLAB_DESTROY_BY_RCU) {
988 /* leave room for rcu footer at the end of object */
989 c->size += sizeof(struct slob_rcu);
990 }
991 c->flags = flags;
992 c->ctor = ctor;
993 /* ignore alignment unless it's forced */
994 c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
995 if (c->align < ARCH_SLAB_MINALIGN)
996 c->align = ARCH_SLAB_MINALIGN;
997 if (c->align < align)
998 c->align = align;
999 } else if (flags & SLAB_PANIC)
1000 panic("Cannot create slab cache %s\n", name);
1001
1002 kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
1003 return c;
1004}
1005EXPORT_SYMBOL(kmem_cache_create);
1006
1007void kmem_cache_destroy(struct kmem_cache *c)
1008{
1009 kmemleak_free(c);
1010 if (c->flags & SLAB_DESTROY_BY_RCU)
1011 rcu_barrier();
1012 slob_free(c, sizeof(struct kmem_cache));
1013}
1014EXPORT_SYMBOL(kmem_cache_destroy);
1015
1016static unsigned int align(unsigned int i)
1017{
1018 return (i + 7) & ~7u;
1019}
1020void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
1021{
1022 void *b;
1023
1024 flags &= gfp_allowed_mask;
1025 unsigned long spin_flags;
1026
1027 lockdep_trace_alloc(flags);
1028
1029 if (c->size < PAGE_SIZE) {
1030 //b = slob_alloc(c->size, flags, c->align, node);
1031 c->size = align(c->size);/*align 8*/
1032 c->align = 0;
1033 b = slob_alloc(c->size, flags, 0, node);/*already align 8*/
1034 trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
1035 SLOB_UNITS(c->size) * SLOB_UNIT,
1036 flags, node);
1037 } else {
1038 b = slob_new_pages(flags, get_order(c->size), node);
1039 if(b) {
1040 raw_spin_lock_irqsave(&g_slob_kmem_cache_spin_lock, spin_flags);
1041 g_slob_kmem_cache_pages += (1 << get_order(c->size));
1042 raw_spin_unlock_irqrestore(&g_slob_kmem_cache_spin_lock, spin_flags);
1043 }
1044 trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
1045 PAGE_SIZE << get_order(c->size),
1046 flags, node);
1047 }
1048 if (c->ctor)
1049 c->ctor(b);
1050
1051 kmemleak_alloc_recursive(b, c->size, 1, c->flags, flags);
1052 return b;
1053}
1054
1055EXPORT_SYMBOL(kmem_cache_alloc_node);
1056static void __kmem_cache_free(void *b, int size)
1057{
1058 unsigned long flags;
1059 if (size < PAGE_SIZE)
1060 slob_free(b, size);
1061 else {
1062 slob_free_pages(b, get_order(size));
1063 raw_spin_lock_irqsave(&g_slob_kmem_cache_spin_lock, flags);
1064 g_slob_kmem_cache_pages -= (1 << get_order(size));
1065 raw_spin_unlock_irqrestore(&g_slob_kmem_cache_spin_lock, flags);
1066 }
1067}
1068
1069static void kmem_rcu_free(struct rcu_head *head)
1070{
1071 struct slob_rcu *slob_rcu = (struct slob_rcu *)head;
1072 void *b = (void *)slob_rcu - (slob_rcu->size - sizeof(struct slob_rcu));
1073
1074 __kmem_cache_free(b, slob_rcu->size);
1075}
1076
1077void kmem_cache_free(struct kmem_cache *c, void *b)
1078{
1079 kmemleak_free_recursive(b, c->flags);
1080
1081 if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
1082 struct slob_rcu *slob_rcu;
1083 slob_rcu = b + (c->size - sizeof(struct slob_rcu));
1084 slob_rcu->size = c->size;
1085 call_rcu(&slob_rcu->head, kmem_rcu_free);
1086 } else {
1087 __kmem_cache_free(b, c->size);
1088 }
1089
1090 trace_kmem_cache_free(_RET_IP_, b);
1091}
1092EXPORT_SYMBOL(kmem_cache_free);
1093
1094unsigned int kmem_cache_size(struct kmem_cache *c)
1095{
1096 return c->size;
1097}
1098EXPORT_SYMBOL(kmem_cache_size);
1099
1100int kmem_cache_shrink(struct kmem_cache *d)
1101{
1102#ifdef CONFIG_SLOB_OPT
1103 int i;
1104 unsigned long flags;
1105 struct slob_page *sp,*n;
1106
1107 for (i = 0; i < SLOB_LIST_NUM; i++){
1108 if (slob_sizes[i].count == 0)
1109 continue;
1110 spin_lock_irqsave(&slob_lock, flags);
1111
1112 list_for_each_entry_safe(sp, n, &(slob_sizes[i].slob_list), list) {
1113 if (sp->units == SLOB_UNITS(PAGE_SIZE)){
1114 if (slob_page_free(sp))
1115 clear_slob_page_free(sp);
1116 clear_slob_page(sp);
1117 clear_slob_page_list_index(sp);
1118 free_slob_page(sp);
1119 slob_free_pages(page_address((struct page*)sp), 0);
1120 }
1121 }
1122 slob_sizes[i].count = 0;
1123 spin_unlock_irqrestore(&slob_lock, flags);
1124
1125 }
1126#endif
1127 return 0;
1128}
1129EXPORT_SYMBOL(kmem_cache_shrink);
1130
1131static unsigned int slob_ready __read_mostly;
1132
1133int slab_is_available(void)
1134{
1135 return slob_ready;
1136}
1137
1138void __init kmem_cache_init(void)
1139{
1140 slob_ready = 1;
1141}
1142
1143void __init kmem_cache_init_late(void)
1144{
1145 /* Nothing to do */
1146}