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
227273efa4
commit
c70c6e004e
|
@ -83,6 +83,14 @@ typedef struct kstat_s kstat_t;
|
||||||
typedef int kid_t; /* unique kstat id */
|
typedef int kid_t; /* unique kstat id */
|
||||||
typedef int kstat_update_t(struct kstat_s *, int); /* dynamic update cb */
|
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 {
|
typedef struct kstat_module {
|
||||||
char ksm_name[KSTAT_STRLEN+1]; /* module name */
|
char ksm_name[KSTAT_STRLEN+1]; /* module name */
|
||||||
struct list_head ksm_module_list; /* module linkage */
|
struct list_head ksm_module_list; /* module linkage */
|
||||||
|
@ -92,6 +100,7 @@ typedef struct kstat_module {
|
||||||
|
|
||||||
typedef struct kstat_raw_ops {
|
typedef struct kstat_raw_ops {
|
||||||
int (*headers)(char *buf, size_t size);
|
int (*headers)(char *buf, size_t size);
|
||||||
|
int (*seq_headers)(struct seq_file *);
|
||||||
int (*data)(char *buf, size_t size, void *data);
|
int (*data)(char *buf, size_t size, void *data);
|
||||||
void *(*addr)(kstat_t *ksp, loff_t index);
|
void *(*addr)(kstat_t *ksp, loff_t index);
|
||||||
} kstat_raw_ops_t;
|
} kstat_raw_ops_t;
|
||||||
|
@ -112,6 +121,7 @@ struct kstat_s {
|
||||||
size_t ks_data_size; /* size of kstat data section */
|
size_t ks_data_size; /* size of kstat data section */
|
||||||
kstat_update_t *ks_update; /* dynamic updates */
|
kstat_update_t *ks_update; /* dynamic updates */
|
||||||
void *ks_private; /* private data */
|
void *ks_private; /* private data */
|
||||||
|
void *ks_private1; /* private data */
|
||||||
kmutex_t ks_private_lock; /* kstat private data lock */
|
kmutex_t ks_private_lock; /* kstat private data lock */
|
||||||
kmutex_t *ks_lock; /* kstat data lock */
|
kmutex_t *ks_lock; /* kstat data lock */
|
||||||
struct list_head ks_list; /* kstat linkage */
|
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),
|
int (*data)(char *buf, size_t size, void *data),
|
||||||
void* (*addr)(kstat_t *ksp, loff_t index));
|
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,
|
extern kstat_t *__kstat_create(const char *ks_module, int ks_instance,
|
||||||
const char *ks_name, const char *ks_class, uchar_t ks_type,
|
const char *ks_name, const char *ks_class, uchar_t ks_type,
|
||||||
uint_t ks_ndata, uchar_t ks_flags);
|
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_enter(kstat_io_t *);
|
||||||
extern void kstat_runq_exit(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) \
|
#define kstat_set_raw_ops(k, h, d, a) \
|
||||||
__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) \
|
#define kstat_create(m, i, n, c, t, s, f) \
|
||||||
|
|
|
@ -33,16 +33,18 @@
|
||||||
* procfs list manipulation
|
* procfs list manipulation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct seq_file { };
|
typedef struct procfs_list procfs_list_t;
|
||||||
void seq_printf(struct seq_file *m, const char *fmt, ...);
|
struct procfs_list {
|
||||||
|
|
||||||
typedef struct procfs_list {
|
|
||||||
void *pl_private;
|
void *pl_private;
|
||||||
|
void *pl_next_data;
|
||||||
kmutex_t pl_lock;
|
kmutex_t pl_lock;
|
||||||
list_t pl_list;
|
list_t pl_list;
|
||||||
uint64_t pl_next_id;
|
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;
|
size_t pl_node_offset;
|
||||||
} procfs_list_t;
|
};
|
||||||
|
|
||||||
typedef struct procfs_list_node {
|
typedef struct procfs_list_node {
|
||||||
list_node_t pln_link;
|
list_node_t pln_link;
|
||||||
|
@ -50,6 +52,7 @@ typedef struct procfs_list_node {
|
||||||
} procfs_list_node_t;
|
} procfs_list_node_t;
|
||||||
|
|
||||||
void procfs_list_install(const char *module,
|
void procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct procfs_list_node {
|
||||||
} procfs_list_node_t;
|
} procfs_list_node_t;
|
||||||
|
|
||||||
void procfs_list_install(const char *module,
|
void procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
|
|
@ -386,6 +386,7 @@ typedef struct procfs_list_node {
|
||||||
} procfs_list_node_t;
|
} procfs_list_node_t;
|
||||||
|
|
||||||
void procfs_list_install(const char *module,
|
void procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
|
|
@ -444,6 +444,7 @@ seq_printf(struct seq_file *m, const char *fmt, ...)
|
||||||
|
|
||||||
void
|
void
|
||||||
procfs_list_install(const char *module,
|
procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
|
|
@ -55,6 +55,17 @@ __kstat_set_raw_ops(kstat_t *ksp,
|
||||||
ksp->ks_raw_ops.addr = addr;
|
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
|
static int
|
||||||
kstat_default_update(kstat_t *ksp, int rw)
|
kstat_default_update(kstat_t *ksp, int rw)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +171,7 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
||||||
void *data;
|
void *data;
|
||||||
kstat_t *ksp = arg1;
|
kstat_t *ksp = arg1;
|
||||||
void *(*addr_op)(kstat_t *ksp, loff_t index);
|
void *(*addr_op)(kstat_t *ksp, loff_t index);
|
||||||
int n, rc = 0;
|
int n, has_header, rc = 0;
|
||||||
|
|
||||||
sb = sbuf_new_auto();
|
sb = sbuf_new_auto();
|
||||||
if (sb == NULL)
|
if (sb == NULL)
|
||||||
|
@ -180,14 +191,25 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
||||||
ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
|
ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
has_header = (ksp->ks_raw_ops.headers ||
|
||||||
|
ksp->ks_raw_ops.seq_headers);
|
||||||
|
|
||||||
restart_headers:
|
restart_headers:
|
||||||
if (ksp->ks_raw_ops.headers) {
|
if (ksp->ks_raw_ops.headers) {
|
||||||
rc = ksp->ks_raw_ops.headers(
|
rc = ksp->ks_raw_ops.headers(
|
||||||
ksp->ks_raw_buf, ksp->ks_raw_bufsize);
|
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))
|
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
||||||
goto restart_headers;
|
goto restart_headers;
|
||||||
if (rc == 0)
|
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) {
|
while ((data = addr_op(ksp, n)) != NULL) {
|
||||||
|
@ -220,16 +242,21 @@ kstat_t *
|
||||||
__kstat_create(const char *module, int instance, const char *name,
|
__kstat_create(const char *module, int instance, const char *name,
|
||||||
const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags)
|
const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags)
|
||||||
{
|
{
|
||||||
|
char buf[KSTAT_STRLEN];
|
||||||
struct sysctl_oid *root;
|
struct sysctl_oid *root;
|
||||||
kstat_t *ksp;
|
kstat_t *ksp;
|
||||||
|
char *pool;
|
||||||
|
|
||||||
KASSERT(instance == 0, ("instance=%d", instance));
|
KASSERT(instance == 0, ("instance=%d", instance));
|
||||||
if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
|
if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
|
||||||
ASSERT(ks_ndata == 1);
|
ASSERT(ks_ndata == 1);
|
||||||
|
|
||||||
|
if (class == NULL)
|
||||||
|
class = "misc";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate the main structure. We don't need to copy module/class/name
|
* Allocate the main structure. We don't need to keep a copy of
|
||||||
* stuff in here, because it is only used for sysctl node creation
|
* module in here, because it is only used for sysctl node creation
|
||||||
* done in this function.
|
* done in this function.
|
||||||
*/
|
*/
|
||||||
ksp = malloc(sizeof (*ksp), M_KSTAT, M_WAITOK|M_ZERO);
|
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_crtime = gethrtime();
|
||||||
ksp->ks_snaptime = ksp->ks_crtime;
|
ksp->ks_snaptime = ksp->ks_crtime;
|
||||||
ksp->ks_instance = instance;
|
ksp->ks_instance = instance;
|
||||||
strncpy(ksp->ks_name, name, KSTAT_STRLEN);
|
(void) strlcpy(ksp->ks_name, name, KSTAT_STRLEN);
|
||||||
strncpy(ksp->ks_class, class, KSTAT_STRLEN);
|
(void) strlcpy(ksp->ks_class, class, KSTAT_STRLEN);
|
||||||
ksp->ks_type = ks_type;
|
ksp->ks_type = ks_type;
|
||||||
ksp->ks_flags = flags;
|
ksp->ks_flags = flags;
|
||||||
ksp->ks_update = kstat_default_update;
|
ksp->ks_update = kstat_default_update;
|
||||||
|
@ -280,10 +307,22 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||||
ksp = NULL;
|
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:
|
* Create sysctl tree for those statistics:
|
||||||
*
|
*
|
||||||
* kstat.<module>.<class>.<name>.
|
* kstat.<module>[.<pool>].<class>.<name>
|
||||||
*/
|
*/
|
||||||
sysctl_ctx_init(&ksp->ks_sysctl_ctx);
|
sysctl_ctx_init(&ksp->ks_sysctl_ctx);
|
||||||
root = SYSCTL_ADD_NODE(&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);
|
free(ksp, M_KSTAT);
|
||||||
return (NULL);
|
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),
|
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root),
|
||||||
OID_AUTO, class, CTLFLAG_RW, 0, "");
|
OID_AUTO, class, CTLFLAG_RW, 0, "");
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
printf("%s: Cannot create kstat.%s.%s tree!\n", __func__,
|
if (pool != NULL)
|
||||||
module, class);
|
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);
|
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
|
||||||
free(ksp, M_KSTAT);
|
free(ksp, M_KSTAT);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
@ -309,8 +363,13 @@ __kstat_create(const char *module, int instance, const char *name,
|
||||||
SYSCTL_CHILDREN(root),
|
SYSCTL_CHILDREN(root),
|
||||||
OID_AUTO, name, CTLFLAG_RW, 0, "");
|
OID_AUTO, name, CTLFLAG_RW, 0, "");
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
printf("%s: Cannot create kstat.%s.%s.%s tree!\n",
|
if (pool != NULL)
|
||||||
__func__, module, class, name);
|
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);
|
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
|
||||||
free(ksp, M_KSTAT);
|
free(ksp, M_KSTAT);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
@ -411,7 +470,6 @@ kstat_install(kstat_t *ksp)
|
||||||
switch (ksp->ks_type) {
|
switch (ksp->ks_type) {
|
||||||
case KSTAT_TYPE_NAMED:
|
case KSTAT_TYPE_NAMED:
|
||||||
return (kstat_install_named(ksp));
|
return (kstat_install_named(ksp));
|
||||||
break;
|
|
||||||
case KSTAT_TYPE_RAW:
|
case KSTAT_TYPE_RAW:
|
||||||
if (ksp->ks_raw_ops.data) {
|
if (ksp->ks_raw_ops.data) {
|
||||||
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||||
|
@ -426,7 +484,6 @@ kstat_install(kstat_t *ksp)
|
||||||
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||||
ksp, 0, kstat_sysctl_raw, "", ksp->ks_name);
|
ksp, 0, kstat_sysctl_raw, "", ksp->ks_name);
|
||||||
}
|
}
|
||||||
VERIFY(root != NULL);
|
|
||||||
break;
|
break;
|
||||||
case KSTAT_TYPE_IO:
|
case KSTAT_TYPE_IO:
|
||||||
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||||
|
@ -440,6 +497,7 @@ kstat_install(kstat_t *ksp)
|
||||||
default:
|
default:
|
||||||
panic("unsupported kstat type %d\n", ksp->ks_type);
|
panic("unsupported kstat type %d\n", ksp->ks_type);
|
||||||
}
|
}
|
||||||
|
VERIFY(root != NULL);
|
||||||
ksp->ks_sysctl_root = root;
|
ksp->ks_sysctl_root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,74 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/procfs_list.h>
|
#include <sys/procfs_list.h>
|
||||||
|
|
||||||
|
typedef struct procfs_list_iter {
|
||||||
|
procfs_list_t *pli_pl;
|
||||||
|
void *pli_elt;
|
||||||
|
} pli_t;
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
procfs_list_install(const char *module,
|
procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
@ -46,12 +108,31 @@ procfs_list_install(const char *module,
|
||||||
int (*clear)(procfs_list_t *procfs_list),
|
int (*clear)(procfs_list_t *procfs_list),
|
||||||
size_t procfs_list_node_off)
|
size_t procfs_list_node_off)
|
||||||
{
|
{
|
||||||
|
kstat_t *procfs_kstat;
|
||||||
|
|
||||||
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
|
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||||
list_create(&procfs_list->pl_list,
|
list_create(&procfs_list->pl_list,
|
||||||
procfs_list_node_off + sizeof (procfs_list_node_t),
|
procfs_list_node_off + sizeof (procfs_list_node_t),
|
||||||
procfs_list_node_off + offsetof(procfs_list_node_t, pln_link));
|
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_next_id = 1;
|
||||||
procfs_list->pl_node_offset = procfs_list_node_off;
|
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
|
void
|
||||||
|
@ -62,6 +143,7 @@ void
|
||||||
procfs_list_destroy(procfs_list_t *procfs_list)
|
procfs_list_destroy(procfs_list_t *procfs_list)
|
||||||
{
|
{
|
||||||
ASSERT(list_is_empty(&procfs_list->pl_list));
|
ASSERT(list_is_empty(&procfs_list->pl_list));
|
||||||
|
kstat_delete(procfs_list->pl_private);
|
||||||
list_destroy(&procfs_list->pl_list);
|
list_destroy(&procfs_list->pl_list);
|
||||||
mutex_destroy(&procfs_list->pl_lock);
|
mutex_destroy(&procfs_list->pl_lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,7 @@ static const kstat_proc_op_t procfs_list_operations = {
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
procfs_list_install(const char *module,
|
procfs_list_install(const char *module,
|
||||||
|
const char *submodule,
|
||||||
const char *name,
|
const char *name,
|
||||||
mode_t mode,
|
mode_t mode,
|
||||||
procfs_list_t *procfs_list,
|
procfs_list_t *procfs_list,
|
||||||
|
@ -215,6 +216,12 @@ procfs_list_install(const char *module,
|
||||||
int (*clear)(procfs_list_t *procfs_list),
|
int (*clear)(procfs_list_t *procfs_list),
|
||||||
size_t procfs_list_node_off)
|
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);
|
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||||
list_create(&procfs_list->pl_list,
|
list_create(&procfs_list->pl_list,
|
||||||
procfs_list_node_off + sizeof (procfs_list_node_t),
|
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_clear = clear;
|
||||||
procfs_list->pl_node_offset = procfs_list_node_off;
|
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,
|
kstat_proc_entry_install(&procfs_list->pl_kstat_entry, mode,
|
||||||
&procfs_list_operations, procfs_list);
|
&procfs_list_operations, procfs_list);
|
||||||
|
kmem_strfree(modulestr);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(procfs_list_install);
|
EXPORT_SYMBOL(procfs_list_install);
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ void
|
||||||
zfs_dbgmsg_init(void)
|
zfs_dbgmsg_init(void)
|
||||||
{
|
{
|
||||||
procfs_list_install("zfs",
|
procfs_list_install("zfs",
|
||||||
|
NULL,
|
||||||
"dbgmsg",
|
"dbgmsg",
|
||||||
0600,
|
0600,
|
||||||
&zfs_dbgmsgs,
|
&zfs_dbgmsgs,
|
||||||
|
|
|
@ -2169,6 +2169,7 @@ spa_import_progress_init(void)
|
||||||
spa_import_progress_list;
|
spa_import_progress_list;
|
||||||
|
|
||||||
procfs_list_install("zfs",
|
procfs_list_install("zfs",
|
||||||
|
NULL,
|
||||||
"import_progress",
|
"import_progress",
|
||||||
0644,
|
0644,
|
||||||
&spa_import_progress_list->procfs_list,
|
&spa_import_progress_list->procfs_list,
|
||||||
|
|
|
@ -122,14 +122,11 @@ static void
|
||||||
spa_read_history_init(spa_t *spa)
|
spa_read_history_init(spa_t *spa)
|
||||||
{
|
{
|
||||||
spa_history_list_t *shl = &spa->spa_stats.read_history;
|
spa_history_list_t *shl = &spa->spa_stats.read_history;
|
||||||
char *module;
|
|
||||||
|
|
||||||
shl->size = 0;
|
shl->size = 0;
|
||||||
|
|
||||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
|
||||||
|
|
||||||
shl->procfs_list.pl_private = shl;
|
shl->procfs_list.pl_private = shl;
|
||||||
procfs_list_install(module,
|
procfs_list_install("zfs",
|
||||||
|
spa_name(spa),
|
||||||
"reads",
|
"reads",
|
||||||
0600,
|
0600,
|
||||||
&shl->procfs_list,
|
&shl->procfs_list,
|
||||||
|
@ -137,8 +134,6 @@ spa_read_history_init(spa_t *spa)
|
||||||
spa_read_history_show_header,
|
spa_read_history_show_header,
|
||||||
spa_read_history_clear,
|
spa_read_history_clear,
|
||||||
offsetof(spa_read_history_t, srh_node));
|
offsetof(spa_read_history_t, srh_node));
|
||||||
|
|
||||||
kmem_strfree(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -293,14 +288,11 @@ static void
|
||||||
spa_txg_history_init(spa_t *spa)
|
spa_txg_history_init(spa_t *spa)
|
||||||
{
|
{
|
||||||
spa_history_list_t *shl = &spa->spa_stats.txg_history;
|
spa_history_list_t *shl = &spa->spa_stats.txg_history;
|
||||||
char *module;
|
|
||||||
|
|
||||||
shl->size = 0;
|
shl->size = 0;
|
||||||
|
|
||||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
|
||||||
|
|
||||||
shl->procfs_list.pl_private = shl;
|
shl->procfs_list.pl_private = shl;
|
||||||
procfs_list_install(module,
|
procfs_list_install("zfs",
|
||||||
|
spa_name(spa),
|
||||||
"txgs",
|
"txgs",
|
||||||
0644,
|
0644,
|
||||||
&shl->procfs_list,
|
&shl->procfs_list,
|
||||||
|
@ -308,8 +300,6 @@ spa_txg_history_init(spa_t *spa)
|
||||||
spa_txg_history_show_header,
|
spa_txg_history_show_header,
|
||||||
spa_txg_history_clear,
|
spa_txg_history_clear,
|
||||||
offsetof(spa_txg_history_t, sth_node));
|
offsetof(spa_txg_history_t, sth_node));
|
||||||
|
|
||||||
kmem_strfree(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -699,14 +689,12 @@ static void
|
||||||
spa_mmp_history_init(spa_t *spa)
|
spa_mmp_history_init(spa_t *spa)
|
||||||
{
|
{
|
||||||
spa_history_list_t *shl = &spa->spa_stats.mmp_history;
|
spa_history_list_t *shl = &spa->spa_stats.mmp_history;
|
||||||
char *module;
|
|
||||||
|
|
||||||
shl->size = 0;
|
shl->size = 0;
|
||||||
|
|
||||||
module = kmem_asprintf("zfs/%s", spa_name(spa));
|
|
||||||
|
|
||||||
shl->procfs_list.pl_private = shl;
|
shl->procfs_list.pl_private = shl;
|
||||||
procfs_list_install(module,
|
procfs_list_install("zfs",
|
||||||
|
spa_name(spa),
|
||||||
"multihost",
|
"multihost",
|
||||||
0644,
|
0644,
|
||||||
&shl->procfs_list,
|
&shl->procfs_list,
|
||||||
|
@ -714,8 +702,6 @@ spa_mmp_history_init(spa_t *spa)
|
||||||
spa_mmp_history_show_header,
|
spa_mmp_history_show_header,
|
||||||
spa_mmp_history_clear,
|
spa_mmp_history_clear,
|
||||||
offsetof(spa_mmp_history_t, smh_node));
|
offsetof(spa_mmp_history_t, smh_node));
|
||||||
|
|
||||||
kmem_strfree(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue