mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
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:
+77
-9
@@ -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
|
||||
|
||||
+73
-13
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user