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
9 extern bool disable_send_metrics;
10
11 enum 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 CLIENT_METRIC_TYPE_SUBVOLUME_METRICS,
29
30 CLIENT_METRIC_TYPE_MAX = CLIENT_METRIC_TYPE_SUBVOLUME_METRICS,
31 };
32
33 /*
34 * This will always have the highest metric bit value
35 * as the last element of the array.
36 */
37 #define CEPHFS_METRIC_SPEC_CLIENT_SUPPORTED { \
38 CLIENT_METRIC_TYPE_CAP_INFO, \
39 CLIENT_METRIC_TYPE_READ_LATENCY, \
40 CLIENT_METRIC_TYPE_WRITE_LATENCY, \
41 CLIENT_METRIC_TYPE_METADATA_LATENCY, \
42 CLIENT_METRIC_TYPE_DENTRY_LEASE, \
43 CLIENT_METRIC_TYPE_OPENED_FILES, \
44 CLIENT_METRIC_TYPE_PINNED_ICAPS, \
45 CLIENT_METRIC_TYPE_OPENED_INODES, \
46 CLIENT_METRIC_TYPE_READ_IO_SIZES, \
47 CLIENT_METRIC_TYPE_WRITE_IO_SIZES, \
48 CLIENT_METRIC_TYPE_AVG_READ_LATENCY, \
49 CLIENT_METRIC_TYPE_STDEV_READ_LATENCY, \
50 CLIENT_METRIC_TYPE_AVG_WRITE_LATENCY, \
51 CLIENT_METRIC_TYPE_STDEV_WRITE_LATENCY, \
52 CLIENT_METRIC_TYPE_AVG_METADATA_LATENCY, \
53 CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY, \
54 CLIENT_METRIC_TYPE_SUBVOLUME_METRICS, \
55 \
56 CLIENT_METRIC_TYPE_MAX, \
57 }
58
59 struct ceph_metric_header {
60 __le32 type; /* ceph metric type */
61 __u8 ver;
62 __u8 compat;
63 __le32 data_len; /* length of sizeof(hit + mis + total) */
64 } __packed;
65
66 /* metric caps header */
67 struct ceph_metric_cap {
68 struct ceph_metric_header header;
69 __le64 hit;
70 __le64 mis;
71 __le64 total;
72 } __packed;
73
74 /* metric read latency header */
75 struct ceph_metric_read_latency {
76 struct ceph_metric_header header;
77 struct ceph_timespec lat;
78 struct ceph_timespec avg;
79 __le64 sq_sum;
80 __le64 count;
81 } __packed;
82
83 /* metric write latency header */
84 struct ceph_metric_write_latency {
85 struct ceph_metric_header header;
86 struct ceph_timespec lat;
87 struct ceph_timespec avg;
88 __le64 sq_sum;
89 __le64 count;
90 } __packed;
91
92 /* metric metadata latency header */
93 struct ceph_metric_metadata_latency {
94 struct ceph_metric_header header;
95 struct ceph_timespec lat;
96 struct ceph_timespec avg;
97 __le64 sq_sum;
98 __le64 count;
99 } __packed;
100
101 /* metric dentry lease header */
102 struct ceph_metric_dlease {
103 struct ceph_metric_header header;
104 __le64 hit;
105 __le64 mis;
106 __le64 total;
107 } __packed;
108
109 /* metric opened files header */
110 struct ceph_opened_files {
111 struct ceph_metric_header header;
112 __le64 opened_files;
113 __le64 total;
114 } __packed;
115
116 /* metric pinned i_caps header */
117 struct ceph_pinned_icaps {
118 struct ceph_metric_header header;
119 __le64 pinned_icaps;
120 __le64 total;
121 } __packed;
122
123 /* metric opened inodes header */
124 struct ceph_opened_inodes {
125 struct ceph_metric_header header;
126 __le64 opened_inodes;
127 __le64 total;
128 } __packed;
129
130 /* metric read io size header */
131 struct ceph_read_io_size {
132 struct ceph_metric_header header;
133 __le64 total_ops;
134 __le64 total_size;
135 } __packed;
136
137 /* metric write io size header */
138 struct ceph_write_io_size {
139 struct ceph_metric_header header;
140 __le64 total_ops;
141 __le64 total_size;
142 } __packed;
143
144 /**
145 * struct ceph_subvolume_metric_entry_wire - On-wire format sent to MDS
146 * @subvolume_id: Subvolume identifier
147 * @read_ops: Read operation count (32-bit, clamped from 64-bit internal)
148 * @write_ops: Write operation count (32-bit, clamped from 64-bit internal)
149 * @read_bytes: Total bytes read
150 * @write_bytes: Total bytes written
151 * @read_latency_us: Cumulative read latency in microseconds
152 * @write_latency_us: Cumulative write latency in microseconds
153 * @time_stamp: Collection timestamp (currently unused, set to 0)
154 *
155 * Wire format must match C++ AggregatedIOMetrics struct in MDS.
156 */
157 struct ceph_subvolume_metric_entry_wire {
158 __le64 subvolume_id;
159 __le32 read_ops;
160 __le32 write_ops;
161 __le64 read_bytes;
162 __le64 write_bytes;
163 __le64 read_latency_us;
164 __le64 write_latency_us;
165 __le64 time_stamp;
166 } __packed;
167
168 /* Old struct kept for internal tracking, not used on wire */
169 struct ceph_subvolume_metric_entry {
170 __le64 subvolume_id;
171 __le64 read_ops;
172 __le64 write_ops;
173 __le64 read_bytes;
174 __le64 write_bytes;
175 __le64 read_latency_us;
176 __le64 write_latency_us;
177 } __packed;
178
179 struct ceph_metric_head {
180 __le32 num; /* the number of metrics that will be sent */
181 } __packed;
182
183 enum metric_type {
184 METRIC_READ,
185 METRIC_WRITE,
186 METRIC_METADATA,
187 METRIC_COPYFROM,
188 METRIC_MAX
189 };
190
191 struct ceph_metric {
192 spinlock_t lock;
193 u64 total;
194 u64 size_sum;
195 u64 size_min;
196 u64 size_max;
197 ktime_t latency_sum;
198 ktime_t latency_avg;
199 ktime_t latency_sq_sum;
200 ktime_t latency_min;
201 ktime_t latency_max;
202 };
203
204 /* This is the global metrics */
205 struct ceph_client_metric {
206 atomic64_t total_dentries;
207 struct percpu_counter d_lease_hit;
208 struct percpu_counter d_lease_mis;
209
210 atomic64_t total_caps;
211 struct percpu_counter i_caps_hit;
212 struct percpu_counter i_caps_mis;
213
214 struct ceph_metric metric[METRIC_MAX];
215
216 /* The total number of directories and files that are opened */
217 atomic64_t opened_files;
218
219 /* The total number of inodes that have opened files or directories */
220 struct percpu_counter opened_inodes;
221 struct percpu_counter total_inodes;
222
223 struct ceph_mds_session *session;
224 struct delayed_work delayed_work; /* delayed work */
225 };
226
metric_schedule_delayed(struct ceph_client_metric * m)227 static inline void metric_schedule_delayed(struct ceph_client_metric *m)
228 {
229 if (disable_send_metrics)
230 return;
231
232 /* per second */
233 schedule_delayed_work(&m->delayed_work, round_jiffies_relative(HZ));
234 }
235
236 extern int ceph_metric_init(struct ceph_client_metric *m);
237 extern void ceph_metric_destroy(struct ceph_client_metric *m);
238
ceph_update_cap_hit(struct ceph_client_metric * m)239 static inline void ceph_update_cap_hit(struct ceph_client_metric *m)
240 {
241 percpu_counter_inc(&m->i_caps_hit);
242 }
243
ceph_update_cap_mis(struct ceph_client_metric * m)244 static inline void ceph_update_cap_mis(struct ceph_client_metric *m)
245 {
246 percpu_counter_inc(&m->i_caps_mis);
247 }
248
249 extern void ceph_update_metrics(struct ceph_metric *m,
250 ktime_t r_start, ktime_t r_end,
251 unsigned int size, int rc);
252
ceph_update_read_metrics(struct ceph_client_metric * m,ktime_t r_start,ktime_t r_end,unsigned int size,int rc)253 static inline void ceph_update_read_metrics(struct ceph_client_metric *m,
254 ktime_t r_start, ktime_t r_end,
255 unsigned int size, int rc)
256 {
257 ceph_update_metrics(&m->metric[METRIC_READ],
258 r_start, r_end, size, rc);
259 }
ceph_update_write_metrics(struct ceph_client_metric * m,ktime_t r_start,ktime_t r_end,unsigned int size,int rc)260 static inline void ceph_update_write_metrics(struct ceph_client_metric *m,
261 ktime_t r_start, ktime_t r_end,
262 unsigned int size, int rc)
263 {
264 ceph_update_metrics(&m->metric[METRIC_WRITE],
265 r_start, r_end, size, rc);
266 }
ceph_update_metadata_metrics(struct ceph_client_metric * m,ktime_t r_start,ktime_t r_end,int rc)267 static inline void ceph_update_metadata_metrics(struct ceph_client_metric *m,
268 ktime_t r_start, ktime_t r_end,
269 int rc)
270 {
271 ceph_update_metrics(&m->metric[METRIC_METADATA],
272 r_start, r_end, 0, rc);
273 }
ceph_update_copyfrom_metrics(struct ceph_client_metric * m,ktime_t r_start,ktime_t r_end,unsigned int size,int rc)274 static inline void ceph_update_copyfrom_metrics(struct ceph_client_metric *m,
275 ktime_t r_start, ktime_t r_end,
276 unsigned int size, int rc)
277 {
278 ceph_update_metrics(&m->metric[METRIC_COPYFROM],
279 r_start, r_end, size, rc);
280 }
281 #endif /* _FS_CEPH_MDS_METRIC_H */
282