Remove get_vmalloc_info() wrapper
The get_vmalloc_info() function was used to back the vmem_size() function. This was always problematic and resulted in brittle code because the kernel never provided a clean interface for modules. However, it turns out that the only caller of this function in ZFS uses it to determine the total virtual address space size. This can be determined easily without get_vmalloc_info() so vmem_size() has been updated to take this approach which allows us to shed the get_vmalloc_info() dependency. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
50e41ab1e1
commit
e1310afae3
|
@ -25,12 +25,10 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
|
||||||
SPL_AC_ATOMIC_SPINLOCK
|
SPL_AC_ATOMIC_SPINLOCK
|
||||||
SPL_AC_SHRINKER_CALLBACK
|
SPL_AC_SHRINKER_CALLBACK
|
||||||
SPL_AC_CTL_NAME
|
SPL_AC_CTL_NAME
|
||||||
SPL_AC_VMALLOC_INFO
|
|
||||||
SPL_AC_PDE_DATA
|
SPL_AC_PDE_DATA
|
||||||
SPL_AC_MUTEX_OWNER
|
SPL_AC_MUTEX_OWNER
|
||||||
SPL_AC_MUTEX_OWNER_TASK_STRUCT
|
SPL_AC_MUTEX_OWNER_TASK_STRUCT
|
||||||
SPL_AC_KALLSYMS_LOOKUP_NAME
|
SPL_AC_KALLSYMS_LOOKUP_NAME
|
||||||
SPL_AC_GET_VMALLOC_INFO
|
|
||||||
SPL_AC_PGDAT_HELPERS
|
SPL_AC_PGDAT_HELPERS
|
||||||
SPL_AC_FIRST_ONLINE_PGDAT
|
SPL_AC_FIRST_ONLINE_PGDAT
|
||||||
SPL_AC_NEXT_ONLINE_PGDAT
|
SPL_AC_NEXT_ONLINE_PGDAT
|
||||||
|
@ -990,43 +988,6 @@ AC_DEFUN([SPL_AC_KALLSYMS_LOOKUP_NAME],
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl #
|
|
||||||
dnl # Proposed API change,
|
|
||||||
dnl # This symbol is not available in stock kernels. You may build a
|
|
||||||
dnl # custom kernel with the *-spl-export-symbols.patch which will export
|
|
||||||
dnl # these symbols for use. If your already rolling a custom kernel for
|
|
||||||
dnl # your environment this is recommended.
|
|
||||||
dnl #
|
|
||||||
AC_DEFUN([SPL_AC_GET_VMALLOC_INFO],
|
|
||||||
[AC_MSG_CHECKING([whether get_vmalloc_info() is available])
|
|
||||||
SPL_CHECK_SYMBOL_EXPORT([get_vmalloc_info], [], [
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_GET_VMALLOC_INFO, 1,
|
|
||||||
[get_vmalloc_info() is available])
|
|
||||||
], [
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl #
|
|
||||||
dnl # 3.10 API change,
|
|
||||||
dnl # struct vmalloc_info is now declared in linux/vmalloc.h
|
|
||||||
dnl #
|
|
||||||
AC_DEFUN([SPL_AC_VMALLOC_INFO], [
|
|
||||||
AC_MSG_CHECKING([whether struct vmalloc_info is declared])
|
|
||||||
SPL_LINUX_TRY_COMPILE([
|
|
||||||
#include <linux/vmalloc.h>
|
|
||||||
struct vmalloc_info { void *a; };
|
|
||||||
],[
|
|
||||||
return 0;
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_VMALLOC_INFO, 1, [yes])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl #
|
dnl #
|
||||||
dnl # 3.10 API change,
|
dnl # 3.10 API change,
|
||||||
dnl # PDE is replaced by PDE_DATA
|
dnl # PDE is replaced by PDE_DATA
|
||||||
|
|
|
@ -60,39 +60,12 @@ extern vmem_t *zio_arena; /* arena for allocating zio memory */
|
||||||
extern pgcnt_t spl_kmem_availrmem(void);
|
extern pgcnt_t spl_kmem_availrmem(void);
|
||||||
extern size_t vmem_size(vmem_t *vmp, int typemask);
|
extern size_t vmem_size(vmem_t *vmp, int typemask);
|
||||||
|
|
||||||
/*
|
|
||||||
* The following symbols are available for use within the kernel
|
|
||||||
* itself, and they used to be available in older kernels. But it
|
|
||||||
* looks like they have been removed perhaps due to lack of use.
|
|
||||||
* For our purposes we need them to access the global memory state
|
|
||||||
* of the system, which is even available to user space process
|
|
||||||
* in /proc/meminfo. It's odd to me that there is no kernel API
|
|
||||||
* to get the same information, minimally the proc handler for
|
|
||||||
* the above mentioned /proc/meminfo file would make use of it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Source linux/fs/proc/mmu.c */
|
|
||||||
#ifndef HAVE_GET_VMALLOC_INFO
|
|
||||||
#ifdef CONFIG_MMU
|
|
||||||
|
|
||||||
#ifndef HAVE_VMALLOC_INFO
|
|
||||||
struct vmalloc_info {
|
|
||||||
unsigned long used;
|
|
||||||
unsigned long largest_chunk;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*get_vmalloc_info_t)(struct vmalloc_info *);
|
|
||||||
extern get_vmalloc_info_t get_vmalloc_info_fn;
|
|
||||||
|
|
||||||
#define VMEM_ALLOC 0x01
|
#define VMEM_ALLOC 0x01
|
||||||
#define VMEM_FREE 0x02
|
#define VMEM_FREE 0x02
|
||||||
|
|
||||||
|
#ifndef VMALLOC_TOTAL
|
||||||
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
|
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
|
||||||
# define get_vmalloc_info(vmi) get_vmalloc_info_fn(vmi)
|
#endif
|
||||||
#else
|
|
||||||
# error "CONFIG_MMU must be defined"
|
|
||||||
#endif /* CONFIG_MMU */
|
|
||||||
#endif /* HAVE_GET_VMALLOC_INFO */
|
|
||||||
|
|
||||||
#ifdef HAVE_PGDAT_HELPERS
|
#ifdef HAVE_PGDAT_HELPERS
|
||||||
/* Source linux/mm/mmzone.c */
|
/* Source linux/mm/mmzone.c */
|
||||||
|
|
|
@ -148,11 +148,6 @@ EXPORT_SYMBOL(zio_alloc_arena);
|
||||||
vmem_t *zio_arena = NULL;
|
vmem_t *zio_arena = NULL;
|
||||||
EXPORT_SYMBOL(zio_arena);
|
EXPORT_SYMBOL(zio_arena);
|
||||||
|
|
||||||
#ifndef HAVE_GET_VMALLOC_INFO
|
|
||||||
get_vmalloc_info_t get_vmalloc_info_fn = SYMBOL_POISON;
|
|
||||||
EXPORT_SYMBOL(get_vmalloc_info_fn);
|
|
||||||
#endif /* HAVE_GET_VMALLOC_INFO */
|
|
||||||
|
|
||||||
#ifdef HAVE_PGDAT_HELPERS
|
#ifdef HAVE_PGDAT_HELPERS
|
||||||
# ifndef HAVE_FIRST_ONLINE_PGDAT
|
# ifndef HAVE_FIRST_ONLINE_PGDAT
|
||||||
first_online_pgdat_t first_online_pgdat_fn = SYMBOL_POISON;
|
first_online_pgdat_t first_online_pgdat_fn = SYMBOL_POISON;
|
||||||
|
@ -270,20 +265,11 @@ EXPORT_SYMBOL(spl_kmem_availrmem);
|
||||||
size_t
|
size_t
|
||||||
vmem_size(vmem_t *vmp, int typemask)
|
vmem_size(vmem_t *vmp, int typemask)
|
||||||
{
|
{
|
||||||
struct vmalloc_info vmi;
|
ASSERT3P(vmp, ==, NULL);
|
||||||
size_t size = 0;
|
ASSERT3S(typemask & VMEM_ALLOC, ==, VMEM_ALLOC);
|
||||||
|
ASSERT3S(typemask & VMEM_FREE, ==, VMEM_FREE);
|
||||||
|
|
||||||
ASSERT(vmp == NULL);
|
return (VMALLOC_TOTAL);
|
||||||
ASSERT(typemask & (VMEM_ALLOC | VMEM_FREE));
|
|
||||||
|
|
||||||
get_vmalloc_info(&vmi);
|
|
||||||
if (typemask & VMEM_ALLOC)
|
|
||||||
size += (size_t)vmi.used;
|
|
||||||
|
|
||||||
if (typemask & VMEM_FREE)
|
|
||||||
size += (size_t)(VMALLOC_TOTAL - vmi.used);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vmem_size);
|
EXPORT_SYMBOL(vmem_size);
|
||||||
|
|
||||||
|
@ -2500,15 +2486,6 @@ spl_kmem_init_globals(void)
|
||||||
int
|
int
|
||||||
spl_kmem_init_kallsyms_lookup(void)
|
spl_kmem_init_kallsyms_lookup(void)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_GET_VMALLOC_INFO
|
|
||||||
get_vmalloc_info_fn = (get_vmalloc_info_t)
|
|
||||||
spl_kallsyms_lookup_name("get_vmalloc_info");
|
|
||||||
if (!get_vmalloc_info_fn) {
|
|
||||||
printk(KERN_ERR "Error: Unknown symbol get_vmalloc_info\n");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_GET_VMALLOC_INFO */
|
|
||||||
|
|
||||||
#ifdef HAVE_PGDAT_HELPERS
|
#ifdef HAVE_PGDAT_HELPERS
|
||||||
# ifndef HAVE_FIRST_ONLINE_PGDAT
|
# ifndef HAVE_FIRST_ONLINE_PGDAT
|
||||||
first_online_pgdat_fn = (first_online_pgdat_t)
|
first_online_pgdat_fn = (first_online_pgdat_t)
|
||||||
|
|
|
@ -77,10 +77,6 @@
|
||||||
#define SPLAT_KMEM_TEST11_DESC "Slab memory overcommit test"
|
#define SPLAT_KMEM_TEST11_DESC "Slab memory overcommit test"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SPLAT_KMEM_TEST12_ID 0x010c
|
|
||||||
#define SPLAT_KMEM_TEST12_NAME "vmem_size"
|
|
||||||
#define SPLAT_KMEM_TEST12_DESC "Memory zone test"
|
|
||||||
|
|
||||||
#define SPLAT_KMEM_TEST13_ID 0x010d
|
#define SPLAT_KMEM_TEST13_ID 0x010d
|
||||||
#define SPLAT_KMEM_TEST13_NAME "slab_reclaim"
|
#define SPLAT_KMEM_TEST13_NAME "slab_reclaim"
|
||||||
#define SPLAT_KMEM_TEST13_DESC "Slab direct memory reclaim test"
|
#define SPLAT_KMEM_TEST13_DESC "Slab direct memory reclaim test"
|
||||||
|
@ -1104,84 +1100,6 @@ splat_kmem_test11(struct file *file, void *arg)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Check vmem_size() behavior by acquiring the alloc/free/total vmem
|
|
||||||
* space, then allocate a known buffer size from vmem space. We can
|
|
||||||
* then check that vmem_size() values were updated properly with in
|
|
||||||
* a fairly small tolerence. The tolerance is important because we
|
|
||||||
* are not the only vmem consumer on the system. Other unrelated
|
|
||||||
* allocations might occur during the small test window. The vmem
|
|
||||||
* allocation itself may also add in a little extra private space to
|
|
||||||
* the buffer. Finally, verify total space always remains unchanged.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
splat_kmem_test12(struct file *file, void *arg)
|
|
||||||
{
|
|
||||||
size_t alloc1, free1, total1;
|
|
||||||
size_t alloc2, free2, total2;
|
|
||||||
int size = 8*1024*1024;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
alloc1 = vmem_size(NULL, VMEM_ALLOC);
|
|
||||||
free1 = vmem_size(NULL, VMEM_FREE);
|
|
||||||
total1 = vmem_size(NULL, VMEM_ALLOC | VMEM_FREE);
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Vmem alloc=%lu "
|
|
||||||
"free=%lu total=%lu\n", (unsigned long)alloc1,
|
|
||||||
(unsigned long)free1, (unsigned long)total1);
|
|
||||||
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Alloc %d bytes\n", size);
|
|
||||||
ptr = vmem_alloc(size, KM_SLEEP);
|
|
||||||
if (!ptr) {
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME,
|
|
||||||
"Failed to alloc %d bytes\n", size);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc2 = vmem_size(NULL, VMEM_ALLOC);
|
|
||||||
free2 = vmem_size(NULL, VMEM_FREE);
|
|
||||||
total2 = vmem_size(NULL, VMEM_ALLOC | VMEM_FREE);
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Vmem alloc=%lu "
|
|
||||||
"free=%lu total=%lu\n", (unsigned long)alloc2,
|
|
||||||
(unsigned long)free2, (unsigned long)total2);
|
|
||||||
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Free %d bytes\n", size);
|
|
||||||
vmem_free(ptr, size);
|
|
||||||
if (alloc2 < (alloc1 + size - (size / 100)) ||
|
|
||||||
alloc2 > (alloc1 + size + (size / 100))) {
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Failed "
|
|
||||||
"VMEM_ALLOC size: %lu != %lu+%d (+/- 1%%)\n",
|
|
||||||
(unsigned long)alloc2,(unsigned long)alloc1,size);
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free2 < (free1 - size - (size / 100)) ||
|
|
||||||
free2 > (free1 - size + (size / 100))) {
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Failed "
|
|
||||||
"VMEM_FREE size: %lu != %lu-%d (+/- 1%%)\n",
|
|
||||||
(unsigned long)free2, (unsigned long)free1, size);
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total1 != total2) {
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME, "Failed "
|
|
||||||
"VMEM_ALLOC | VMEM_FREE not constant: "
|
|
||||||
"%lu != %lu\n", (unsigned long)total2,
|
|
||||||
(unsigned long)total1);
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME,
|
|
||||||
"VMEM_ALLOC within tolerance: ~%ld%% (%ld/%d)\n",
|
|
||||||
(long)abs(alloc1 + (long)size - alloc2) * 100 / (long)size,
|
|
||||||
(long)abs(alloc1 + (long)size - alloc2), size);
|
|
||||||
splat_vprint(file, SPLAT_KMEM_TEST12_NAME,
|
|
||||||
"VMEM_FREE within tolerance: ~%ld%% (%ld/%d)\n",
|
|
||||||
(long)abs((free1 - (long)size) - free2) * 100 / (long)size,
|
|
||||||
(long)abs((free1 - (long)size) - free2), size);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct dummy_page {
|
typedef struct dummy_page {
|
||||||
struct list_head dp_list;
|
struct list_head dp_list;
|
||||||
char dp_pad[PAGE_SIZE - sizeof(struct list_head)];
|
char dp_pad[PAGE_SIZE - sizeof(struct list_head)];
|
||||||
|
@ -1360,8 +1278,6 @@ splat_kmem_init(void)
|
||||||
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST11_NAME, SPLAT_KMEM_TEST11_DESC,
|
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST11_NAME, SPLAT_KMEM_TEST11_DESC,
|
||||||
SPLAT_KMEM_TEST11_ID, splat_kmem_test11);
|
SPLAT_KMEM_TEST11_ID, splat_kmem_test11);
|
||||||
#endif
|
#endif
|
||||||
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST12_NAME, SPLAT_KMEM_TEST12_DESC,
|
|
||||||
SPLAT_KMEM_TEST12_ID, splat_kmem_test12);
|
|
||||||
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST13_NAME, SPLAT_KMEM_TEST13_DESC,
|
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST13_NAME, SPLAT_KMEM_TEST13_DESC,
|
||||||
SPLAT_KMEM_TEST13_ID, splat_kmem_test13);
|
SPLAT_KMEM_TEST13_ID, splat_kmem_test13);
|
||||||
|
|
||||||
|
@ -1373,7 +1289,6 @@ splat_kmem_fini(splat_subsystem_t *sub)
|
||||||
{
|
{
|
||||||
ASSERT(sub);
|
ASSERT(sub);
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST13_ID);
|
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST13_ID);
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST12_ID);
|
|
||||||
#if 0
|
#if 0
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST11_ID);
|
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST11_ID);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue