1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3eda14cbcSMatt Macy * Copyright (C) 2007 The Regents of the University of California. 4eda14cbcSMatt Macy * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 5eda14cbcSMatt Macy * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 6eda14cbcSMatt Macy * UCRL-CODE-235197 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * This file is part of the SPL, Solaris Porting Layer. 9eda14cbcSMatt Macy * 10eda14cbcSMatt Macy * The SPL is free software; you can redistribute it and/or modify it 11eda14cbcSMatt Macy * under the terms of the GNU General Public License as published by the 12eda14cbcSMatt Macy * Free Software Foundation; either version 2 of the License, or (at your 13eda14cbcSMatt Macy * option) any later version. 14eda14cbcSMatt Macy * 15eda14cbcSMatt Macy * The SPL is distributed in the hope that it will be useful, but WITHOUT 16eda14cbcSMatt Macy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17eda14cbcSMatt Macy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18eda14cbcSMatt Macy * for more details. 19eda14cbcSMatt Macy * 20eda14cbcSMatt Macy * You should have received a copy of the GNU General Public License along 21eda14cbcSMatt Macy * with the SPL. If not, see <http://www.gnu.org/licenses/>. 22eda14cbcSMatt Macy */ 23eda14cbcSMatt Macy 24eda14cbcSMatt Macy #ifndef _SPL_VMEM_H 25eda14cbcSMatt Macy #define _SPL_VMEM_H 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy #include <sys/kmem.h> 28eda14cbcSMatt Macy #include <linux/sched.h> 29eda14cbcSMatt Macy #include <linux/vmalloc.h> 30eda14cbcSMatt Macy 31eda14cbcSMatt Macy typedef struct vmem { } vmem_t; 32eda14cbcSMatt Macy 33eda14cbcSMatt Macy /* 34eda14cbcSMatt Macy * Memory allocation interfaces 35eda14cbcSMatt Macy */ 36eda14cbcSMatt Macy #define VMEM_ALLOC 0x01 37eda14cbcSMatt Macy #define VMEM_FREE 0x02 38eda14cbcSMatt Macy 39eda14cbcSMatt Macy #ifndef VMALLOC_TOTAL 40eda14cbcSMatt Macy #define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START) 41eda14cbcSMatt Macy #endif 42eda14cbcSMatt Macy 43eda14cbcSMatt Macy /* 44eda14cbcSMatt Macy * vmem_* is an interface to a low level arena-based memory allocator on 45eda14cbcSMatt Macy * Illumos that is used to allocate virtual address space. The kmem SLAB 46eda14cbcSMatt Macy * allocator allocates slabs from it. Then the generic allocation functions 47eda14cbcSMatt Macy * kmem_{alloc,zalloc,free}() are layered on top of SLAB allocators. 48eda14cbcSMatt Macy * 49eda14cbcSMatt Macy * On Linux, the primary means of doing allocations is via kmalloc(), which 50eda14cbcSMatt Macy * is similarly layered on top of something called the buddy allocator. The 51eda14cbcSMatt Macy * buddy allocator is not available to kernel modules, it uses physical 52eda14cbcSMatt Macy * memory addresses rather than virtual memory addresses and is prone to 53eda14cbcSMatt Macy * fragmentation. 54eda14cbcSMatt Macy * 55eda14cbcSMatt Macy * Linux sets aside a relatively small address space for in-kernel virtual 56eda14cbcSMatt Macy * memory from which allocations can be done using vmalloc(). It might seem 57eda14cbcSMatt Macy * like a good idea to use vmalloc() to implement something similar to 58eda14cbcSMatt Macy * Illumos' allocator. However, this has the following problems: 59eda14cbcSMatt Macy * 60eda14cbcSMatt Macy * 1. Page directory table allocations are hard coded to use GFP_KERNEL. 61eda14cbcSMatt Macy * Consequently, any KM_PUSHPAGE or KM_NOSLEEP allocations done using 62eda14cbcSMatt Macy * vmalloc() will not have proper semantics. 63eda14cbcSMatt Macy * 64eda14cbcSMatt Macy * 2. Address space exhaustion is a real issue on 32-bit platforms where 65eda14cbcSMatt Macy * only a few 100MB are available. The kernel will handle it by spinning 66eda14cbcSMatt Macy * when it runs out of address space. 67eda14cbcSMatt Macy * 68eda14cbcSMatt Macy * 3. All vmalloc() allocations and frees are protected by a single global 69eda14cbcSMatt Macy * lock which serializes all allocations. 70eda14cbcSMatt Macy * 71eda14cbcSMatt Macy * 4. Accessing /proc/meminfo and /proc/vmallocinfo will iterate the entire 72eda14cbcSMatt Macy * list. The former will sum the allocations while the latter will print 73eda14cbcSMatt Macy * them to user space in a way that user space can keep the lock held 74eda14cbcSMatt Macy * indefinitely. When the total number of mapped allocations is large 75eda14cbcSMatt Macy * (several 100,000) a large amount of time will be spent waiting on locks. 76eda14cbcSMatt Macy * 77eda14cbcSMatt Macy * 5. Linux has a wait_on_bit() locking primitive that assumes physical 78eda14cbcSMatt Macy * memory is used, it simply does not work on virtual memory. Certain 79eda14cbcSMatt Macy * Linux structures (e.g. the superblock) use them and might be embedded 80eda14cbcSMatt Macy * into a structure from Illumos. This makes using Linux virtual memory 81eda14cbcSMatt Macy * unsafe in certain situations. 82eda14cbcSMatt Macy * 83eda14cbcSMatt Macy * It follows that we cannot obtain identical semantics to those on Illumos. 84eda14cbcSMatt Macy * Consequently, we implement the kmem_{alloc,zalloc,free}() functions in 85eda14cbcSMatt Macy * such a way that they can be used as drop-in replacements for small vmem_* 86eda14cbcSMatt Macy * allocations (8MB in size or smaller) and map vmem_{alloc,zalloc,free}() 87eda14cbcSMatt Macy * to them. 88eda14cbcSMatt Macy */ 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy #define vmem_alloc(sz, fl) spl_vmem_alloc((sz), (fl), __func__, __LINE__) 91eda14cbcSMatt Macy #define vmem_zalloc(sz, fl) spl_vmem_zalloc((sz), (fl), __func__, __LINE__) 92eda14cbcSMatt Macy #define vmem_free(ptr, sz) spl_vmem_free((ptr), (sz)) 93eda14cbcSMatt Macy 94*4e8d558cSMartin Matuska extern void *spl_vmem_alloc(size_t sz, int fl, const char *func, int line) 95*4e8d558cSMartin Matuska __attribute__((malloc, alloc_size(1))); 96*4e8d558cSMartin Matuska extern void *spl_vmem_zalloc(size_t sz, int fl, const char *func, int line) 97*4e8d558cSMartin Matuska __attribute__((malloc, alloc_size(1))); 98eda14cbcSMatt Macy extern void spl_vmem_free(const void *ptr, size_t sz); 99eda14cbcSMatt Macy 100eda14cbcSMatt Macy int spl_vmem_init(void); 101eda14cbcSMatt Macy void spl_vmem_fini(void); 102eda14cbcSMatt Macy 103eda14cbcSMatt Macy #endif /* _SPL_VMEM_H */ 104