Add hw_serial support based on a usermodehelper which runs
at spl module load time can calls hostid. The resolved hostid is then fed back in to a proc entry for latter use. It's not a pretty thing, but it will work for now. The hw_serial is required for things such as 'zpool status' to work. git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@71 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
parent
12ea923056
commit
f23e92fabf
|
@ -4,6 +4,7 @@
|
||||||
#include <sys/kmem.h>
|
#include <sys/kmem.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/kmod.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -14,19 +15,23 @@ static spinlock_t spl_debug_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
|
||||||
unsigned long spl_debug_mask = 0;
|
unsigned long spl_debug_mask = 0;
|
||||||
unsigned long spl_debug_subsys = 0xff;
|
unsigned long spl_debug_subsys = 0xff;
|
||||||
|
unsigned long spl_hostid = 0;
|
||||||
|
char hw_serial[11] = "<none>";
|
||||||
|
|
||||||
EXPORT_SYMBOL(spl_debug_mask);
|
EXPORT_SYMBOL(spl_debug_mask);
|
||||||
EXPORT_SYMBOL(spl_debug_subsys);
|
EXPORT_SYMBOL(spl_debug_subsys);
|
||||||
|
EXPORT_SYMBOL(spl_hostid);
|
||||||
|
EXPORT_SYMBOL(hw_serial);
|
||||||
|
|
||||||
static struct proc_dir_entry *spl_proc_root = NULL;
|
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_mask = NULL;
|
||||||
static struct proc_dir_entry *spl_proc_debug_subsys = 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;
|
||||||
|
|
||||||
int p0 = 0;
|
int p0 = 0;
|
||||||
EXPORT_SYMBOL(p0);
|
EXPORT_SYMBOL(p0);
|
||||||
|
|
||||||
char hw_serial[11];
|
|
||||||
EXPORT_SYMBOL(hw_serial);
|
|
||||||
|
|
||||||
vmem_t *zio_alloc_arena = NULL;
|
vmem_t *zio_alloc_arena = NULL;
|
||||||
EXPORT_SYMBOL(zio_alloc_arena);
|
EXPORT_SYMBOL(zio_alloc_arena);
|
||||||
|
|
||||||
|
@ -113,35 +118,68 @@ static int
|
||||||
spl_proc_rd_generic_ul(char *page, char **start, off_t off,
|
spl_proc_rd_generic_ul(char *page, char **start, off_t off,
|
||||||
int count, int *eof, unsigned long val)
|
int count, int *eof, unsigned long val)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
|
|
||||||
*start = page;
|
*start = page;
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
||||||
if (off || count > PAGE_SIZE)
|
if (off || count > PAGE_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock(&spl_debug_lock);
|
return snprintf(page, PAGE_SIZE, "0x%lx\n", val & 0xffffffff);
|
||||||
rc = snprintf(page, PAGE_SIZE, "0x%lx\n", val);
|
|
||||||
spin_unlock(&spl_debug_lock);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spl_proc_rd_debug_mask(char *page, char **start, off_t off,
|
spl_proc_rd_debug_mask(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
return spl_proc_rd_generic_ul(page, start, off, count,
|
int rc;
|
||||||
|
|
||||||
|
spin_lock(&spl_debug_lock);
|
||||||
|
rc = spl_proc_rd_generic_ul(page, start, off, count,
|
||||||
eof, spl_debug_mask);
|
eof, spl_debug_mask);
|
||||||
|
spin_unlock(&spl_debug_lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spl_proc_rd_debug_subsys(char *page, char **start, off_t off,
|
spl_proc_rd_debug_subsys(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
return spl_proc_rd_generic_ul(page, start, off, count,
|
int rc;
|
||||||
|
|
||||||
|
spin_lock(&spl_debug_lock);
|
||||||
|
rc = spl_proc_rd_generic_ul(page, start, off, count,
|
||||||
eof, spl_debug_subsys);
|
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
|
static int
|
||||||
|
@ -200,6 +238,23 @@ spl_proc_wr_debug_subsys(struct file *file, const char *ubuf,
|
||||||
return count;
|
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 *
|
static struct proc_dir_entry *
|
||||||
spl_register_proc_entry(const char *name, mode_t mode,
|
spl_register_proc_entry(const char *name, mode_t mode,
|
||||||
struct proc_dir_entry *parent, void *data,
|
struct proc_dir_entry *parent, void *data,
|
||||||
|
@ -235,6 +290,15 @@ EXPORT_SYMBOL(spl_set_debug_subsys);
|
||||||
static int __init spl_init(void)
|
static int __init spl_init(void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
char sh_path[] = "/bin/sh";
|
||||||
|
char *argv[] = { sh_path,
|
||||||
|
"-c",
|
||||||
|
"/usr/bin/hostid >/proc/spl/hostid",
|
||||||
|
NULL };
|
||||||
|
char *envp[] = { "HOME=/",
|
||||||
|
"TERM=linux",
|
||||||
|
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
|
||||||
|
NULL };
|
||||||
|
|
||||||
spl_proc_root = proc_mkdir("spl", NULL);
|
spl_proc_root = proc_mkdir("spl", NULL);
|
||||||
if (!spl_proc_root) {
|
if (!spl_proc_root) {
|
||||||
|
@ -260,16 +324,49 @@ static int __init spl_init(void)
|
||||||
goto out2;
|
goto out2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = kmem_init()))
|
if ((rc = kmem_init()))
|
||||||
goto out2;
|
goto out4;
|
||||||
|
|
||||||
if ((rc = vn_init()))
|
if ((rc = vn_init()))
|
||||||
goto out2;
|
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;
|
||||||
|
|
||||||
strcpy(hw_serial, "007f0100"); /* loopback */
|
|
||||||
printk("spl: Loaded Solaris Porting Layer v%s\n", VERSION);
|
printk("spl: Loaded Solaris Porting Layer v%s\n", VERSION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out4:
|
||||||
|
if (spl_proc_hw_serial)
|
||||||
|
remove_proc_entry("hw_serial", spl_proc_root);
|
||||||
|
out3:
|
||||||
|
if (spl_proc_hostid)
|
||||||
|
remove_proc_entry("hostid", spl_proc_root);
|
||||||
out2:
|
out2:
|
||||||
if (spl_proc_debug_mask)
|
if (spl_proc_debug_mask)
|
||||||
remove_proc_entry("debug_mask", spl_proc_root);
|
remove_proc_entry("debug_mask", spl_proc_root);
|
||||||
|
@ -287,6 +384,8 @@ static void spl_fini(void)
|
||||||
vn_fini();
|
vn_fini();
|
||||||
kmem_fini();
|
kmem_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_subsys", spl_proc_root);
|
||||||
remove_proc_entry("debug_mask", spl_proc_root);
|
remove_proc_entry("debug_mask", spl_proc_root);
|
||||||
remove_proc_entry("spl", NULL);
|
remove_proc_entry("spl", NULL);
|
||||||
|
|
Loading…
Reference in New Issue