fusefs: convert statistical sysctls to use counter(9)

counter(9) is more performant than using atomic instructions to update
sysctls that just report statistics to userland.

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-06-27 16:30:25 +00:00
parent caeea8b4cc
commit 560a55d094
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=349462
11 changed files with 118 additions and 46 deletions

View File

@ -28,7 +28,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.Dd June 26, 2019
.Dd June 27, 2019
.Dt FUSEFS 5
.Os
.Sh NAME
@ -60,11 +60,9 @@ Finally, the
API is portable.
Many daemons can run on multiple operating systems with minimal modifications.
.Sh SYSCTL VARIABLES
The following variables are available as both
The following
.Xr sysctl 8
variables and
.Xr loader 8
tunables:
variables are available:
.Bl -tag -width indent
.It Va vfs.fusefs.kernelabi_major
Major version of the FUSE kernel ABI supported by this driver.
@ -87,14 +85,19 @@ require network access.
.Pp
FUSE file systems using protocol 7.23 or later specify their cache behavior
on a per-mountpoint basis, ignoring this sysctl.
.It Va vfs.fusefs.stats.filehandle_count
Current number of open FUSE file handles.
.It Va vfs.fusefs.stats.lookup_cache_hits
Total number of lookup cache hits.
.It Va vfs.fusefs.stats.lookup_cache_misses
Total number of lookup cache misses.
.It Va vfs.fusefs.stats.node_count
Current number of allocated FUSE vnodes.
.It Va vfs.fusefs.stats.ticket_count
Current number of allocated FUSE tickets, which is roughly equal to the number
number of FUSE operations currently being processed by daemons.
.\" Undocumented sysctls
.\" ====================
.\" Counters: I intend to rename to vfs.fusefs.stats.* for clarity
.\" vfs.fusefs.lookup_cache_{hits, misses}
.\" vfs.fusefs.filehandle_count
.\" vfs.fusefs.ticker_count
.\" vfs.fusefs.node_count
.\"
.\" vfs.fusefs.reclaim_revoked: I don't understand it well-enough
.\" vfs.fusefs.enforce_dev_perms: I don't understand it well enough.
.\" vfs.fusefs.iov_credit: I don't understand it well enough

View File

@ -66,6 +66,7 @@
/* misc */
SYSCTL_DECL(_vfs_fusefs);
SYSCTL_DECL(_vfs_fusefs_stats);
/* Fuse locking */

View File

@ -59,6 +59,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/counter.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
@ -93,10 +94,10 @@ SDT_PROVIDER_DECLARE(fusefs);
*/
SDT_PROBE_DEFINE2(fusefs, , file, trace, "int", "char*");
static int fuse_fh_count = 0;
static counter_u64_t fuse_fh_count = 0;
SYSCTL_INT(_vfs_fusefs, OID_AUTO, filehandle_count, CTLFLAG_RD,
&fuse_fh_count, 0, "number of open FUSE filehandles");
SYSCTL_COUNTER_U64(_vfs_fusefs_stats, OID_AUTO, filehandle_count, CTLFLAG_RD,
&fuse_fh_count, "number of open FUSE filehandles");
/* Get the FUFH type for a particular access mode */
static inline fufh_type_t
@ -190,7 +191,7 @@ fuse_filehandle_close(struct vnode *vp, struct fuse_filehandle *fufh,
fdisp_destroy(&fdi);
out:
atomic_subtract_acq_int(&fuse_fh_count, 1);
counter_u64_add(fuse_fh_count, -1);
LIST_REMOVE(fufh, next);
free(fufh, M_FUSE_FILEHANDLE);
@ -343,7 +344,7 @@ fuse_filehandle_init(struct vnode *vp, fufh_type_t fufh_type,
if (fufhp != NULL)
*fufhp = fufh;
atomic_add_acq_int(&fuse_fh_count, 1);
counter_u64_add(fuse_fh_count, 1);
if (foo->open_flags & FOPEN_DIRECT_IO) {
ASSERT_VOP_ELOCKED(vp, __func__);
@ -356,3 +357,16 @@ fuse_filehandle_init(struct vnode *vp, fufh_type_t fufh_type,
}
}
void
fuse_file_init(void)
{
fuse_fh_count = counter_u64_alloc(M_WAITOK);
counter_u64_zero(fuse_fh_count);
}
void
fuse_file_destroy(void)
{
counter_u64_free(fuse_fh_count);
}

View File

@ -213,4 +213,7 @@ int fuse_filehandle_open(struct vnode *vp, int mode,
int fuse_filehandle_close(struct vnode *vp, struct fuse_filehandle *fufh,
struct thread *td, struct ucred *cred);
void fuse_file_init(void);
void fuse_file_destroy(void);
#endif /* _FUSE_FILE_H_ */

View File

@ -59,6 +59,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/counter.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
@ -107,6 +108,15 @@ static int isbzero(void *buf, size_t len);
#endif
counter_u64_t fuse_lookup_cache_hits = 0;
counter_u64_t fuse_lookup_cache_misses = 0;
SYSCTL_COUNTER_U64(_vfs_fusefs_stats, OID_AUTO, lookup_cache_hits, CTLFLAG_RD,
&fuse_lookup_cache_hits, "number of positive cache hits in lookup");
SYSCTL_COUNTER_U64(_vfs_fusefs_stats, OID_AUTO, lookup_cache_misses, CTLFLAG_RD,
&fuse_lookup_cache_misses, "number of cache misses in lookup");
int
fuse_internal_get_cached_vnode(struct mount* mp, ino_t ino, int flags,
struct vnode **vpp)
@ -130,11 +140,11 @@ fuse_internal_get_cached_vnode(struct mount* mp, ino_t ino, int flags,
if (*vpp != NULL) {
getbinuptime(&now);
if (bintime_cmp(&(VTOFUD(*vpp)->entry_cache_timeout), &now, >)){
atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
counter_u64_add(fuse_lookup_cache_hits, 1);
return 0;
} else {
/* Entry cache timeout */
atomic_add_acq_long(&fuse_lookup_cache_misses, 1);
counter_u64_add(fuse_lookup_cache_misses, 1);
cache_purge(*vpp);
vput(*vpp);
*vpp = NULL;
@ -1157,3 +1167,19 @@ isbzero(void *buf, size_t len)
}
#endif
void
fuse_internal_init(void)
{
fuse_lookup_cache_misses = counter_u64_alloc(M_WAITOK);
counter_u64_zero(fuse_lookup_cache_misses);
fuse_lookup_cache_hits = counter_u64_alloc(M_WAITOK);
counter_u64_zero(fuse_lookup_cache_hits);
}
void
fuse_internal_destroy(void)
{
counter_u64_free(fuse_lookup_cache_hits);
counter_u64_free(fuse_lookup_cache_misses);
}

View File

@ -61,6 +61,7 @@
#define _FUSE_INTERNAL_H_
#include <sys/types.h>
#include <sys/counter.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/vnode.h>
@ -68,8 +69,8 @@
#include "fuse_ipc.h"
#include "fuse_node.h"
extern u_long fuse_lookup_cache_hits;
extern u_long fuse_lookup_cache_misses;
extern counter_u64_t fuse_lookup_cache_hits;
extern counter_u64_t fuse_lookup_cache_misses;
static inline bool
vfs_isrdonly(struct mount *mp)
@ -312,4 +313,8 @@ void fuse_internal_forget_send(struct mount *mp, struct thread *td,
int fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio);
void fuse_internal_send_init(struct fuse_data *data, struct thread *td);
/* module load/unload */
void fuse_internal_init(void);
void fuse_internal_destroy(void);
#endif /* _FUSE_INTERNAL_H_ */

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/counter.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/conf.h>
@ -107,11 +108,10 @@ static int fuse_body_audit(struct fuse_ticket *ftick, size_t blen);
static fuse_handler_t fuse_standard_handler;
SYSCTL_NODE(_vfs, OID_AUTO, fusefs, CTLFLAG_RW, 0, "FUSE tunables");
static int fuse_ticket_count = 0;
static counter_u64_t fuse_ticket_count;
SYSCTL_COUNTER_U64(_vfs_fusefs_stats, OID_AUTO, ticket_count, CTLFLAG_RD,
&fuse_ticket_count, "Number of allocated tickets");
SYSCTL_INT(_vfs_fusefs, OID_AUTO, ticket_count, CTLFLAG_RW,
&fuse_ticket_count, 0, "number of allocated tickets");
static long fuse_iov_permanent_bufsize = 1 << 19;
SYSCTL_LONG(_vfs_fusefs, OID_AUTO, iov_permanent_bufsize, CTLFLAG_RW,
@ -326,7 +326,7 @@ fticket_ctor(void *mem, int size, void *arg, int flags)
ftick->irq_unique = 0;
refcount_init(&ftick->tk_refcount, 1);
atomic_add_acq_int(&fuse_ticket_count, 1);
counter_u64_add(fuse_ticket_count, 1);
return 0;
}
@ -341,7 +341,7 @@ fticket_dtor(void *mem, int size, void *arg)
FUSE_ASSERT_MS_DONE(ftick);
FUSE_ASSERT_AW_DONE(ftick);
atomic_subtract_acq_int(&fuse_ticket_count, 1);
counter_u64_add(fuse_ticket_count, -1);
}
static int
@ -1075,10 +1075,13 @@ fuse_ipc_init(void)
ticket_zone = uma_zcreate("fuse_ticket", sizeof(struct fuse_ticket),
fticket_ctor, fticket_dtor, fticket_init, fticket_fini,
UMA_ALIGN_PTR, 0);
fuse_ticket_count = counter_u64_alloc(M_WAITOK);
counter_u64_zero(fuse_ticket_count);
}
void
fuse_ipc_destroy(void)
{
counter_u64_free(fuse_ticket_count);
uma_zdestroy(ticket_zone);
}

View File

@ -77,6 +77,10 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include "fuse.h"
#include "fuse_file.h"
#include "fuse_ipc.h"
#include "fuse_internal.h"
#include "fuse_node.h"
static void fuse_bringdown(eventhandler_tag eh_tag);
static int fuse_loader(struct module *m, int what, void *arg);
@ -97,6 +101,8 @@ static struct vfsconf fuse_vfsconf = {
.vfc_flags = VFCF_JAIL | VFCF_SYNTHETIC
};
SYSCTL_NODE(_vfs, OID_AUTO, fusefs, CTLFLAG_RW, 0, "FUSE tunables");
SYSCTL_NODE(_vfs_fusefs, OID_AUTO, stats, CTLFLAG_RW, 0, "FUSE statistics");
SYSCTL_INT(_vfs_fusefs, OID_AUTO, kernelabi_major, CTLFLAG_RD,
SYSCTL_NULL_INT_PTR, FUSE_KERNEL_VERSION, "FUSE kernel abi major version");
SYSCTL_INT(_vfs_fusefs, OID_AUTO, kernelabi_minor, CTLFLAG_RD,
@ -112,7 +118,9 @@ SDT_PROVIDER_DEFINE(fusefs);
static void
fuse_bringdown(eventhandler_tag eh_tag)
{
fuse_node_destroy();
fuse_internal_destroy();
fuse_file_destroy();
fuse_ipc_destroy();
fuse_device_destroy();
mtx_destroy(&fuse_mtx);
@ -133,6 +141,9 @@ fuse_loader(struct module *m, int what, void *arg)
return (err);
}
fuse_ipc_init();
fuse_file_init();
fuse_internal_init();
fuse_node_init();
fuse_pbuf_zone = pbuf_zsecond_create("fusepbuf", nswbuf / 2);
/* vfs_modevent ignores its first arg */

View File

@ -59,6 +59,7 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/counter.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
@ -101,10 +102,10 @@ MALLOC_DEFINE(M_FUSEVN, "fuse_vnode", "fuse vnode private data");
static int sysctl_fuse_cache_mode(SYSCTL_HANDLER_ARGS);
static int fuse_node_count = 0;
static counter_u64_t fuse_node_count;
SYSCTL_INT(_vfs_fusefs, OID_AUTO, node_count, CTLFLAG_RD,
&fuse_node_count, 0, "Count of FUSE vnodes");
SYSCTL_COUNTER_U64(_vfs_fusefs_stats, OID_AUTO, node_count, CTLFLAG_RD,
&fuse_node_count, "Count of FUSE vnodes");
int fuse_data_cache_mode = FUSE_CACHE_WT;
@ -158,7 +159,7 @@ fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
vp->v_type = vtyp;
vp->v_data = fvdat;
atomic_add_acq_int(&fuse_node_count, 1);
counter_u64_add(fuse_node_count, 1);
}
void
@ -171,7 +172,7 @@ fuse_vnode_destroy(struct vnode *vp)
("Destroying fuse vnode with open files!"));
free(fvdat, M_FUSEVN);
atomic_subtract_acq_int(&fuse_node_count, 1);
counter_u64_add(fuse_node_count, -1);
}
int
@ -480,3 +481,16 @@ fuse_vnode_update(struct vnode *vp, int flags)
fvdat->flag |= flags;
}
void
fuse_node_init(void)
{
fuse_node_count = counter_u64_alloc(M_WAITOK);
counter_u64_zero(fuse_node_count);
}
void
fuse_node_destroy(void)
{
counter_u64_free(fuse_node_count);
}

View File

@ -191,4 +191,7 @@ int fuse_vnode_setsize(struct vnode *vp, off_t newsize);
void fuse_vnode_undirty_cached_timestamps(struct vnode *vp);
void fuse_vnode_update(struct vnode *vp, int flags);
void fuse_node_init(void);
void fuse_node_destroy(void);
#endif /* _FUSE_NODE_H_ */

View File

@ -218,16 +218,6 @@ struct vop_vector fuse_vnops = {
.vop_vptofh = fuse_vnop_vptofh,
};
u_long fuse_lookup_cache_hits = 0;
SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_hits, CTLFLAG_RD,
&fuse_lookup_cache_hits, 0, "number of positive cache hits in lookup");
u_long fuse_lookup_cache_misses = 0;
SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD,
&fuse_lookup_cache_misses, 0, "number of cache misses in lookup");
/*
* XXX: This feature is highly experimental and can bring to instabilities,
* needs revisiting before to be enabled by default.
@ -1048,11 +1038,10 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
switch (err) {
case -1: /* positive match */
if (timespeccmp(&timeout, &now, >)) {
atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
counter_u64_add(fuse_lookup_cache_hits, 1);
} else {
/* Cache timeout */
atomic_add_acq_long(&fuse_lookup_cache_misses,
1);
counter_u64_add(fuse_lookup_cache_misses, 1);
bintime_clear(
&VTOFUD(*vpp)->entry_cache_timeout);
cache_purge(*vpp);
@ -1066,7 +1055,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
return 0;
case 0: /* no match in cache */
atomic_add_acq_long(&fuse_lookup_cache_misses, 1);
counter_u64_add(fuse_lookup_cache_misses, 1);
break;
case ENOENT: /* negative match */