mirror_zfs/include/os/linux/spl/sys/wmsum.h
Alexander Motin 85c43508f3 Introduce write-mostly sums
wmsum counters are a reduced version of aggsum counters, optimized for
write-mostly scenarios.  They do not provide optimized read functions,
but instead allow much cheaper add function.  The primary usage is
infrequently read statistic counters, not requiring exact precision.

The Linux implementation is directly mapped into percpu_counter KPI.
The FreeBSD implementation is directly mapped into counter(9) KPI.
In user-space due to lack of better implementation mapped to aggsum.

Unfortunately neither Linux percpu_counter nor FreeBSD counter(9)
provide sufficient functionality to completelly replace aggsum, so
it still remains to be used for several hot counters.

Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored-By: iXsystems, Inc.
Closes #12114
2021-06-09 13:05:34 -07:00

77 lines
1.6 KiB
C

/*
* CDDL HEADER START
*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*
* CDDL HEADER END
*/
/*
* wmsum counters are a reduced version of aggsum counters, optimized for
* write-mostly scenarios. They do not provide optimized read functions,
* but instead allow much cheaper add function. The primary usage is
* infrequently read statistic counters, not requiring exact precision.
*
* The Linux implementation is directly mapped into percpu_counter KPI.
*/
#ifndef _SYS_WMSUM_H
#define _SYS_WMSUM_H
#include <linux/percpu_counter.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct percpu_counter wmsum_t;
static inline void
wmsum_init(wmsum_t *ws, uint64_t value)
{
#ifdef HAVE_PERCPU_COUNTER_INIT_WITH_GFP
percpu_counter_init(ws, value, GFP_KERNEL);
#else
percpu_counter_init(ws, value);
#endif
}
static inline void
wmsum_fini(wmsum_t *ws)
{
percpu_counter_destroy(ws);
}
static inline uint64_t
wmsum_value(wmsum_t *ws)
{
return (percpu_counter_sum(ws));
}
static inline void
wmsum_add(wmsum_t *ws, int64_t delta)
{
#ifdef HAVE_PERCPU_COUNTER_ADD_BATCH
percpu_counter_add_batch(ws, delta, INT_MAX / 2);
#else
__percpu_counter_add(ws, delta, INT_MAX / 2);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* _SYS_WMSUM_H */