Additional Linux VM integration

Added support for Solaris swapfs_minfree, and swapfs_reserve tunables.
In additional availrmem is now available and return a reasonable value
which is reasonably analogous to the Solaris meaning.  On linux we
return the sun of free and inactive pages since these are all easily
reclaimable.

All tunables are available in /proc/sys/kernel/spl/vm/* and they may
need a little adjusting once we observe the real behavior.  Some of
the defaults are mapped to similar linux counterparts, others are
straight from the OpenSolaris defaults.
This commit is contained in:
Brian Behlendorf 2009-02-05 12:26:34 -08:00
parent 36b313dacf
commit 4ab13d3b5c
7 changed files with 214 additions and 39 deletions

View File

@ -707,7 +707,7 @@ AC_DEFUN([SPL_AC_3ARGS_ON_EACH_CPU], [
])
dnl #
dnl # Distro specific first_online_pgdat symbol export.
dnl # Distro specific first_online_pgdat() symbol export.
dnl #
AC_DEFUN([SPL_AC_FIRST_ONLINE_PGDAT], [
SPL_CHECK_SYMBOL_EXPORT(
@ -719,7 +719,7 @@ AC_DEFUN([SPL_AC_FIRST_ONLINE_PGDAT], [
])
dnl #
dnl # Distro specific next_online_pgdat symbol export.
dnl # Distro specific next_online_pgdat() symbol export.
dnl #
AC_DEFUN([SPL_AC_NEXT_ONLINE_PGDAT], [
SPL_CHECK_SYMBOL_EXPORT(
@ -731,7 +731,7 @@ AC_DEFUN([SPL_AC_NEXT_ONLINE_PGDAT], [
])
dnl #
dnl # Distro specific next_zone symbol export.
dnl # Distro specific next_zone() symbol export.
dnl #
AC_DEFUN([SPL_AC_NEXT_ZONE], [
SPL_CHECK_SYMBOL_EXPORT(
@ -741,3 +741,15 @@ AC_DEFUN([SPL_AC_NEXT_ZONE], [
[next_zone() is available])],
[])
])
dnl #
dnl # Distro specific get_zone_counts() symbol export.
dnl #
AC_DEFUN([SPL_AC_GET_ZONE_COUNTS], [
SPL_CHECK_SYMBOL_EXPORT(
[get_zone_counts],
[],
[AC_DEFINE(HAVE_GET_ZONE_COUNTS, 1,
[get_zone_counts() is available])],
[])
])

39
configure vendored
View File

@ -20598,6 +20598,45 @@ _ACEOF
echo "$as_me:$LINENO: checking whether symbol get_zone_counts is exported" >&5
echo $ECHO_N "checking whether symbol get_zone_counts is exported... $ECHO_C" >&6
grep -q -E '[[:space:]]get_zone_counts[[:space:]]' $LINUX/Module.symvers 2>/dev/null
rc=$?
if test $rc -ne 0; then
export=0
for file in ; do
grep -q -E "EXPORT_SYMBOL.*(get_zone_counts)" "$LINUX/$file" 2>/dev/null
rc=$?
if test $rc -eq 0; then
export=1
break;
fi
done
if test $export -eq 0; then
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
else
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
cat >>confdefs.h <<\_ACEOF
#define HAVE_GET_ZONE_COUNTS 1
_ACEOF
fi
else
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
cat >>confdefs.h <<\_ACEOF
#define HAVE_GET_ZONE_COUNTS 1
_ACEOF
fi
TOPDIR=`/bin/pwd`
# Add "V=1" to KERNELMAKE_PARAMS to enable verbose module build

View File

@ -72,6 +72,7 @@ SPL_AC_3ARGS_ON_EACH_CPU
SPL_AC_FIRST_ONLINE_PGDAT
SPL_AC_NEXT_ONLINE_PGDAT
SPL_AC_NEXT_ZONE
SPL_AC_GET_ZONE_COUNTS
TOPDIR=`/bin/pwd`

View File

@ -45,15 +45,14 @@
#define physmem num_physpages
#define freemem nr_free_pages()
#define availrmem spl_kmem_availrmem()
extern pgcnt_t minfree; /* Sum of zone->pages_min */
extern pgcnt_t desfree; /* Sum of zone->pages_low */
extern pgcnt_t lotsfree; /* Sum of zone->pages_high */
extern pgcnt_t needfree; /* Always 0 */
extern pgcnt_t swapfs_minfree;
extern pgcnt_t swapfs_desfree;
extern pgcnt_t swapfs_reserve;
extern pgcnt_t availrmem;
extern pgcnt_t needfree; /* Always 0 unused in new Solaris */
extern pgcnt_t swapfs_minfree; /* Solaris default value */
extern pgcnt_t swapfs_reserve; /* Solaris default value */
extern vmem_t *heap_arena; /* primary kernel heap arena */
extern vmem_t *zio_alloc_arena; /* arena for zio caches */
@ -62,15 +61,8 @@ extern vmem_t *zio_arena; /* arena for allocating zio memory */
#define VMEM_ALLOC 0x01
#define VMEM_FREE 0x02
static __inline__ size_t
vmem_size(vmem_t *vmp, int typemask)
{
/* Arena's unsupported */
ASSERT(vmp == NULL);
ASSERT(typemask & (VMEM_ALLOC | VMEM_FREE));
return 0;
}
extern pgcnt_t spl_kmem_availrmem(void);
extern size_t vmem_size(vmem_t *vmp, int typemask);
#define xcopyin(from, to, size) copy_from_user(to, from, size)
#define xcopyout(from, to, size) copy_to_user(to, from, size)

View File

@ -64,18 +64,12 @@ EXPORT_SYMBOL(lotsfree);
pgcnt_t needfree = 0;
EXPORT_SYMBOL(needfree);
pgcnt_t swapfs_desfree = 0;
EXPORT_SYMBOL(swapfs_desfree);
pgcnt_t swapfs_minfree = 0;
EXPORT_SYMBOL(swapfs_minfree);
pgcnt_t swapfs_reserve = 0;
EXPORT_SYMBOL(swapfs_reserve);
pgcnt_t availrmem = 0;
EXPORT_SYMBOL(availrmem);
vmem_t *heap_arena = NULL;
EXPORT_SYMBOL(heap_arena);
@ -86,14 +80,17 @@ vmem_t *zio_arena = NULL;
EXPORT_SYMBOL(zio_arena);
#ifndef HAVE_FIRST_ONLINE_PGDAT
struct pglist_data *first_online_pgdat(void)
struct pglist_data *
first_online_pgdat(void)
{
return NODE_DATA(first_online_node);
}
EXPORT_SYMBOL(first_online_pgdat);
#endif /* HAVE_FIRST_ONLINE_PGDAT */
#ifndef HAVE_NEXT_ONLINE_PGDAT
struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
struct pglist_data *
next_online_pgdat(struct pglist_data *pgdat)
{
int nid = next_online_node(pgdat->node_id);
@ -102,10 +99,12 @@ struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
return NODE_DATA(nid);
}
EXPORT_SYMBOL(next_online_pgdat);
#endif /* HAVE_NEXT_ONLINE_PGDAT */
#ifndef HAVE_NEXT_ZONE
struct zone *next_zone(struct zone *zone)
struct zone *
next_zone(struct zone *zone)
{
pg_data_t *pgdat = zone->zone_pgdat;
@ -120,8 +119,73 @@ struct zone *next_zone(struct zone *zone)
}
return zone;
}
EXPORT_SYMBOL(next_zone);
#endif /* HAVE_NEXT_ZONE */
#ifndef HAVE_GET_ZONE_COUNTS
void
__get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free, struct pglist_data *pgdat)
{
struct zone *zones = pgdat->node_zones;
int i;
*active = 0;
*inactive = 0;
*free = 0;
for (i = 0; i < MAX_NR_ZONES; i++) {
*active += zones[i].nr_active;
*inactive += zones[i].nr_inactive;
*free += zones[i].free_pages;
}
}
void
get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free)
{
struct pglist_data *pgdat;
*active = 0;
*inactive = 0;
*free = 0;
for_each_online_pgdat(pgdat) {
unsigned long l, m, n;
__get_zone_counts(&l, &m, &n, pgdat);
*active += l;
*inactive += m;
*free += n;
}
}
EXPORT_SYMBOL(get_zone_counts);
#endif /* HAVE_GET_ZONE_COUNTS */
pgcnt_t
spl_kmem_availrmem(void)
{
unsigned long active;
unsigned long inactive;
unsigned long free;
get_zone_counts(&active, &inactive, &free);
/* The amount of easily available memory */
return free + inactive;
}
EXPORT_SYMBOL(spl_kmem_availrmem);
size_t
vmem_size(vmem_t *vmp, int typemask)
{
/* Arena's unsupported */
ASSERT(vmp == NULL);
ASSERT(typemask & (VMEM_ALLOC | VMEM_FREE));
return 0;
}
EXPORT_SYMBOL(vmem_size);
/*
* Memory allocation interfaces and debugging for basic kmem_*
* and vmem_* style memory allocation. When DEBUG_KMEM is enable
@ -1707,6 +1771,10 @@ spl_kmem_init_globals(void)
desfree += zone->pages_low;
lotsfree += zone->pages_high;
}
/* Solaris default values */
swapfs_minfree = MAX(2*1024*1024 / PAGE_SIZE, physmem / 8);
swapfs_reserve = MIN(4*1024*1024 / PAGE_SIZE, physmem / 16);
}
int

View File

@ -91,9 +91,10 @@ struct proc_dir_entry *proc_spl_kstat = NULL;
#define CTL_VM_LOTSFREE CTL_UNNUMBERED /* Lots of free memory */
#define CTL_VM_NEEDFREE CTL_UNNUMBERED /* Need free memory */
#define CTL_VM_SWAPFS_MINFREE CTL_UNNUMBERED /* Minimum swapfs memory */
#define CTL_VM_SWAPFS_DESFREE CTL_UNNUMBERED /* Desired swapfs memory */
#define CTL_VM_SWAPFS_RESERVE CTL_UNNUMBERED /* Reserved swapfs memory */
#define CTL_VM_AVAILRMEM CTL_UNNUMBERED /* Available reserved memory */
#define CTL_VM_AVAILRMEM CTL_UNNUMBERED /* Easily available memory */
#define CTL_VM_FREEMEM CTL_UNNUMBERED /* Free memory */
#define CTL_VM_PHYSMEM CTL_UNNUMBERED /* Total physical memory */
#ifdef DEBUG_KMEM
#define CTL_KMEM_KMEMUSED CTL_UNNUMBERED /* Alloc'd kmem bytes */
@ -145,9 +146,10 @@ enum {
CTL_VM_LOTSFREE, /* Lots of free memory threshold */
CTL_VM_NEEDFREE, /* Need free memory deficit */
CTL_VM_SWAPFS_MINFREE, /* Minimum swapfs memory */
CTL_VM_SWAPFS_DESFREE, /* Desired swapfs memory */
CTL_VM_SWAPFS_RESERVE, /* Reserved swapfs memory */
CTL_VM_AVAILRMEM, /* Available reserved memory */
CTL_VM_AVAILRMEM, /* Easily available memory */
CTL_VM_FREEMEM, /* Free memory */
CTL_VM_PHYSMEM, /* Total physical memory */
#ifdef DEBUG_KMEM
CTL_KMEM_KMEMUSED, /* Alloc'd kmem bytes */
@ -486,6 +488,58 @@ proc_dohostid(struct ctl_table *table, int write, struct file *filp,
RETURN(rc);
}
static int
proc_doavailrmem(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int len, rc = 0;
char str[32];
ENTRY;
if (write) {
*ppos += *lenp;
} else {
len = snprintf(str, sizeof(str), "%lu", (unsigned long)availrmem);
if (*ppos >= len)
rc = 0;
else
rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
if (rc >= 0) {
*lenp = rc;
*ppos += rc;
}
}
RETURN(rc);
}
static int
proc_dofreemem(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int len, rc = 0;
char str[32];
ENTRY;
if (write) {
*ppos += *lenp;
} else {
len = snprintf(str, sizeof(str), "%lu", (unsigned long)freemem);
if (*ppos >= len)
rc = 0;
else
rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
if (rc >= 0) {
*lenp = rc;
*ppos += rc;
}
}
RETURN(rc);
}
#ifdef DEBUG_MUTEX
static void
mutex_seq_show_headers(struct seq_file *f)
@ -832,14 +886,6 @@ static struct ctl_table spl_vm_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_VM_SWAPFS_DESFREE,
.procname = "swapfs_desfree",
.data = &swapfs_desfree,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_VM_SWAPFS_RESERVE,
.procname = "swapfs_reserve",
@ -851,7 +897,21 @@ static struct ctl_table spl_vm_table[] = {
{
.ctl_name = CTL_VM_AVAILRMEM,
.procname = "availrmem",
.data = &availrmem,
.mode = 0444,
.proc_handler = &proc_doavailrmem,
},
{
.ctl_name = CTL_VM_FREEMEM,
.procname = "freemem",
.data = (void *)2,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dofreemem,
},
{
.ctl_name = CTL_VM_PHYSMEM,
.procname = "physmem",
.data = &physmem,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,

View File

@ -51,6 +51,9 @@
/* fls64() is available */
#undef HAVE_FLS64
/* get_zone_counts() is available */
#undef HAVE_GET_ZONE_COUNTS
/* init_utsname() is available */
#undef HAVE_INIT_UTSNAME