-/*
- * This file is part of the SPL: Solaris Porting Layer.
- *
- * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
- * Produced at Lawrence Livermore National Laboratory
- * Written by:
- * Brian Behlendorf <behlendorf1@llnl.gov>,
- * Herb Wartens <wartens2@llnl.gov>,
- * Jim Garlick <garlick@llnl.gov>
+/*****************************************************************************\
+ * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
+ * Copyright (C) 2007 The Regents of the University of California.
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
* UCRL-CODE-235197
*
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This file is part of the SPL, Solaris Porting Layer.
+ * For details, see <http://github.com/behlendorf/spl/>.
+ *
+ * The SPL is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*
- * This is distributed in the hope that it will be useful, but WITHOUT
+ * The SPL is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <sys/proc.h>
-
-#ifdef DEBUG_SUBSYSTEM
-#undef DEBUG_SUBSYSTEM
+ * with the SPL. If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************
+ * Solaris Porting Layer (SPL) Proc Implementation.
+\*****************************************************************************/
+
+#include <sys/systeminfo.h>
+#include <sys/kstat.h>
+#include <linux/kmod.h>
+#include <linux/seq_file.h>
+#include <linux/proc_compat.h>
+#include <spl-debug.h>
+
+#ifdef SS_DEBUG_SUBSYS
+#undef SS_DEBUG_SUBSYS
#endif
-#define DEBUG_SUBSYSTEM S_PROC
+#define SS_DEBUG_SUBSYS SS_PROC
#ifdef DEBUG_KMEM
static unsigned long table_min = 0;
static struct ctl_table_header *spl_header = NULL;
#endif /* CONFIG_SYSCTL */
-#if defined(DEBUG_MUTEX) || defined(DEBUG_KMEM) || defined(DEBUG_KSTAT)
static struct proc_dir_entry *proc_spl = NULL;
-#ifdef DEBUG_MUTEX
-static struct proc_dir_entry *proc_spl_mutex = NULL;
-static struct proc_dir_entry *proc_spl_mutex_stats = NULL;
-#endif /* DEBUG_MUTEX */
#ifdef DEBUG_KMEM
static struct proc_dir_entry *proc_spl_kmem = NULL;
static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
#endif /* DEBUG_KMEM */
-#ifdef DEBUG_KSTAT
struct proc_dir_entry *proc_spl_kstat = NULL;
-#endif /* DEBUG_KSTAT */
-#endif /* DEBUG_MUTEX || DEBUG_KMEM || DEBUG_KSTAT */
+#ifdef HAVE_CTL_NAME
#ifdef HAVE_CTL_UNNUMBERED
#define CTL_SPL CTL_UNNUMBERED
#define CTL_SPL_DEBUG CTL_UNNUMBERED
+#define CTL_SPL_VM CTL_UNNUMBERED
#define CTL_SPL_MUTEX CTL_UNNUMBERED
#define CTL_SPL_KMEM CTL_UNNUMBERED
#define CTL_SPL_KSTAT CTL_UNNUMBERED
#define CTL_VERSION CTL_UNNUMBERED /* Version */
#define CTL_HOSTID CTL_UNNUMBERED /* Host id by /usr/bin/hostid */
#define CTL_HW_SERIAL CTL_UNNUMBERED /* HW serial number by hostid */
+#define CTL_KALLSYMS CTL_UNNUMBERED /* kallsyms_lookup_name addr */
#define CTL_DEBUG_SUBSYS CTL_UNNUMBERED /* Debug subsystem */
#define CTL_DEBUG_MASK CTL_UNNUMBERED /* Debug mask */
#define CTL_CONSOLE_MIN_DELAY_CS CTL_UNNUMBERED /* Init delay skip messages */
#define CTL_CONSOLE_BACKOFF CTL_UNNUMBERED /* Delay increase factor */
+#define CTL_VM_MINFREE CTL_UNNUMBERED /* Minimum free memory */
+#define CTL_VM_DESFREE CTL_UNNUMBERED /* Desired free memory */
+#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_RESERVE CTL_UNNUMBERED /* Reserved swapfs 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 */
#define CTL_KMEM_KMEMMAX CTL_UNNUMBERED /* Max alloc'd by kmem bytes */
#define CTL_KMEM_ALLOC_FAILED CTL_UNNUMBERED /* Cache allocations failed */
#endif
-#define CTL_MUTEX_STATS CTL_UNNUMBERED /* Global mutex statistics */
-#define CTL_MUTEX_STATS_PER CTL_UNNUMBERED /* Per mutex statistics */
-#define CTL_MUTEX_SPIN_MAX CTL_UNNUMBERED /* Max mutex spin iterations */
-
#else /* HAVE_CTL_UNNUMBERED */
-#define CTL_SPL 0x87
-#define CTL_SPL_DEBUG 0x88
-#define CTL_SPL_MUTEX 0x89
-#define CTL_SPL_KMEM 0x90
-#define CTL_SPL_KSTAT 0x91
+enum {
+ CTL_SPL = 0x87,
+ CTL_SPL_DEBUG = 0x88,
+ CTL_SPL_VM = 0x89,
+ CTL_SPL_MUTEX = 0x90,
+ CTL_SPL_KMEM = 0x91,
+ CTL_SPL_KSTAT = 0x92,
+};
enum {
- CTL_VERSION = 1, /* Version */
- CTL_HOSTID, /* Host id reported by /usr/bin/hostid */
- CTL_HW_SERIAL, /* Hardware serial number from hostid */
-
- CTL_DEBUG_SUBSYS, /* Debug subsystem */
- CTL_DEBUG_MASK, /* Debug mask */
- CTL_DEBUG_PRINTK, /* Force all messages to console */
- CTL_DEBUG_MB, /* Debug buffer size */
- CTL_DEBUG_BINARY, /* Include binary data in buffer */
- CTL_DEBUG_CATASTROPHE, /* Set if we have BUG'd or panic'd */
- CTL_DEBUG_PANIC_ON_BUG, /* Set if we should panic on BUG */
- CTL_DEBUG_PATH, /* Dump log location */
- CTL_DEBUG_DUMP, /* Dump debug buffer to file */
- CTL_DEBUG_FORCE_BUG, /* Hook to force a BUG */
- CTL_DEBUG_STACK_SIZE, /* Max observed stack size */
-
- CTL_CONSOLE_RATELIMIT, /* Ratelimit console messages */
- CTL_CONSOLE_MAX_DELAY_CS, /* Max delay at which we skip messages */
- CTL_CONSOLE_MIN_DELAY_CS, /* Init delay at which we skip messages */
- CTL_CONSOLE_BACKOFF, /* Delay increase factor */
+ CTL_VERSION = 1, /* Version */
+ CTL_HOSTID, /* Host id reported by /usr/bin/hostid */
+ CTL_HW_SERIAL, /* Hardware serial number from hostid */
+ CTL_KALLSYMS, /* Address of kallsyms_lookup_name */
+
+ CTL_DEBUG_SUBSYS, /* Debug subsystem */
+ CTL_DEBUG_MASK, /* Debug mask */
+ CTL_DEBUG_PRINTK, /* Force all messages to console */
+ CTL_DEBUG_MB, /* Debug buffer size */
+ CTL_DEBUG_BINARY, /* Include binary data in buffer */
+ CTL_DEBUG_CATASTROPHE, /* Set if we have BUG'd or panic'd */
+ CTL_DEBUG_PANIC_ON_BUG, /* Set if we should panic on BUG */
+ CTL_DEBUG_PATH, /* Dump log location */
+ CTL_DEBUG_DUMP, /* Dump debug buffer to file */
+ CTL_DEBUG_FORCE_BUG, /* Hook to force a BUG */
+ CTL_DEBUG_STACK_SIZE, /* Max observed stack size */
+
+ CTL_CONSOLE_RATELIMIT, /* Ratelimit console messages */
+ CTL_CONSOLE_MAX_DELAY_CS, /* Max delay which we skip messages */
+ CTL_CONSOLE_MIN_DELAY_CS, /* Init delay which we skip messages */
+ CTL_CONSOLE_BACKOFF, /* Delay increase factor */
+
+ CTL_VM_MINFREE, /* Minimum free memory threshold */
+ CTL_VM_DESFREE, /* Desired free memory threshold */
+ 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_RESERVE, /* Reserved swapfs 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 */
- CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
- CTL_KMEM_VMEMUSED, /* Alloc'd vmem bytes */
- CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
+ CTL_KMEM_KMEMUSED, /* Alloc'd kmem bytes */
+ CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
+ CTL_KMEM_VMEMUSED, /* Alloc'd vmem bytes */
+ CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
#endif
-
- CTL_MUTEX_STATS, /* Global mutex statistics */
- CTL_MUTEX_STATS_PER, /* Per mutex statistics */
- CTL_MUTEX_SPIN_MAX, /* Maximum mutex spin iterations */
};
#endif /* HAVE_CTL_UNNUMBERED */
+#endif /* HAVE_CTL_NAME */
static int
proc_copyin_string(char *kbuffer, int kbuffer_size,
return size;
}
-static int
-proc_dobitmasks(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_dobitmasks)
{
unsigned long *mask = table->data;
int is_subsys = (mask == &spl_debug_subsys) ? 1 : 0;
int is_printk = (mask == &spl_debug_printk) ? 1 : 0;
int size = 512, rc;
char *str;
- ENTRY;
+ SENTRY;
str = kmem_alloc(size, KM_SLEEP);
if (str == NULL)
- RETURN(-ENOMEM);
+ SRETURN(-ENOMEM);
if (write) {
rc = proc_copyin_string(str, size, buffer, *lenp);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
rc = spl_debug_str2mask(mask, str, is_subsys);
/* Always print BUG/ASSERT to console, so keep this mask */
if (is_printk)
- *mask |= D_EMERG;
+ *mask |= SD_EMERG;
*ppos += *lenp;
} else {
}
kmem_free(str, size);
- RETURN(rc);
+ SRETURN(rc);
}
-static int
-proc_debug_mb(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_debug_mb)
{
char str[32];
int rc, len;
- ENTRY;
+ SENTRY;
if (write) {
rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
rc = spl_debug_set_mb(simple_strtoul(str, NULL, 0));
*ppos += *lenp;
if (*ppos >= len)
rc = 0;
else
- rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
+ rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
if (rc >= 0) {
*lenp = rc;
}
}
- RETURN(rc);
+ SRETURN(rc);
}
-static int
-proc_dump_kernel(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_dump_kernel)
{
- ENTRY;
+ SENTRY;
if (write) {
spl_debug_dumplog(0);
*lenp = 0;
}
- RETURN(0);
+ SRETURN(0);
}
-static int
-proc_force_bug(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_force_bug)
{
- ENTRY;
+ SENTRY;
- if (write) {
- CERROR("Crashing due to forced SBUG\n");
- SBUG();
- /* Unreachable */
- } else {
+ if (write)
+ PANIC("Crashing due to forced panic\n");
+ else
*lenp = 0;
- }
- RETURN(0);
+ SRETURN(0);
}
-static int
-proc_console_max_delay_cs(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_console_max_delay_cs)
{
int rc, max_delay_cs;
struct ctl_table dummy = *table;
long d;
- ENTRY;
+ SENTRY;
dummy.data = &max_delay_cs;
dummy.proc_handler = &proc_dointvec;
if (write) {
max_delay_cs = 0;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
if (max_delay_cs <= 0)
- RETURN(-EINVAL);
+ SRETURN(-EINVAL);
d = (max_delay_cs * HZ) / 100;
if (d == 0 || d < spl_console_min_delay)
- RETURN(-EINVAL);
+ SRETURN(-EINVAL);
spl_console_max_delay = d;
} else {
max_delay_cs = (spl_console_max_delay * 100) / HZ;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
}
- RETURN(rc);
+ SRETURN(rc);
}
-static int
-proc_console_min_delay_cs(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_console_min_delay_cs)
{
int rc, min_delay_cs;
struct ctl_table dummy = *table;
long d;
- ENTRY;
+ SENTRY;
dummy.data = &min_delay_cs;
dummy.proc_handler = &proc_dointvec;
if (write) {
min_delay_cs = 0;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
if (min_delay_cs <= 0)
- RETURN(-EINVAL);
+ SRETURN(-EINVAL);
d = (min_delay_cs * HZ) / 100;
if (d == 0 || d > spl_console_max_delay)
- RETURN(-EINVAL);
+ SRETURN(-EINVAL);
spl_console_min_delay = d;
} else {
min_delay_cs = (spl_console_min_delay * 100) / HZ;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
}
- RETURN(rc);
+ SRETURN(rc);
}
-static int
-proc_console_backoff(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_console_backoff)
{
int rc, backoff;
struct ctl_table dummy = *table;
- ENTRY;
+ SENTRY;
dummy.data = &backoff;
dummy.proc_handler = &proc_dointvec;
if (write) {
backoff = 0;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
if (backoff <= 0)
- RETURN(-EINVAL);
+ SRETURN(-EINVAL);
spl_console_backoff = backoff;
} else {
backoff = spl_console_backoff;
- rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+ rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
}
- RETURN(rc);
+ SRETURN(rc);
}
#ifdef DEBUG_KMEM
-static int
-proc_doatomic64(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_domemused)
{
int rc = 0;
unsigned long min = 0, max = ~0, val;
struct ctl_table dummy = *table;
- ENTRY;
+ SENTRY;
dummy.data = &val;
dummy.proc_handler = &proc_dointvec;
if (write) {
*ppos += *lenp;
} else {
+# ifdef HAVE_ATOMIC64_T
val = atomic64_read((atomic64_t *)table->data);
- rc = proc_doulongvec_minmax(&dummy, write, filp,
- buffer, lenp, ppos);
+# else
+ val = atomic_read((atomic_t *)table->data);
+# endif /* HAVE_ATOMIC64_T */
+ rc = spl_proc_doulongvec_minmax(&dummy, write, filp,
+ buffer, lenp, ppos);
}
- RETURN(rc);
+ SRETURN(rc);
}
#endif /* DEBUG_KMEM */
-static int
-proc_dohostid(struct ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+SPL_PROC_HANDLER(proc_dohostid)
{
int len, rc = 0;
int32_t val;
char *end, str[32];
- ENTRY;
+ SENTRY;
if (write) {
- /* We can't use proc_doulongvec_minmax() in the write
- * case hear because hostid while a hex value has no
- * leading 0x which confuses the helper function. */
+ /* We can't use spl_proc_doulongvec_minmax() in the write
+ * case hear because hostid while a hex value has no
+ * leading 0x which confuses the helper function. */
rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
if (rc < 0)
- RETURN(rc);
+ SRETURN(rc);
val = simple_strtol(str, &end, 16);
- if (str == end)
- RETURN(-EINVAL);
+ if (str == end)
+ SRETURN(-EINVAL);
- spl_hostid = (long)val;
- (void)snprintf(hw_serial, 11, "%u", (val >= 0) ? val : -val);
+ spl_hostid = (long) val;
+ (void) snprintf(hw_serial, HW_HOSTID_LEN, "%u",
+ (val >= 0) ? val : -val);
+ hw_serial[HW_HOSTID_LEN - 1] = '\0';
*ppos += *lenp;
} else {
len = snprintf(str, sizeof(str), "%lx", spl_hostid);
if (*ppos >= len)
rc = 0;
else
- rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
+ rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
if (rc >= 0) {
*lenp = rc;
}
}
- RETURN(rc);
-}
-
-#ifdef DEBUG_MUTEX
-static void
-mutex_seq_show_headers(struct seq_file *f)
-{
- seq_printf(f, "%-36s %-4s %-16s\t"
- "e_tot\te_nh\te_sp\te_sl\tte_tot\tte_nh\n",
- "name", "type", "owner");
+ SRETURN(rc);
}
-static int
-mutex_seq_show(struct seq_file *f, void *p)
+#ifndef HAVE_KALLSYMS_LOOKUP_NAME
+SPL_PROC_HANDLER(proc_dokallsyms_lookup_name)
{
- kmutex_t *mp = p;
- char t = 'X';
- int i;
-
- ASSERT(mp->km_magic == KM_MAGIC);
-
- switch (mp->km_type) {
- case MUTEX_DEFAULT: t = 'D'; break;
- case MUTEX_SPIN: t = 'S'; break;
- case MUTEX_ADAPTIVE: t = 'A'; break;
- default:
- SBUG();
- }
- seq_printf(f, "%-36s %c ", mp->km_name, t);
- if (mp->km_owner)
- seq_printf(f, "%p\t", mp->km_owner);
- else
- seq_printf(f, "%-16s\t", "<not held>");
+ int len, rc = 0;
+ char *end, str[32];
+ SENTRY;
- for (i = 0; i < MUTEX_STATS_SIZE; i++)
- seq_printf(f, "%d%c", mp->km_stats[i],
- (i + 1 == MUTEX_STATS_SIZE) ? '\n' : '\t');
+ if (write) {
+ /* This may only be set once at module load time */
+ if (spl_kallsyms_lookup_name_fn != SYMBOL_POISON)
+ SRETURN(-EEXIST);
- return 0;
-}
+ /* We can't use spl_proc_doulongvec_minmax() in the write
+ * case hear because the address while a hex value has no
+ * leading 0x which confuses the helper function. */
+ rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
+ if (rc < 0)
+ SRETURN(rc);
-static void *
-mutex_seq_start(struct seq_file *f, loff_t *pos)
-{
- struct list_head *p;
- loff_t n = *pos;
- ENTRY;
+ spl_kallsyms_lookup_name_fn =
+ (kallsyms_lookup_name_t)simple_strtoul(str, &end, 16);
+ if (str == end)
+ SRETURN(-EINVAL);
- spin_lock(&mutex_stats_lock);
- if (!n)
- mutex_seq_show_headers(f);
+ *ppos += *lenp;
+ } else {
+ len = snprintf(str, sizeof(str), "%lx",
+ (unsigned long)spl_kallsyms_lookup_name_fn);
+ if (*ppos >= len)
+ rc = 0;
+ else
+ rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
- p = mutex_stats_list.next;
- while (n--) {
- p = p->next;
- if (p == &mutex_stats_list)
- RETURN(NULL);
+ if (rc >= 0) {
+ *lenp = rc;
+ *ppos += rc;
+ }
}
- RETURN(list_entry(p, kmutex_t, km_list));
+ SRETURN(rc);
}
+#endif /* HAVE_KALLSYMS_LOOKUP_NAME */
-static void *
-mutex_seq_next(struct seq_file *f, void *p, loff_t *pos)
+SPL_PROC_HANDLER(proc_doavailrmem)
{
- kmutex_t *mp = p;
- ENTRY;
+ int len, rc = 0;
+ char str[32];
+ SENTRY;
- ++*pos;
- RETURN((mp->km_list.next == &mutex_stats_list) ?
- NULL : list_entry(mp->km_list.next, kmutex_t, km_list));
+ 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;
+ }
+ }
+
+ SRETURN(rc);
}
-static void
-mutex_seq_stop(struct seq_file *f, void *v)
+SPL_PROC_HANDLER(proc_dofreemem)
{
- spin_unlock(&mutex_stats_lock);
-}
+ int len, rc = 0;
+ char str[32];
+ SENTRY;
-static struct seq_operations mutex_seq_ops = {
- .show = mutex_seq_show,
- .start = mutex_seq_start,
- .next = mutex_seq_next,
- .stop = mutex_seq_stop,
-};
+ 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;
+ }
+ }
-static int
-proc_mutex_open(struct inode *inode, struct file *filp)
-{
- return seq_open(filp, &mutex_seq_ops);
+ SRETURN(rc);
}
-static struct file_operations proc_mutex_operations = {
- .open = proc_mutex_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-#endif /* DEBUG_MUTEX */
-
#ifdef DEBUG_KMEM
static void
slab_seq_show_headers(struct seq_file *f)
{
- seq_printf(f, "%-36s\n", "name");
+ seq_printf(f,
+ "--------------------- cache ----------"
+ "--------------------------------------------- "
+ "----- slab ------ "
+ "---- object -----\n");
+ seq_printf(f,
+ "name "
+ " flags size alloc slabsize objsize "
+ "total alloc max "
+ "total alloc max\n");
}
static int
slab_seq_show(struct seq_file *f, void *p)
{
- spl_kmem_cache_t *skc = p;
-
- ASSERT(skc->skc_magic == SKC_MAGIC);
-
- spin_lock(&skc->skc_lock);
- seq_printf(f, "%-36s ", skc->skc_name);
- seq_printf(f, "%u %u %u - %lu %lu %lu - %lu %lu %lu - %lu %lu %lu\n",
- (unsigned)skc->skc_obj_size,
- (unsigned)skc->skc_slab_objs,
- (unsigned)skc->skc_slab_size,
- (long unsigned)skc->skc_slab_fail,
- (long unsigned)skc->skc_slab_create,
- (long unsigned)skc->skc_slab_destroy,
- (long unsigned)skc->skc_slab_total,
- (long unsigned)skc->skc_slab_alloc,
- (long unsigned)skc->skc_slab_max,
- (long unsigned)skc->skc_obj_total,
- (long unsigned)skc->skc_obj_alloc,
- (long unsigned)skc->skc_obj_max);
-
- spin_unlock(&skc->skc_lock);
+ spl_kmem_cache_t *skc = p;
+
+ ASSERT(skc->skc_magic == SKC_MAGIC);
+
+ spin_lock(&skc->skc_lock);
+ seq_printf(f, "%-36s ", skc->skc_name);
+ seq_printf(f, "0x%05lx %9lu %9lu %8u %8u "
+ "%5lu %5lu %5lu %5lu %5lu %5lu\n",
+ (long unsigned)skc->skc_flags,
+ (long unsigned)(skc->skc_slab_size * skc->skc_slab_total),
+ (long unsigned)(skc->skc_obj_size * skc->skc_obj_alloc),
+ (unsigned)skc->skc_slab_size,
+ (unsigned)skc->skc_obj_size,
+ (long unsigned)skc->skc_slab_total,
+ (long unsigned)skc->skc_slab_alloc,
+ (long unsigned)skc->skc_slab_max,
+ (long unsigned)skc->skc_obj_total,
+ (long unsigned)skc->skc_obj_alloc,
+ (long unsigned)skc->skc_obj_max);
+
+ spin_unlock(&skc->skc_lock);
return 0;
}
{
struct list_head *p;
loff_t n = *pos;
- ENTRY;
+ SENTRY;
down_read(&spl_kmem_cache_sem);
if (!n)
while (n--) {
p = p->next;
if (p == &spl_kmem_cache_list)
- RETURN(NULL);
+ SRETURN(NULL);
}
- RETURN(list_entry(p, spl_kmem_cache_t, skc_list));
+ SRETURN(list_entry(p, spl_kmem_cache_t, skc_list));
}
static void *
slab_seq_next(struct seq_file *f, void *p, loff_t *pos)
{
spl_kmem_cache_t *skc = p;
- ENTRY;
+ SENTRY;
++*pos;
- RETURN((skc->skc_list.next == &spl_kmem_cache_list) ?
- NULL : list_entry(skc->skc_list.next, spl_kmem_cache_t, skc_list));
+ SRETURN((skc->skc_list.next == &spl_kmem_cache_list) ?
+ NULL : list_entry(skc->skc_list.next,spl_kmem_cache_t,skc_list));
}
static void
static struct ctl_table spl_debug_table[] = {
{
- .ctl_name = CTL_DEBUG_SUBSYS,
+ CTL_NAME (CTL_DEBUG_SUBSYS)
.procname = "subsystem",
.data = &spl_debug_subsys,
.maxlen = sizeof(unsigned long),
.proc_handler = &proc_dobitmasks
},
{
- .ctl_name = CTL_DEBUG_MASK,
+ CTL_NAME (CTL_DEBUG_MASK)
.procname = "mask",
.data = &spl_debug_mask,
.maxlen = sizeof(unsigned long),
.proc_handler = &proc_dobitmasks
},
{
- .ctl_name = CTL_DEBUG_PRINTK,
+ CTL_NAME (CTL_DEBUG_PRINTK)
.procname = "printk",
.data = &spl_debug_printk,
.maxlen = sizeof(unsigned long),
.proc_handler = &proc_dobitmasks
},
{
- .ctl_name = CTL_DEBUG_MB,
+ CTL_NAME (CTL_DEBUG_MB)
.procname = "mb",
.mode = 0644,
.proc_handler = &proc_debug_mb,
},
{
- .ctl_name = CTL_DEBUG_BINARY,
+ CTL_NAME (CTL_DEBUG_BINARY)
.procname = "binary",
.data = &spl_debug_binary,
.maxlen = sizeof(int),
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_DEBUG_CATASTROPHE,
+ CTL_NAME (CTL_DEBUG_CATASTROPHE)
.procname = "catastrophe",
.data = &spl_debug_catastrophe,
.maxlen = sizeof(int),
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_DEBUG_PANIC_ON_BUG,
+ CTL_NAME (CTL_DEBUG_PANIC_ON_BUG)
.procname = "panic_on_bug",
.data = &spl_debug_panic_on_bug,
.maxlen = sizeof(int),
.proc_handler = &proc_dointvec
},
{
- .ctl_name = CTL_DEBUG_PATH,
+ CTL_NAME (CTL_DEBUG_PATH)
.procname = "path",
.data = spl_debug_file_path,
.maxlen = sizeof(spl_debug_file_path),
.proc_handler = &proc_dostring,
},
{
- .ctl_name = CTL_DEBUG_DUMP,
+ CTL_NAME (CTL_DEBUG_DUMP)
.procname = "dump",
.mode = 0200,
.proc_handler = &proc_dump_kernel,
},
- { .ctl_name = CTL_DEBUG_FORCE_BUG,
+ { CTL_NAME (CTL_DEBUG_FORCE_BUG)
.procname = "force_bug",
.mode = 0200,
.proc_handler = &proc_force_bug,
},
{
- .ctl_name = CTL_CONSOLE_RATELIMIT,
+ CTL_NAME (CTL_CONSOLE_RATELIMIT)
.procname = "console_ratelimit",
.data = &spl_console_ratelimit,
.maxlen = sizeof(int),
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_CONSOLE_MAX_DELAY_CS,
+ CTL_NAME (CTL_CONSOLE_MAX_DELAY_CS)
.procname = "console_max_delay_centisecs",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_console_max_delay_cs,
},
{
- .ctl_name = CTL_CONSOLE_MIN_DELAY_CS,
+ CTL_NAME (CTL_CONSOLE_MIN_DELAY_CS)
.procname = "console_min_delay_centisecs",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_console_min_delay_cs,
},
{
- .ctl_name = CTL_CONSOLE_BACKOFF,
+ CTL_NAME (CTL_CONSOLE_BACKOFF)
.procname = "console_backoff",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_console_backoff,
},
{
- .ctl_name = CTL_DEBUG_STACK_SIZE,
+ CTL_NAME (CTL_DEBUG_STACK_SIZE)
.procname = "stack_max",
.data = &spl_debug_stack,
.maxlen = sizeof(int),
{0},
};
-#ifdef DEBUG_MUTEX
-static struct ctl_table spl_mutex_table[] = {
+static struct ctl_table spl_vm_table[] = {
+ {
+ CTL_NAME (CTL_VM_MINFREE)
+ .procname = "minfree",
+ .data = &minfree,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ CTL_NAME (CTL_VM_DESFREE)
+ .procname = "desfree",
+ .data = &desfree,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ CTL_NAME (CTL_VM_LOTSFREE)
+ .procname = "lotsfree",
+ .data = &lotsfree,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
{
- .ctl_name = CTL_MUTEX_STATS,
- .procname = "stats",
- .data = &mutex_stats,
- .maxlen = sizeof(int) * MUTEX_STATS_SIZE,
+ CTL_NAME (CTL_VM_NEEDFREE)
+ .procname = "needfree",
+ .data = &needfree,
+ .maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_MUTEX_SPIN_MAX,
- .procname = "spin_max",
- .data = &mutex_spin_max,
+ CTL_NAME (CTL_VM_SWAPFS_MINFREE)
+ .procname = "swapfs_minfree",
+ .data = &swapfs_minfree,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ CTL_NAME (CTL_VM_SWAPFS_RESERVE)
+ .procname = "swapfs_reserve",
+ .data = &swapfs_reserve,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ CTL_NAME (CTL_VM_AVAILRMEM)
+ .procname = "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,
+ },
{0},
};
-#endif /* DEBUG_MUTEX */
#ifdef DEBUG_KMEM
static struct ctl_table spl_kmem_table[] = {
{
- .ctl_name = CTL_KMEM_KMEMUSED,
+ CTL_NAME (CTL_KMEM_KMEMUSED)
.procname = "kmem_used",
.data = &kmem_alloc_used,
+# ifdef HAVE_ATOMIC64_T
.maxlen = sizeof(atomic64_t),
+# else
+ .maxlen = sizeof(atomic_t),
+# endif /* HAVE_ATOMIC64_T */
.mode = 0444,
- .proc_handler = &proc_doatomic64,
+ .proc_handler = &proc_domemused,
},
{
- .ctl_name = CTL_KMEM_KMEMMAX,
+ CTL_NAME (CTL_KMEM_KMEMMAX)
.procname = "kmem_max",
.data = &kmem_alloc_max,
.maxlen = sizeof(unsigned long),
.proc_handler = &proc_doulongvec_minmax,
},
{
- .ctl_name = CTL_KMEM_VMEMUSED,
+ CTL_NAME (CTL_KMEM_VMEMUSED)
.procname = "vmem_used",
.data = &vmem_alloc_used,
+# ifdef HAVE_ATOMIC64_T
.maxlen = sizeof(atomic64_t),
+# else
+ .maxlen = sizeof(atomic_t),
+# endif /* HAVE_ATOMIC64_T */
.mode = 0444,
- .proc_handler = &proc_doatomic64,
+ .proc_handler = &proc_domemused,
},
{
- .ctl_name = CTL_KMEM_VMEMMAX,
+ CTL_NAME (CTL_KMEM_VMEMMAX)
.procname = "vmem_max",
.data = &vmem_alloc_max,
.maxlen = sizeof(unsigned long),
};
#endif /* DEBUG_KMEM */
-#ifdef DEBUG_KSTAT
static struct ctl_table spl_kstat_table[] = {
{0},
};
-#endif /* DEBUG_KSTAT */
static struct ctl_table spl_table[] = {
/* NB No .strategy entries have been provided since
* sysctl(8) prefers to go via /proc for portability.
*/
{
- .ctl_name = CTL_VERSION,
+ CTL_NAME (CTL_VERSION)
.procname = "version",
.data = spl_version,
.maxlen = sizeof(spl_version),
.proc_handler = &proc_dostring,
},
{
- .ctl_name = CTL_HOSTID,
+ CTL_NAME (CTL_HOSTID)
.procname = "hostid",
.data = &spl_hostid,
.maxlen = sizeof(unsigned long),
.proc_handler = &proc_dohostid,
},
{
- .ctl_name = CTL_HW_SERIAL,
+ CTL_NAME (CTL_HW_SERIAL)
.procname = "hw_serial",
.data = hw_serial,
.maxlen = sizeof(hw_serial),
.mode = 0444,
.proc_handler = &proc_dostring,
},
+#ifndef HAVE_KALLSYMS_LOOKUP_NAME
+ {
+ CTL_NAME (CTL_KALLSYMS)
+ .procname = "kallsyms_lookup_name",
+ .data = &spl_kallsyms_lookup_name_fn,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644,
+ .proc_handler = &proc_dokallsyms_lookup_name,
+ },
+#endif
{
- .ctl_name = CTL_SPL_DEBUG,
+ CTL_NAME (CTL_SPL_DEBUG)
.procname = "debug",
.mode = 0555,
.child = spl_debug_table,
},
-#ifdef DEBUG_MUTEX
{
- .ctl_name = CTL_SPL_MUTEX,
- .procname = "mutex",
+ CTL_NAME (CTL_SPL_VM)
+ .procname = "vm",
.mode = 0555,
- .child = spl_mutex_table,
+ .child = spl_vm_table,
},
-#endif
#ifdef DEBUG_KMEM
{
- .ctl_name = CTL_SPL_KMEM,
+ CTL_NAME (CTL_SPL_KMEM)
.procname = "kmem",
.mode = 0555,
.child = spl_kmem_table,
},
#endif
-#ifdef DEBUG_KSTAT
{
- .ctl_name = CTL_SPL_KSTAT,
+ CTL_NAME (CTL_SPL_KSTAT)
.procname = "kstat",
.mode = 0555,
.child = spl_kstat_table,
},
-#endif
{ 0 },
};
static struct ctl_table spl_dir[] = {
{
- .ctl_name = CTL_SPL,
+ CTL_NAME (CTL_SPL)
.procname = "spl",
.mode = 0555,
.child = spl_table,
static struct ctl_table spl_root[] = {
{
- .ctl_name = CTL_KERN,
+ CTL_NAME (CTL_KERN)
.procname = "kernel",
.mode = 0555,
.child = spl_dir,
proc_init(void)
{
int rc = 0;
- ENTRY;
+ SENTRY;
#ifdef CONFIG_SYSCTL
spl_header = spl_register_sysctl_table(spl_root, 0);
if (spl_header == NULL)
- RETURN(-EUNATCH);
+ SRETURN(-EUNATCH);
#endif /* CONFIG_SYSCTL */
-#if defined(DEBUG_MUTEX) || defined(DEBUG_KMEM) || defined(DEBUG_KSTAT)
proc_spl = proc_mkdir("spl", NULL);
if (proc_spl == NULL)
- GOTO(out, rc = -EUNATCH);
-
-#ifdef DEBUG_MUTEX
- proc_spl_mutex = proc_mkdir("mutex", proc_spl);
- if (proc_spl_mutex == NULL)
- GOTO(out, rc = -EUNATCH);
-
- proc_spl_mutex_stats = create_proc_entry("stats_per", 0444,
- proc_spl_mutex);
- if (proc_spl_mutex_stats == NULL)
- GOTO(out, rc = -EUNATCH);
-
- proc_spl_mutex_stats->proc_fops = &proc_mutex_operations;
-#endif /* DEBUG_MUTEX */
+ SGOTO(out, rc = -EUNATCH);
#ifdef DEBUG_KMEM
proc_spl_kmem = proc_mkdir("kmem", proc_spl);
if (proc_spl_kmem == NULL)
- GOTO(out, rc = -EUNATCH);
+ SGOTO(out, rc = -EUNATCH);
proc_spl_kmem_slab = create_proc_entry("slab", 0444, proc_spl_kmem);
if (proc_spl_kmem_slab == NULL)
- GOTO(out, rc = -EUNATCH);
+ SGOTO(out, rc = -EUNATCH);
proc_spl_kmem_slab->proc_fops = &proc_slab_operations;
#endif /* DEBUG_KMEM */
-#ifdef DEBUG_KSTAT
proc_spl_kstat = proc_mkdir("kstat", proc_spl);
if (proc_spl_kstat == NULL)
- GOTO(out, rc = -EUNATCH);
-#endif /* DEBUG_KSTAT */
-
+ SGOTO(out, rc = -EUNATCH);
out:
if (rc) {
remove_proc_entry("kstat", proc_spl);
#ifdef DEBUG_KMEM
remove_proc_entry("slab", proc_spl_kmem);
-#endif
remove_proc_entry("kmem", proc_spl);
-#ifdef DEBUG_MUTEX
- remove_proc_entry("stats_per", proc_spl_mutex);
#endif
- remove_proc_entry("mutex", proc_spl);
remove_proc_entry("spl", NULL);
#ifdef CONFIG_SYSCTL
spl_unregister_sysctl_table(spl_header);
#endif /* CONFIG_SYSCTL */
}
-#endif /* DEBUG_MUTEX || DEBUG_KMEM || DEBUG_KSTAT */
- RETURN(rc);
+ SRETURN(rc);
}
void
proc_fini(void)
{
- ENTRY;
+ SENTRY;
-#if defined(DEBUG_MUTEX) || defined(DEBUG_KMEM) || defined(DEBUG_KSTAT)
remove_proc_entry("kstat", proc_spl);
#ifdef DEBUG_KMEM
remove_proc_entry("slab", proc_spl_kmem);
-#endif
remove_proc_entry("kmem", proc_spl);
-#ifdef DEBUG_MUTEX
- remove_proc_entry("stats_per", proc_spl_mutex);
#endif
- remove_proc_entry("mutex", proc_spl);
remove_proc_entry("spl", NULL);
-#endif /* DEBUG_MUTEX || DEBUG_KMEM || DEBUG_KSTAT */
#ifdef CONFIG_SYSCTL
ASSERT(spl_header != NULL);
spl_unregister_sysctl_table(spl_header);
#endif /* CONFIG_SYSCTL */
- EXIT;
+ SEXIT;
}