mm/mempool.c

Source file repositories/reference/linux-study-clean/mm/mempool.c

File Facts

System
Linux kernel
Corpus path
mm/mempool.c
Extension
.c
Size
22640 bytes
Lines
760
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (obj[i] != exp) {
			poison_error(pool, element, size, i);
			return;
		}
	}
	memset(obj, POISON_INUSE, size);
}

static void check_element(struct mempool *pool, void *element)
{
	/* Skip checking: KASAN might save its metadata in the element. */
	if (kasan_enabled())
		return;

	/* Mempools backed by slab allocator */
	if (pool->free == mempool_kfree) {
		__check_element(pool, element, (size_t)pool->pool_data);
	} else if (pool->free == mempool_free_slab) {
		__check_element(pool, element, kmem_cache_size(pool->pool_data));
	} else if (pool->free == mempool_free_pages) {
		/* Mempools backed by page allocator */
		int order = (int)(long)pool->pool_data;

#ifdef CONFIG_HIGHMEM
		for (int i = 0; i < (1 << order); i++) {
			struct page *page = (struct page *)element;
			void *addr = kmap_local_page(page + i);

			__check_element(pool, addr, PAGE_SIZE);
			kunmap_local(addr);
		}
#else
		void *addr = page_address((struct page *)element);

		__check_element(pool, addr, PAGE_SIZE << order);
#endif
	}
}

static void __poison_element(void *element, size_t size)
{
	u8 *obj = element;

	memset(obj, POISON_FREE, size - 1);
	obj[size - 1] = POISON_END;
}

static void poison_element(struct mempool *pool, void *element)
{
	/* Skip poisoning: KASAN might save its metadata in the element. */
	if (kasan_enabled())
		return;

	/* Mempools backed by slab allocator */
	if (pool->alloc == mempool_kmalloc) {
		__poison_element(element, (size_t)pool->pool_data);
	} else if (pool->alloc == mempool_alloc_slab) {
		__poison_element(element, kmem_cache_size(pool->pool_data));
	} else if (pool->alloc == mempool_alloc_pages) {
		/* Mempools backed by page allocator */
		int order = (int)(long)pool->pool_data;

#ifdef CONFIG_HIGHMEM
		for (int i = 0; i < (1 << order); i++) {
			struct page *page = (struct page *)element;
			void *addr = kmap_local_page(page + i);

			__poison_element(addr, PAGE_SIZE);
			kunmap_local(addr);
		}
#else
		void *addr = page_address((struct page *)element);

		__poison_element(addr, PAGE_SIZE << order);
#endif
	}
}
#else /* CONFIG_SLUB_DEBUG_ON */
static inline void check_element(struct mempool *pool, void *element)
{
}
static inline void poison_element(struct mempool *pool, void *element)
{
}
#endif /* CONFIG_SLUB_DEBUG_ON */

static __always_inline bool kasan_poison_element(struct mempool *pool,
		void *element)
{
	if (pool->alloc == mempool_alloc_slab || pool->alloc == mempool_kmalloc)

Annotation

Implementation Notes