1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _FS_CEPH_MDS_METRIC_H
3#define _FS_CEPH_MDS_METRIC_H
4
5#include <linux/ceph/types.h>
6#include <linux/percpu_counter.h>
7#include <linux/ktime.h>
8
9extern bool disable_send_metrics;
10
11enum ceph_metric_type {
12	CLIENT_METRIC_TYPE_CAP_INFO,
13	CLIENT_METRIC_TYPE_READ_LATENCY,
14	CLIENT_METRIC_TYPE_WRITE_LATENCY,
15	CLIENT_METRIC_TYPE_METADATA_LATENCY,
16	CLIENT_METRIC_TYPE_DENTRY_LEASE,
17	CLIENT_METRIC_TYPE_OPENED_FILES,
18	CLIENT_METRIC_TYPE_PINNED_ICAPS,
19	CLIENT_METRIC_TYPE_OPENED_INODES,
20	CLIENT_METRIC_TYPE_READ_IO_SIZES,
21	CLIENT_METRIC_TYPE_WRITE_IO_SIZES,
22	CLIENT_METRIC_TYPE_AVG_READ_LATENCY,
23	CLIENT_METRIC_TYPE_STDEV_READ_LATENCY,
24	CLIENT_METRIC_TYPE_AVG_WRITE_LATENCY,
25	CLIENT_METRIC_TYPE_STDEV_WRITE_LATENCY,
26	CLIENT_METRIC_TYPE_AVG_METADATA_LATENCY,
27	CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY,
28
29	CLIENT_METRIC_TYPE_MAX = CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY,
30};
31
32/*
33 * This will always have the highest metric bit value
34 * as the last element of the array.
35 */
36#define CEPHFS_METRIC_SPEC_CLIENT_SUPPORTED {	   \
37	CLIENT_METRIC_TYPE_CAP_INFO,		   \
38	CLIENT_METRIC_TYPE_READ_LATENCY,	   \
39	CLIENT_METRIC_TYPE_WRITE_LATENCY,	   \
40	CLIENT_METRIC_TYPE_METADATA_LATENCY,	   \
41	CLIENT_METRIC_TYPE_DENTRY_LEASE,	   \
42	CLIENT_METRIC_TYPE_OPENED_FILES,	   \
43	CLIENT_METRIC_TYPE_PINNED_ICAPS,	   \
44	CLIENT_METRIC_TYPE_OPENED_INODES,	   \
45	CLIENT_METRIC_TYPE_READ_IO_SIZES,	   \
46	CLIENT_METRIC_TYPE_WRITE_IO_SIZES,	   \
47	CLIENT_METRIC_TYPE_AVG_READ_LATENCY,	   \
48	CLIENT_METRIC_TYPE_STDEV_READ_LATENCY,	   \
49	CLIENT_METRIC_TYPE_AVG_WRITE_LATENCY,	   \
50	CLIENT_METRIC_TYPE_STDEV_WRITE_LATENCY,	   \
51	CLIENT_METRIC_TYPE_AVG_METADATA_LATENCY,   \
52	CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY, \
53						   \
54	CLIENT_METRIC_TYPE_MAX,			   \
55}
56
57struct ceph_metric_header {
58	__le32 type;     /* ceph metric type */
59	__u8  ver;
60	__u8  compat;
61	__le32 data_len; /* length of sizeof(hit + mis + total) */
62} __packed;
63
64/* metric caps header */
65struct ceph_metric_cap {
66	struct ceph_metric_header header;
67	__le64 hit;
68	__le64 mis;
69	__le64 total;
70} __packed;
71
72/* metric read latency header */
73struct ceph_metric_read_latency {
74	struct ceph_metric_header header;
75	struct ceph_timespec lat;
76	struct ceph_timespec avg;
77	__le64 sq_sum;
78	__le64 count;
79} __packed;
80
81/* metric write latency header */
82struct ceph_metric_write_latency {
83	struct ceph_metric_header header;
84	struct ceph_timespec lat;
85	struct ceph_timespec avg;
86	__le64 sq_sum;
87	__le64 count;
88} __packed;
89
90/* metric metadata latency header */
91struct ceph_metric_metadata_latency {
92	struct ceph_metric_header header;
93	struct ceph_timespec lat;
94	struct ceph_timespec avg;
95	__le64 sq_sum;
96	__le64 count;
97} __packed;
98
99/* metric dentry lease header */
100struct ceph_metric_dlease {
101	struct ceph_metric_header header;
102	__le64 hit;
103	__le64 mis;
104	__le64 total;
105} __packed;
106
107/* metric opened files header */
108struct ceph_opened_files {
109	struct ceph_metric_header header;
110	__le64 opened_files;
111	__le64 total;
112} __packed;
113
114/* metric pinned i_caps header */
115struct ceph_pinned_icaps {
116	struct ceph_metric_header header;
117	__le64 pinned_icaps;
118	__le64 total;
119} __packed;
120
121/* metric opened inodes header */
122struct ceph_opened_inodes {
123	struct ceph_metric_header header;
124	__le64 opened_inodes;
125	__le64 total;
126} __packed;
127
128/* metric read io size header */
129struct ceph_read_io_size {
130	struct ceph_metric_header header;
131	__le64 total_ops;
132	__le64 total_size;
133} __packed;
134
135/* metric write io size header */
136struct ceph_write_io_size {
137	struct ceph_metric_header header;
138	__le64 total_ops;
139	__le64 total_size;
140} __packed;
141
142struct ceph_metric_head {
143	__le32 num;	/* the number of metrics that will be sent */
144} __packed;
145
146enum metric_type {
147	METRIC_READ,
148	METRIC_WRITE,
149	METRIC_METADATA,
150	METRIC_COPYFROM,
151	METRIC_MAX
152};
153
154struct ceph_metric {
155	spinlock_t lock;
156	u64 total;
157	u64 size_sum;
158	u64 size_min;
159	u64 size_max;
160	ktime_t latency_sum;
161	ktime_t latency_avg;
162	ktime_t latency_sq_sum;
163	ktime_t latency_min;
164	ktime_t latency_max;
165};
166
167/* This is the global metrics */
168struct ceph_client_metric {
169	atomic64_t            total_dentries;
170	struct percpu_counter d_lease_hit;
171	struct percpu_counter d_lease_mis;
172
173	atomic64_t            total_caps;
174	struct percpu_counter i_caps_hit;
175	struct percpu_counter i_caps_mis;
176
177	struct ceph_metric metric[METRIC_MAX];
178
179	/* The total number of directories and files that are opened */
180	atomic64_t opened_files;
181
182	/* The total number of inodes that have opened files or directories */
183	struct percpu_counter opened_inodes;
184	struct percpu_counter total_inodes;
185
186	struct ceph_mds_session *session;
187	struct delayed_work delayed_work;  /* delayed work */
188};
189
190static inline void metric_schedule_delayed(struct ceph_client_metric *m)
191{
192	if (disable_send_metrics)
193		return;
194
195	/* per second */
196	schedule_delayed_work(&m->delayed_work, round_jiffies_relative(HZ));
197}
198
199extern int ceph_metric_init(struct ceph_client_metric *m);
200extern void ceph_metric_destroy(struct ceph_client_metric *m);
201
202static inline void ceph_update_cap_hit(struct ceph_client_metric *m)
203{
204	percpu_counter_inc(&m->i_caps_hit);
205}
206
207static inline void ceph_update_cap_mis(struct ceph_client_metric *m)
208{
209	percpu_counter_inc(&m->i_caps_mis);
210}
211
212extern void ceph_update_metrics(struct ceph_metric *m,
213				ktime_t r_start, ktime_t r_end,
214				unsigned int size, int rc);
215
216static inline void ceph_update_read_metrics(struct ceph_client_metric *m,
217					    ktime_t r_start, ktime_t r_end,
218					    unsigned int size, int rc)
219{
220	ceph_update_metrics(&m->metric[METRIC_READ],
221			    r_start, r_end, size, rc);
222}
223static inline void ceph_update_write_metrics(struct ceph_client_metric *m,
224					     ktime_t r_start, ktime_t r_end,
225					     unsigned int size, int rc)
226{
227	ceph_update_metrics(&m->metric[METRIC_WRITE],
228			    r_start, r_end, size, rc);
229}
230static inline void ceph_update_metadata_metrics(struct ceph_client_metric *m,
231						ktime_t r_start, ktime_t r_end,
232						int rc)
233{
234	ceph_update_metrics(&m->metric[METRIC_METADATA],
235			    r_start, r_end, 0, rc);
236}
237static inline void ceph_update_copyfrom_metrics(struct ceph_client_metric *m,
238						ktime_t r_start, ktime_t r_end,
239						unsigned int size, int rc)
240{
241	ceph_update_metrics(&m->metric[METRIC_COPYFROM],
242			    r_start, r_end, size, rc);
243}
244#endif /* _FS_CEPH_MDS_METRIC_H */
245