mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 01:51:00 +03:00
FreeBSD: Add support for procfs_list
The procfs_list interface is required by several kstats. Implement this functionality for FreeBSD to provide access to these kstats. Reviewed-by: Allan Jude <allan@klarasystems.com> Reviewed-by: Ryan Moeller <ryan@ixsystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Matt Macy <mmacy@FreeBSD.org> Closes #10890
This commit is contained in:
parent
3dad29fb4b
commit
7b8363d7f0
@ -83,6 +83,14 @@ typedef struct kstat_s kstat_t;
|
||||
typedef int kid_t; /* unique kstat id */
|
||||
typedef int kstat_update_t(struct kstat_s *, int); /* dynamic update cb */
|
||||
|
||||
struct seq_file {
|
||||
char *sf_buf;
|
||||
size_t sf_size;
|
||||
};
|
||||
|
||||
void seq_printf(struct seq_file *m, const char *fmt, ...);
|
||||
|
||||
|
||||
typedef struct kstat_module {
|
||||
char ksm_name[KSTAT_STRLEN+1]; /* module name */
|
||||
struct list_head ksm_module_list; /* module linkage */
|
||||
@ -92,6 +100,7 @@ typedef struct kstat_module {
|
||||
|
||||
typedef struct kstat_raw_ops {
|
||||
int (*headers)(char *buf, size_t size);
|
||||
int (*seq_headers)(struct seq_file *);
|
||||
int (*data)(char *buf, size_t size, void *data);
|
||||
void *(*addr)(kstat_t *ksp, loff_t index);
|
||||
} kstat_raw_ops_t;
|
||||
@ -112,6 +121,7 @@ struct kstat_s {
|
||||
size_t ks_data_size; /* size of kstat data section */
|
||||
kstat_update_t *ks_update; /* dynamic updates */
|
||||
void *ks_private; /* private data */
|
||||
void *ks_private1; /* private data */
|
||||
kmutex_t ks_private_lock; /* kstat private data lock */
|
||||
kmutex_t *ks_lock; /* kstat data lock */
|
||||
struct list_head ks_list; /* kstat linkage */
|
||||
@ -185,6 +195,12 @@ extern void __kstat_set_raw_ops(kstat_t *ksp,
|
||||
int (*data)(char *buf, size_t size, void *data),
|
||||
void* (*addr)(kstat_t *ksp, loff_t index));
|
||||
|
||||
extern void __kstat_set_seq_raw_ops(kstat_t *ksp,
|
||||
int (*headers)(struct seq_file *),
|
||||
int (*data)(char *buf, size_t size, void *data),
|
||||
void* (*addr)(kstat_t *ksp, loff_t index));
|
||||
|
||||
|
||||
extern kstat_t *__kstat_create(const char *ks_module, int ks_instance,
|
||||
const char *ks_name, const char *ks_class, uchar_t ks_type,
|
||||
uint_t ks_ndata, uchar_t ks_flags);
|
||||
@ -196,6 +212,8 @@ extern void kstat_waitq_exit(kstat_io_t *);
|
||||
extern void kstat_runq_enter(kstat_io_t *);
|
||||
extern void kstat_runq_exit(kstat_io_t *);
|
||||
|
||||
#define kstat_set_seq_raw_ops(k, h, d, a) \
|
||||
__kstat_set_seq_raw_ops(k, h, d, a)
|
||||
#define kstat_set_raw_ops(k, h, d, a) \
|
||||
__kstat_set_raw_ops(k, h, d, a)
|
||||
#define kstat_create(m, i, n, c, t, s, f) \
|
||||
|
@ -33,16 +33,18 @@
|
||||
* procfs list manipulation
|
||||
*/
|
||||
|
||||
struct seq_file { };
|
||||
void seq_printf(struct seq_file *m, const char *fmt, ...);
|
||||
|
||||
typedef struct procfs_list {
|
||||
typedef struct procfs_list procfs_list_t;
|
||||
struct procfs_list {
|
||||
void *pl_private;
|
||||
void *pl_next_data;
|
||||
kmutex_t pl_lock;
|
||||
list_t pl_list;
|
||||
uint64_t pl_next_id;
|
||||
int (*pl_show)(struct seq_file *f, void *p);
|
||||
int (*pl_show_header)(struct seq_file *f);
|
||||
int (*pl_clear)(procfs_list_t *procfs_list);
|
||||
size_t pl_node_offset;
|
||||
} procfs_list_t;
|
||||
};
|
||||
|
||||
typedef struct procfs_list_node {
|
||||
list_node_t pln_link;
|
||||
@ -50,6 +52,7 @@ typedef struct procfs_list_node {
|
||||
} procfs_list_node_t;
|
||||
|
||||
void procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
|
@ -57,6 +57,7 @@ typedef struct procfs_list_node {
|
||||
} procfs_list_node_t;
|
||||
|
||||
void procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
|
@ -386,6 +386,7 @@ typedef struct procfs_list_node {
|
||||
} procfs_list_node_t;
|
||||
|
||||
void procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
|
@ -444,6 +444,7 @@ seq_printf(struct seq_file *m, const char *fmt, ...)
|
||||
|
||||
void
|
||||
procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
|
@ -55,6 +55,17 @@ __kstat_set_raw_ops(kstat_t *ksp,
|
||||
ksp->ks_raw_ops.addr = addr;
|
||||
}
|
||||
|
||||
void
|
||||
__kstat_set_seq_raw_ops(kstat_t *ksp,
|
||||
int (*headers)(struct seq_file *f),
|
||||
int (*data)(char *buf, size_t size, void *data),
|
||||
void *(*addr)(kstat_t *ksp, loff_t index))
|
||||
{
|
||||
ksp->ks_raw_ops.seq_headers = headers;
|
||||
ksp->ks_raw_ops.data = data;
|
||||
ksp->ks_raw_ops.addr = addr;
|
||||
}
|
||||
|
||||
static int
|
||||
kstat_default_update(kstat_t *ksp, int rw)
|
||||
{
|
||||
@ -160,7 +171,7 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
||||
void *data;
|
||||
kstat_t *ksp = arg1;
|
||||
void *(*addr_op)(kstat_t *ksp, loff_t index);
|
||||
int n, rc = 0;
|
||||
int n, has_header, rc = 0;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
if (sb == NULL)
|
||||
@ -180,14 +191,25 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
||||
ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
|
||||
|
||||
n = 0;
|
||||
has_header = (ksp->ks_raw_ops.headers ||
|
||||
ksp->ks_raw_ops.seq_headers);
|
||||
|
||||
restart_headers:
|
||||
if (ksp->ks_raw_ops.headers) {
|
||||
rc = ksp->ks_raw_ops.headers(
|
||||
ksp->ks_raw_buf, ksp->ks_raw_bufsize);
|
||||
} else if (ksp->ks_raw_ops.seq_headers) {
|
||||
struct seq_file f;
|
||||
|
||||
f.sf_buf = ksp->ks_raw_buf;
|
||||
f.sf_size = ksp->ks_raw_bufsize;
|
||||
rc = ksp->ks_raw_ops.seq_headers(&f);
|
||||
}
|
||||
if (has_header) {
|
||||
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
||||
goto restart_headers;
|
||||
if (rc == 0)
|
||||
sbuf_printf(sb, "%s", ksp->ks_raw_buf);
|
||||
sbuf_printf(sb, "\n%s", ksp->ks_raw_buf);
|
||||
}
|
||||
|
||||
while ((data = addr_op(ksp, n)) != NULL) {
|
||||
@ -220,16 +242,21 @@ kstat_t *
|
||||
__kstat_create(const char *module, int instance, const char *name,
|
||||
const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags)
|
||||
{
|
||||
char buf[KSTAT_STRLEN];
|
||||
struct sysctl_oid *root;
|
||||
kstat_t *ksp;
|
||||
char *pool;
|
||||
|
||||
KASSERT(instance == 0, ("instance=%d", instance));
|
||||
if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
|
||||
ASSERT(ks_ndata == 1);
|
||||
|
||||
if (class == NULL)
|
||||
class = "misc";
|
||||
|
||||
/*
|
||||
* Allocate the main structure. We don't need to copy module/class/name
|
||||
* stuff in here, because it is only used for sysctl node creation
|
||||
* Allocate the main structure. We don't need to keep a copy of
|
||||
* module in here, because it is only used for sysctl node creation
|
||||
* done in this function.
|
||||
*/
|
||||
ksp = malloc(sizeof (*ksp), M_KSTAT, M_WAITOK|M_ZERO);
|
||||
@ -237,8 +264,8 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||
ksp->ks_crtime = gethrtime();
|
||||
ksp->ks_snaptime = ksp->ks_crtime;
|
||||
ksp->ks_instance = instance;
|
||||
strncpy(ksp->ks_name, name, KSTAT_STRLEN);
|
||||
strncpy(ksp->ks_class, class, KSTAT_STRLEN);
|
||||
(void) strlcpy(ksp->ks_name, name, KSTAT_STRLEN);
|
||||
(void) strlcpy(ksp->ks_class, class, KSTAT_STRLEN);
|
||||
ksp->ks_type = ks_type;
|
||||
ksp->ks_flags = flags;
|
||||
ksp->ks_update = kstat_default_update;
|
||||
@ -280,10 +307,22 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||
ksp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some kstats use a module name like "zfs/poolname" to distinguish a
|
||||
* set of kstats belonging to a specific pool. Split on '/' to add an
|
||||
* extra node for the pool name if needed.
|
||||
*/
|
||||
(void) strlcpy(buf, module, KSTAT_STRLEN);
|
||||
module = buf;
|
||||
pool = strchr(module, '/');
|
||||
if (pool != NULL)
|
||||
*pool++ = '\0';
|
||||
|
||||
/*
|
||||
* Create sysctl tree for those statistics:
|
||||
*
|
||||
* kstat.<module>.<class>.<name>.
|
||||
* kstat.<module>[.<pool>].<class>.<name>
|
||||
*/
|
||||
sysctl_ctx_init(&ksp->ks_sysctl_ctx);
|
||||
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
|
||||
@ -295,11 +334,26 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||
free(ksp, M_KSTAT);
|
||||
return (NULL);
|
||||
}
|
||||
if (pool != NULL) {
|
||||
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(root), OID_AUTO, pool, CTLFLAG_RW, 0, "");
|
||||
if (root == NULL) {
|
||||
printf("%s: Cannot create kstat.%s.%s tree!\n",
|
||||
__func__, module, pool);
|
||||
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
|
||||
free(ksp, M_KSTAT);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root),
|
||||
OID_AUTO, class, CTLFLAG_RW, 0, "");
|
||||
if (root == NULL) {
|
||||
printf("%s: Cannot create kstat.%s.%s tree!\n", __func__,
|
||||
module, class);
|
||||
if (pool != NULL)
|
||||
printf("%s: Cannot create kstat.%s.%s.%s tree!\n",
|
||||
__func__, module, pool, class);
|
||||
else
|
||||
printf("%s: Cannot create kstat.%s.%s tree!\n",
|
||||
__func__, module, class);
|
||||
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
|
||||
free(ksp, M_KSTAT);
|
||||
return (NULL);
|
||||
@ -309,8 +363,13 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||
SYSCTL_CHILDREN(root),
|
||||
OID_AUTO, name, CTLFLAG_RW, 0, "");
|
||||
if (root == NULL) {
|
||||
printf("%s: Cannot create kstat.%s.%s.%s tree!\n",
|
||||
__func__, module, class, name);
|
||||
if (pool != NULL)
|
||||
printf("%s: Cannot create kstat.%s.%s.%s.%s "
|
||||
"tree!\n", __func__, module, pool, class,
|
||||
name);
|
||||
else
|
||||
printf("%s: Cannot create kstat.%s.%s.%s "
|
||||
"tree!\n", __func__, module, class, name);
|
||||
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
|
||||
free(ksp, M_KSTAT);
|
||||
return (NULL);
|
||||
@ -411,7 +470,6 @@ kstat_install(kstat_t *ksp)
|
||||
switch (ksp->ks_type) {
|
||||
case KSTAT_TYPE_NAMED:
|
||||
return (kstat_install_named(ksp));
|
||||
break;
|
||||
case KSTAT_TYPE_RAW:
|
||||
if (ksp->ks_raw_ops.data) {
|
||||
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
@ -426,7 +484,6 @@ kstat_install(kstat_t *ksp)
|
||||
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, 0, kstat_sysctl_raw, "", ksp->ks_name);
|
||||
}
|
||||
VERIFY(root != NULL);
|
||||
break;
|
||||
case KSTAT_TYPE_IO:
|
||||
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
@ -440,6 +497,7 @@ kstat_install(kstat_t *ksp)
|
||||
default:
|
||||
panic("unsupported kstat type %d\n", ksp->ks_type);
|
||||
}
|
||||
VERIFY(root != NULL);
|
||||
ksp->ks_sysctl_root = root;
|
||||
}
|
||||
|
||||
|
@ -32,12 +32,74 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/procfs_list.h>
|
||||
|
||||
typedef struct procfs_list_iter {
|
||||
procfs_list_t *pli_pl;
|
||||
void *pli_elt;
|
||||
} pli_t;
|
||||
|
||||
void
|
||||
seq_printf(struct seq_file *m, const char *fmt, ...)
|
||||
{}
|
||||
seq_printf(struct seq_file *f, const char *fmt, ...)
|
||||
{
|
||||
va_list adx;
|
||||
|
||||
va_start(adx, fmt);
|
||||
(void) vsnprintf(f->sf_buf, f->sf_size, fmt, adx);
|
||||
va_end(adx);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_list_update(kstat_t *ksp, int rw)
|
||||
{
|
||||
procfs_list_t *pl = ksp->ks_private;
|
||||
|
||||
if (rw == KSTAT_WRITE)
|
||||
pl->pl_clear(pl);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_list_data(char *buf, size_t size, void *data)
|
||||
{
|
||||
pli_t *p;
|
||||
void *elt;
|
||||
procfs_list_t *pl;
|
||||
struct seq_file f;
|
||||
|
||||
p = data;
|
||||
pl = p->pli_pl;
|
||||
elt = p->pli_elt;
|
||||
free(p, M_TEMP);
|
||||
f.sf_buf = buf;
|
||||
f.sf_size = size;
|
||||
return (pl->pl_show(&f, elt));
|
||||
}
|
||||
|
||||
static void *
|
||||
procfs_list_addr(kstat_t *ksp, loff_t n)
|
||||
{
|
||||
procfs_list_t *pl = ksp->ks_private;
|
||||
void *elt = ksp->ks_private1;
|
||||
pli_t *p = NULL;
|
||||
|
||||
|
||||
if (n == 0)
|
||||
ksp->ks_private1 = list_head(&pl->pl_list);
|
||||
else if (elt)
|
||||
ksp->ks_private1 = list_next(&pl->pl_list, elt);
|
||||
|
||||
if (ksp->ks_private1) {
|
||||
p = malloc(sizeof (*p), M_TEMP, M_WAITOK);
|
||||
p->pli_pl = pl;
|
||||
p->pli_elt = ksp->ks_private1;
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
@ -46,12 +108,31 @@ procfs_list_install(const char *module,
|
||||
int (*clear)(procfs_list_t *procfs_list),
|
||||
size_t procfs_list_node_off)
|
||||
{
|
||||
kstat_t *procfs_kstat;
|
||||
|
||||
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
list_create(&procfs_list->pl_list,
|
||||
procfs_list_node_off + sizeof (procfs_list_node_t),
|
||||
procfs_list_node_off + offsetof(procfs_list_node_t, pln_link));
|
||||
procfs_list->pl_show = show;
|
||||
procfs_list->pl_show_header = show_header;
|
||||
procfs_list->pl_clear = clear;
|
||||
procfs_list->pl_next_id = 1;
|
||||
procfs_list->pl_node_offset = procfs_list_node_off;
|
||||
|
||||
procfs_kstat = kstat_create(module, 0, name, submodule,
|
||||
KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
|
||||
|
||||
if (procfs_kstat) {
|
||||
procfs_kstat->ks_lock = &procfs_list->pl_lock;
|
||||
procfs_kstat->ks_ndata = UINT32_MAX;
|
||||
procfs_kstat->ks_private = procfs_list;
|
||||
procfs_kstat->ks_update = procfs_list_update;
|
||||
kstat_set_seq_raw_ops(procfs_kstat, show_header,
|
||||
procfs_list_data, procfs_list_addr);
|
||||
kstat_install(procfs_kstat);
|
||||
procfs_list->pl_private = procfs_kstat;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -62,6 +143,7 @@ void
|
||||
procfs_list_destroy(procfs_list_t *procfs_list)
|
||||
{
|
||||
ASSERT(list_is_empty(&procfs_list->pl_list));
|
||||
kstat_delete(procfs_list->pl_private);
|
||||
list_destroy(&procfs_list->pl_list);
|
||||
mutex_destroy(&procfs_list->pl_lock);
|
||||
}
|
||||
|
@ -207,6 +207,7 @@ static const kstat_proc_op_t procfs_list_operations = {
|
||||
*/
|
||||
void
|
||||
procfs_list_install(const char *module,
|
||||
const char *submodule,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
procfs_list_t *procfs_list,
|
||||
@ -215,6 +216,12 @@ procfs_list_install(const char *module,
|
||||
int (*clear)(procfs_list_t *procfs_list),
|
||||
size_t procfs_list_node_off)
|
||||
{
|
||||
char *modulestr;
|
||||
|
||||
if (submodule != NULL)
|
||||
modulestr = kmem_asprintf("%s/%s", module, submodule);
|
||||
else
|
||||
modulestr = kmem_asprintf("%s", module);
|
||||
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
list_create(&procfs_list->pl_list,
|
||||
procfs_list_node_off + sizeof (procfs_list_node_t),
|
||||
@ -225,9 +232,10 @@ procfs_list_install(const char *module,
|
||||
procfs_list->pl_clear = clear;
|
||||
procfs_list->pl_node_offset = procfs_list_node_off;
|
||||
|
||||
kstat_proc_entry_init(&procfs_list->pl_kstat_entry, module, name);
|
||||
kstat_proc_entry_init(&procfs_list->pl_kstat_entry, modulestr, name);
|
||||
kstat_proc_entry_install(&procfs_list->pl_kstat_entry, mode,
|
||||
&procfs_list_operations, procfs_list);
|
||||
kmem_strfree(modulestr);
|
||||
}
|
||||
EXPORT_SYMBOL(procfs_list_install);
|
||||
|
||||
|
@ -94,6 +94,7 @@ void
|
||||
zfs_dbgmsg_init(void)
|
||||
{
|
||||
procfs_list_install("zfs",
|
||||
NULL,
|
||||
"dbgmsg",
|
||||
0600,
|
||||
&zfs_dbgmsgs,
|
||||
|
@ -2169,6 +2169,7 @@ spa_import_progress_init(void)
|
||||
spa_import_progress_list;
|
||||
|
||||
procfs_list_install("zfs",
|
||||
NULL,
|
||||
"import_progress",
|
||||
0644,
|
||||
&spa_import_progress_list->procfs_list,
|
||||
|
@ -122,14 +122,11 @@ static void
|
||||
spa_read_history_init(spa_t *spa)
|
||||
{
|
||||
spa_history_list_t *shl = &spa->spa_stats.read_history;
|
||||
char *module;
|
||||
|
||||
shl->size = 0;
|
||||
|
||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
||||
|
||||
shl->procfs_list.pl_private = shl;
|
||||
procfs_list_install(module,
|
||||
procfs_list_install("zfs",
|
||||
spa_name(spa),
|
||||
"reads",
|
||||
0600,
|
||||
&shl->procfs_list,
|
||||
@ -137,8 +134,6 @@ spa_read_history_init(spa_t *spa)
|
||||
spa_read_history_show_header,
|
||||
spa_read_history_clear,
|
||||
offsetof(spa_read_history_t, srh_node));
|
||||
|
||||
kmem_strfree(module);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -293,14 +288,11 @@ static void
|
||||
spa_txg_history_init(spa_t *spa)
|
||||
{
|
||||
spa_history_list_t *shl = &spa->spa_stats.txg_history;
|
||||
char *module;
|
||||
|
||||
shl->size = 0;
|
||||
|
||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
||||
|
||||
shl->procfs_list.pl_private = shl;
|
||||
procfs_list_install(module,
|
||||
procfs_list_install("zfs",
|
||||
spa_name(spa),
|
||||
"txgs",
|
||||
0644,
|
||||
&shl->procfs_list,
|
||||
@ -308,8 +300,6 @@ spa_txg_history_init(spa_t *spa)
|
||||
spa_txg_history_show_header,
|
||||
spa_txg_history_clear,
|
||||
offsetof(spa_txg_history_t, sth_node));
|
||||
|
||||
kmem_strfree(module);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -699,14 +689,12 @@ static void
|
||||
spa_mmp_history_init(spa_t *spa)
|
||||
{
|
||||
spa_history_list_t *shl = &spa->spa_stats.mmp_history;
|
||||
char *module;
|
||||
|
||||
shl->size = 0;
|
||||
|
||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
||||
|
||||
shl->procfs_list.pl_private = shl;
|
||||
procfs_list_install(module,
|
||||
procfs_list_install("zfs",
|
||||
spa_name(spa),
|
||||
"multihost",
|
||||
0644,
|
||||
&shl->procfs_list,
|
||||
@ -714,8 +702,6 @@ spa_mmp_history_init(spa_t *spa)
|
||||
spa_mmp_history_show_header,
|
||||
spa_mmp_history_clear,
|
||||
offsetof(spa_mmp_history_t, smh_node));
|
||||
|
||||
kmem_strfree(module);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user