mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +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
							
								
									227273efa4
								
							
						
					
					
						commit
						c70c6e004e
					
				@ -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