xref: /linux/fs/ceph/subvolume_metrics.h (revision ac2dc6d57425ffa9629941d7c9d7c0e51082cb5a)
1*b1137e0bSAlex Markuze /* SPDX-License-Identifier: GPL-2.0 */
2*b1137e0bSAlex Markuze #ifndef _FS_CEPH_SUBVOLUME_METRICS_H
3*b1137e0bSAlex Markuze #define _FS_CEPH_SUBVOLUME_METRICS_H
4*b1137e0bSAlex Markuze 
5*b1137e0bSAlex Markuze #include <linux/types.h>
6*b1137e0bSAlex Markuze #include <linux/rbtree.h>
7*b1137e0bSAlex Markuze #include <linux/spinlock.h>
8*b1137e0bSAlex Markuze #include <linux/ktime.h>
9*b1137e0bSAlex Markuze #include <linux/atomic.h>
10*b1137e0bSAlex Markuze 
11*b1137e0bSAlex Markuze struct seq_file;
12*b1137e0bSAlex Markuze struct ceph_mds_client;
13*b1137e0bSAlex Markuze struct ceph_inode_info;
14*b1137e0bSAlex Markuze 
15*b1137e0bSAlex Markuze /**
16*b1137e0bSAlex Markuze  * struct ceph_subvol_metric_snapshot - Point-in-time snapshot of subvolume metrics
17*b1137e0bSAlex Markuze  * @subvolume_id: Subvolume identifier (inode number of subvolume root)
18*b1137e0bSAlex Markuze  * @read_ops: Number of read operations since last snapshot
19*b1137e0bSAlex Markuze  * @write_ops: Number of write operations since last snapshot
20*b1137e0bSAlex Markuze  * @read_bytes: Total bytes read since last snapshot
21*b1137e0bSAlex Markuze  * @write_bytes: Total bytes written since last snapshot
22*b1137e0bSAlex Markuze  * @read_latency_us: Sum of read latencies in microseconds (for avg calculation)
23*b1137e0bSAlex Markuze  * @write_latency_us: Sum of write latencies in microseconds (for avg calculation)
24*b1137e0bSAlex Markuze  */
25*b1137e0bSAlex Markuze struct ceph_subvol_metric_snapshot {
26*b1137e0bSAlex Markuze 	u64 subvolume_id;
27*b1137e0bSAlex Markuze 	u64 read_ops;
28*b1137e0bSAlex Markuze 	u64 write_ops;
29*b1137e0bSAlex Markuze 	u64 read_bytes;
30*b1137e0bSAlex Markuze 	u64 write_bytes;
31*b1137e0bSAlex Markuze 	u64 read_latency_us;
32*b1137e0bSAlex Markuze 	u64 write_latency_us;
33*b1137e0bSAlex Markuze };
34*b1137e0bSAlex Markuze 
35*b1137e0bSAlex Markuze /**
36*b1137e0bSAlex Markuze  * struct ceph_subvolume_metrics_tracker - Tracks per-subvolume I/O metrics
37*b1137e0bSAlex Markuze  * @lock: Protects @tree and @nr_entries during concurrent access
38*b1137e0bSAlex Markuze  * @tree: Red-black tree of per-subvolume entries, keyed by subvolume_id
39*b1137e0bSAlex Markuze  * @nr_entries: Number of entries currently in @tree
40*b1137e0bSAlex Markuze  * @enabled: Whether collection is enabled (requires MDS feature support)
41*b1137e0bSAlex Markuze  * @snapshot_attempts: Debug counter: total ceph_subvolume_metrics_snapshot() calls
42*b1137e0bSAlex Markuze  * @snapshot_empty: Debug counter: snapshots that found no data to report
43*b1137e0bSAlex Markuze  * @snapshot_failures: Debug counter: snapshots that failed to allocate memory
44*b1137e0bSAlex Markuze  * @record_calls: Debug counter: total ceph_subvolume_metrics_record() calls
45*b1137e0bSAlex Markuze  * @record_disabled: Debug counter: record calls skipped because disabled
46*b1137e0bSAlex Markuze  * @record_no_subvol: Debug counter: record calls skipped (no subvolume_id)
47*b1137e0bSAlex Markuze  * @total_read_ops: Cumulative read ops across all snapshots (never reset)
48*b1137e0bSAlex Markuze  * @total_read_bytes: Cumulative bytes read across all snapshots (never reset)
49*b1137e0bSAlex Markuze  * @total_write_ops: Cumulative write ops across all snapshots (never reset)
50*b1137e0bSAlex Markuze  * @total_write_bytes: Cumulative bytes written across all snapshots (never reset)
51*b1137e0bSAlex Markuze  */
52*b1137e0bSAlex Markuze struct ceph_subvolume_metrics_tracker {
53*b1137e0bSAlex Markuze 	spinlock_t lock;
54*b1137e0bSAlex Markuze 	struct rb_root_cached tree;
55*b1137e0bSAlex Markuze 	u32 nr_entries;
56*b1137e0bSAlex Markuze 	bool enabled;
57*b1137e0bSAlex Markuze 	atomic64_t snapshot_attempts;
58*b1137e0bSAlex Markuze 	atomic64_t snapshot_empty;
59*b1137e0bSAlex Markuze 	atomic64_t snapshot_failures;
60*b1137e0bSAlex Markuze 	atomic64_t record_calls;
61*b1137e0bSAlex Markuze 	atomic64_t record_disabled;
62*b1137e0bSAlex Markuze 	atomic64_t record_no_subvol;
63*b1137e0bSAlex Markuze 	atomic64_t total_read_ops;
64*b1137e0bSAlex Markuze 	atomic64_t total_read_bytes;
65*b1137e0bSAlex Markuze 	atomic64_t total_write_ops;
66*b1137e0bSAlex Markuze 	atomic64_t total_write_bytes;
67*b1137e0bSAlex Markuze };
68*b1137e0bSAlex Markuze 
69*b1137e0bSAlex Markuze void ceph_subvolume_metrics_init(struct ceph_subvolume_metrics_tracker *tracker);
70*b1137e0bSAlex Markuze void ceph_subvolume_metrics_destroy(struct ceph_subvolume_metrics_tracker *tracker);
71*b1137e0bSAlex Markuze void ceph_subvolume_metrics_enable(struct ceph_subvolume_metrics_tracker *tracker,
72*b1137e0bSAlex Markuze 				   bool enable);
73*b1137e0bSAlex Markuze void ceph_subvolume_metrics_record(struct ceph_subvolume_metrics_tracker *tracker,
74*b1137e0bSAlex Markuze 				   u64 subvol_id, bool is_write,
75*b1137e0bSAlex Markuze 				   size_t size, u64 latency_us);
76*b1137e0bSAlex Markuze int ceph_subvolume_metrics_snapshot(struct ceph_subvolume_metrics_tracker *tracker,
77*b1137e0bSAlex Markuze 				    struct ceph_subvol_metric_snapshot **out,
78*b1137e0bSAlex Markuze 				    u32 *nr, bool consume);
79*b1137e0bSAlex Markuze void ceph_subvolume_metrics_free_snapshot(struct ceph_subvol_metric_snapshot *snapshot);
80*b1137e0bSAlex Markuze void ceph_subvolume_metrics_dump(struct ceph_subvolume_metrics_tracker *tracker,
81*b1137e0bSAlex Markuze 				 struct seq_file *s);
82*b1137e0bSAlex Markuze 
83*b1137e0bSAlex Markuze void ceph_subvolume_metrics_record_io(struct ceph_mds_client *mdsc,
84*b1137e0bSAlex Markuze 				      struct ceph_inode_info *ci,
85*b1137e0bSAlex Markuze 				      bool is_write, size_t bytes,
86*b1137e0bSAlex Markuze 				      ktime_t start, ktime_t end);
87*b1137e0bSAlex Markuze 
ceph_subvolume_metrics_enabled(const struct ceph_subvolume_metrics_tracker * tracker)88*b1137e0bSAlex Markuze static inline bool ceph_subvolume_metrics_enabled(
89*b1137e0bSAlex Markuze 		const struct ceph_subvolume_metrics_tracker *tracker)
90*b1137e0bSAlex Markuze {
91*b1137e0bSAlex Markuze 	return READ_ONCE(tracker->enabled);
92*b1137e0bSAlex Markuze }
93*b1137e0bSAlex Markuze 
94*b1137e0bSAlex Markuze int __init ceph_subvolume_metrics_cache_init(void);
95*b1137e0bSAlex Markuze void ceph_subvolume_metrics_cache_destroy(void);
96*b1137e0bSAlex Markuze 
97*b1137e0bSAlex Markuze #endif /* _FS_CEPH_SUBVOLUME_METRICS_H */
98