summaryrefslogtreecommitdiffstats
path: root/modules/spl/spl-generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/spl/spl-generic.c')
-rw-r--r--modules/spl/spl-generic.c356
1 files changed, 48 insertions, 308 deletions
diff --git a/modules/spl/spl-generic.c b/modules/spl/spl-generic.c
index 8cd217cf1..252e9788d 100644
--- a/modules/spl/spl-generic.c
+++ b/modules/spl/spl-generic.c
@@ -3,32 +3,21 @@
#include <sys/vnode.h>
#include <sys/kmem.h>
#include <sys/debug.h>
-#include <linux/proc_fs.h>
+#include <sys/proc.h>
#include <linux/kmod.h>
#include "config.h"
-/*
- * Generic support
- */
-static char spl_debug_buffer1[1024];
-static char spl_debug_buffer2[1024];
-static spinlock_t spl_debug_lock = SPIN_LOCK_UNLOCKED;
+#ifdef DEBUG_SUBSYSTEM
+#undef DEBUG_SUBSYSTEM
+#endif
-unsigned long spl_debug_mask = 0;
-unsigned long spl_debug_subsys = 0xff;
-unsigned long spl_hostid = 0;
-char hw_serial[11] = "<none>";
+#define DEBUG_SUBSYSTEM S_GENERIC
-EXPORT_SYMBOL(spl_debug_mask);
-EXPORT_SYMBOL(spl_debug_subsys);
+unsigned long spl_hostid = 0;
EXPORT_SYMBOL(spl_hostid);
-EXPORT_SYMBOL(hw_serial);
-static struct proc_dir_entry *spl_proc_root = NULL;
-static struct proc_dir_entry *spl_proc_debug_mask = NULL;
-static struct proc_dir_entry *spl_proc_debug_subsys = NULL;
-static struct proc_dir_entry *spl_proc_hostid = NULL;
-static struct proc_dir_entry *spl_proc_hw_serial = NULL;
+char spl_hw_serial[11] = "<none>";
+EXPORT_SYMBOL(spl_hw_serial);
int p0 = 0;
EXPORT_SYMBOL(p0);
@@ -36,14 +25,14 @@ EXPORT_SYMBOL(p0);
vmem_t *zio_alloc_arena = NULL;
EXPORT_SYMBOL(zio_alloc_arena);
-
int
highbit(unsigned long i)
{
register int h = 1;
+ ENTRY;
if (i == 0)
- return (0);
+ RETURN(0);
#if BITS_PER_LONG == 64
if (i & 0xffffffff00000000ul) {
h += 32; i >>= 32;
@@ -64,7 +53,7 @@ highbit(unsigned long i)
if (i & 0x2) {
h += 1;
}
- return (h);
+ RETURN(h);
}
EXPORT_SYMBOL(highbit);
@@ -76,324 +65,75 @@ ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result)
}
EXPORT_SYMBOL(ddi_strtoul);
-/* XXX: Not the most efficient debug function ever. This should be re-done
- * as an internal per-cpu in-memory debug log accessable via /proc/. Not as
- * a shared global buffer everything gets serialize though. That said I'll
- * worry about performance considerations once I've dealt with correctness.
- */
-void
-__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
-{
- char *sfp;
- struct timeval tv;
- unsigned long flags;
- va_list ap;
-
- sfp = strrchr(file, '/');
- do_gettimeofday(&tv);
-
- /* XXX: This is particularly bad for performance, but we need to
- * disable irqs here or two __dprintf()'s may deadlock on each
- * other if one if called from an irq handler. This is yet another
- * reason why we really, really, need an internal debug log.
- */
- spin_lock_irqsave(&spl_debug_lock, flags);
- memset(spl_debug_buffer1, 0, 1024);
- memset(spl_debug_buffer2, 0, 1024);
-
- snprintf(spl_debug_buffer1, 1023,
- "spl: %lu.%06lu:%d:%u:%s:%d:%s(): ",
- tv.tv_sec, tv.tv_usec, current->pid,
- smp_processor_id(),
- sfp == NULL ? file : sfp + 1,
- line, func);
-
- va_start(ap, fmt);
- vsnprintf(spl_debug_buffer2, 1023, fmt, ap);
- va_end(ap);
-
- printk("%s%s", spl_debug_buffer1, spl_debug_buffer2);
- spin_unlock_irqrestore(&spl_debug_lock, flags);
-}
-EXPORT_SYMBOL(__dprintf);
-
-static int
-spl_proc_rd_generic_ul(char *page, char **start, off_t off,
- int count, int *eof, unsigned long val)
-{
- *start = page;
- *eof = 1;
-
- if (off || count > PAGE_SIZE)
- return 0;
-
- return snprintf(page, PAGE_SIZE, "0x%lx\n", val & 0xffffffff);
-}
-
-static int
-spl_proc_rd_debug_mask(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int rc;
-
- spin_lock(&spl_debug_lock);
- rc = spl_proc_rd_generic_ul(page, start, off, count,
- eof, spl_debug_mask);
- spin_unlock(&spl_debug_lock);
-
- return rc;
-}
-
-static int
-spl_proc_rd_debug_subsys(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int rc;
-
- spin_lock(&spl_debug_lock);
- rc = spl_proc_rd_generic_ul(page, start, off, count,
- eof, spl_debug_subsys);
- spin_unlock(&spl_debug_lock);
-
- return rc;
-}
-
-static int
-spl_proc_rd_hostid(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- *start = page;
- *eof = 1;
-
- if (off || count > PAGE_SIZE)
- return 0;
-
- return snprintf(page, PAGE_SIZE, "%lx\n", spl_hostid & 0xffffffff);
-}
-
-static int
-spl_proc_rd_hw_serial(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- *start = page;
- *eof = 1;
-
- if (off || count > PAGE_SIZE)
- return 0;
-
- strncpy(page, hw_serial, 11);
- return strlen(page);
-}
-
-static int
-spl_proc_wr_generic_ul(const char *ubuf, unsigned long count,
- unsigned long *val, int base)
-{
- char *end, kbuf[32];
-
- if (count >= sizeof(kbuf))
- return -EOVERFLOW;
-
- if (copy_from_user(kbuf, ubuf, count))
- return -EFAULT;
-
- kbuf[count] = '\0';
- *val = (int)simple_strtoul(kbuf, &end, base);
- if (kbuf == end)
- return -EINVAL;
-
- return 0;
-}
-
static int
-spl_proc_wr_debug_mask(struct file *file, const char *ubuf,
- unsigned long count, void *data, int mode)
+set_hostid(void)
{
- unsigned long val;
- int rc;
-
- rc = spl_proc_wr_generic_ul(ubuf, count, &val, 16);
- if (rc)
- return rc;
-
- spin_lock(&spl_debug_lock);
- spl_debug_mask = val;
- spin_unlock(&spl_debug_lock);
-
- return count;
-}
-
-static int
-spl_proc_wr_debug_subsys(struct file *file, const char *ubuf,
- unsigned long count, void *data, int mode)
-{
- unsigned long val;
- int rc;
-
- rc = spl_proc_wr_generic_ul(ubuf, count, &val, 16);
- if (rc)
- return rc;
-
- spin_lock(&spl_debug_lock);
- spl_debug_subsys = val;
- spin_unlock(&spl_debug_lock);
-
- return count;
-}
-
-static int
-spl_proc_wr_hostid(struct file *file, const char *ubuf,
- unsigned long count, void *data, int mode)
-{
- unsigned long val;
- int rc;
-
- rc = spl_proc_wr_generic_ul(ubuf, count, &val, 16);
- if (rc)
- return rc;
-
- spl_hostid = val;
- sprintf(hw_serial, "%lu\n", ((long)val >= 0) ? val : -val);
-
- return count;
-}
-
-static struct proc_dir_entry *
-spl_register_proc_entry(const char *name, mode_t mode,
- struct proc_dir_entry *parent, void *data,
- void *read_proc, void *write_proc)
-{
- struct proc_dir_entry *entry;
-
- entry = create_proc_entry(name, mode, parent);
- if (!entry)
- return ERR_PTR(-EINVAL);
-
- entry->data = data;
- entry->read_proc = read_proc;
- entry->write_proc = write_proc;
-
- return entry;
-} /* register_proc_entry() */
-
-void spl_set_debug_mask(unsigned long mask) {
- spin_lock(&spl_debug_lock);
- spl_debug_mask = mask;
- spin_unlock(&spl_debug_lock);
-}
-EXPORT_SYMBOL(spl_set_debug_mask);
-
-void spl_set_debug_subsys(unsigned long mask) {
- spin_lock(&spl_debug_lock);
- spl_debug_subsys = mask;
- spin_unlock(&spl_debug_lock);
-}
-EXPORT_SYMBOL(spl_set_debug_subsys);
-
-static int __init spl_init(void)
-{
- int rc = 0;
char sh_path[] = "/bin/sh";
char *argv[] = { sh_path,
"-c",
- "/usr/bin/hostid >/proc/spl/hostid",
+ "/usr/bin/hostid >/proc/sys/spl/hostid",
NULL };
char *envp[] = { "HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL };
- spl_proc_root = proc_mkdir("spl", NULL);
- if (!spl_proc_root) {
- printk("spl: Error unable to create /proc/spl/ directory\n");
- return -EINVAL;
- }
-
- spl_proc_debug_mask = spl_register_proc_entry("debug_mask", 0644,
- spl_proc_root, NULL,
- spl_proc_rd_debug_mask,
- spl_proc_wr_debug_mask);
- if (IS_ERR(spl_proc_debug_mask)) {
- rc = PTR_ERR(spl_proc_debug_mask);
- goto out;
- }
-
- spl_proc_debug_subsys = spl_register_proc_entry("debug_subsys", 0644,
- spl_proc_root, NULL,
- spl_proc_rd_debug_subsys,
- spl_proc_wr_debug_subsys);
- if (IS_ERR(spl_proc_debug_subsys)) {
- rc = PTR_ERR(spl_proc_debug_subsys);
- goto out2;
- }
+ /* Doing address resolution in the kernel is tricky and just
+ * not a good idea in general. So to set the proper 'spl_hw_serial'
+ * use the usermodehelper support to ask '/bin/sh' to run
+ * '/usr/bin/hostid' and redirect the result to /proc/sys/spl/hostid
+ * for us to use. It's a horific solution but it will do for now.
+ */
+ return call_usermodehelper(sh_path, argv, envp, 1);
+}
- spl_proc_hostid = spl_register_proc_entry("hostid", 0644,
- spl_proc_root, NULL,
- spl_proc_rd_hostid,
- spl_proc_wr_hostid);
- if (IS_ERR(spl_proc_hostid)) {
- rc = PTR_ERR(spl_proc_hostid);
- goto out3;
- }
+static int __init spl_init(void)
+{
+ int rc = 0;
+ ENTRY;
- spl_proc_hw_serial = spl_register_proc_entry("hw_serial", 0444,
- spl_proc_root, NULL,
- spl_proc_rd_hw_serial,
- NULL);
- if (IS_ERR(spl_proc_hw_serial)) {
- rc = PTR_ERR(spl_proc_hw_serial);
- goto out4;
- }
+ if ((rc = debug_init()))
+ RETURN(rc);
if ((rc = kmem_init()))
- goto out4;
+ GOTO(out , rc);
if ((rc = vn_init()))
- goto out4;
-
- /* Doing address resolution in the kernel is tricky and just
- * not a good idea in general. So to set the proper 'hw_serial'
- * use the usermodehelper support to ask '/bin/sh' to run
- * '/usr/bin/hostid' and redirect the result to /proc/spl/hostid
- * for us to use. It's a horific solution but it will do.
- */
- if ((rc = call_usermodehelper(sh_path, argv, envp, 1)))
- goto out4;
+ GOTO(out2, rc);
- printk("spl: Loaded Solaris Porting Layer v%s\n", VERSION);
+ if ((rc = proc_init()))
+ GOTO(out3, rc);
- return 0;
+ if ((rc = set_hostid()))
+ GOTO(out4, rc = -EADDRNOTAVAIL);
+ CWARN("Loaded Solaris Porting Layer v%s\n", VERSION);
+ RETURN(rc);
out4:
- if (spl_proc_hw_serial)
- remove_proc_entry("hw_serial", spl_proc_root);
+ proc_fini();
out3:
- if (spl_proc_hostid)
- remove_proc_entry("hostid", spl_proc_root);
+ vn_fini();
out2:
- if (spl_proc_debug_mask)
- remove_proc_entry("debug_mask", spl_proc_root);
-
- if (spl_proc_debug_subsys)
- remove_proc_entry("debug_subsys", spl_proc_root);
+ kmem_fini();
out:
- remove_proc_entry("spl", NULL);
+ debug_fini();
- return rc;
+ printk("SPL: Failed to Load Solaris Porting Layer v%s, "
+ "rc = %d\n", VERSION, rc);
+ RETURN(rc);
}
static void spl_fini(void)
{
+ ENTRY;
+
+ CWARN("Unloaded Solaris Porting Layer v%s\n", VERSION);
+ proc_fini();
vn_fini();
kmem_fini();
+ debug_fini();
- remove_proc_entry("hw_serial", spl_proc_root);
- remove_proc_entry("hostid", spl_proc_root);
- remove_proc_entry("debug_subsys", spl_proc_root);
- remove_proc_entry("debug_mask", spl_proc_root);
- remove_proc_entry("spl", NULL);
-
- return;
+ EXIT;
}
module_init(spl_init);