]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef CEPH_MMDSBEACON_H | |
16 | #define CEPH_MMDSBEACON_H | |
17 | ||
11fdf7f2 | 18 | #include <string_view> |
94b18763 | 19 | |
11fdf7f2 | 20 | #include "msg/Message.h" |
7c673cae FG |
21 | #include "messages/PaxosServiceMessage.h" |
22 | ||
23 | #include "include/types.h" | |
24 | ||
25 | #include "mds/MDSMap.h" | |
26 | ||
27 | ||
28 | ||
29 | /** | |
30 | * Unique ID for each type of metric we can send to the mon, so that if the mon | |
31 | * knows about the IDs then it can implement special behaviour for certain | |
32 | * messages. | |
33 | */ | |
34 | enum mds_metric_t { | |
35 | MDS_HEALTH_NULL = 0, | |
36 | MDS_HEALTH_TRIM, | |
37 | MDS_HEALTH_CLIENT_RECALL, | |
38 | MDS_HEALTH_CLIENT_LATE_RELEASE, | |
39 | MDS_HEALTH_CLIENT_RECALL_MANY, | |
40 | MDS_HEALTH_CLIENT_LATE_RELEASE_MANY, | |
41 | MDS_HEALTH_CLIENT_OLDEST_TID, | |
42 | MDS_HEALTH_CLIENT_OLDEST_TID_MANY, | |
43 | MDS_HEALTH_DAMAGE, | |
44 | MDS_HEALTH_READ_ONLY, | |
45 | MDS_HEALTH_SLOW_REQUEST, | |
91327a77 AA |
46 | MDS_HEALTH_CACHE_OVERSIZED, |
47 | MDS_HEALTH_SLOW_METADATA_IO, | |
7c673cae FG |
48 | }; |
49 | ||
11fdf7f2 | 50 | inline const char *mds_metric_name(mds_metric_t m) |
224ce89b WB |
51 | { |
52 | switch (m) { | |
53 | case MDS_HEALTH_TRIM: return "MDS_TRIM"; | |
54 | case MDS_HEALTH_CLIENT_RECALL: return "MDS_CLIENT_RECALL"; | |
55 | case MDS_HEALTH_CLIENT_LATE_RELEASE: return "MDS_CLIENT_LATE_RELEASE"; | |
56 | case MDS_HEALTH_CLIENT_RECALL_MANY: return "MDS_CLIENT_RECALL_MANY"; | |
57 | case MDS_HEALTH_CLIENT_LATE_RELEASE_MANY: return "MDS_CLIENT_LATE_RELEASE_MANY"; | |
58 | case MDS_HEALTH_CLIENT_OLDEST_TID: return "MDS_CLIENT_OLDEST_TID"; | |
59 | case MDS_HEALTH_CLIENT_OLDEST_TID_MANY: return "MDS_CLIENT_OLDEST_TID_MANY"; | |
60 | case MDS_HEALTH_DAMAGE: return "MDS_DAMAGE"; | |
61 | case MDS_HEALTH_READ_ONLY: return "MDS_READ_ONLY"; | |
62 | case MDS_HEALTH_SLOW_REQUEST: return "MDS_SLOW_REQUEST"; | |
63 | case MDS_HEALTH_CACHE_OVERSIZED: return "MDS_CACHE_OVERSIZED"; | |
91327a77 | 64 | case MDS_HEALTH_SLOW_METADATA_IO: return "MDS_SLOW_METADATA_IO"; |
224ce89b WB |
65 | default: |
66 | return "???"; | |
67 | } | |
68 | } | |
69 | ||
11fdf7f2 | 70 | inline const char *mds_metric_summary(mds_metric_t m) |
224ce89b WB |
71 | { |
72 | switch (m) { | |
73 | case MDS_HEALTH_TRIM: | |
74 | return "%num% MDSs behind on trimming"; | |
75 | case MDS_HEALTH_CLIENT_RECALL: | |
76 | return "%num% clients failing to respond to cache pressure"; | |
77 | case MDS_HEALTH_CLIENT_LATE_RELEASE: | |
78 | return "%num% clients failing to respond to capability release"; | |
79 | case MDS_HEALTH_CLIENT_RECALL_MANY: | |
80 | return "%num% MDSs have many clients failing to respond to cache pressure"; | |
81 | case MDS_HEALTH_CLIENT_LATE_RELEASE_MANY: | |
82 | return "%num% MDSs have many clients failing to respond to capability " | |
83 | "release"; | |
84 | case MDS_HEALTH_CLIENT_OLDEST_TID: | |
85 | return "%num% clients failing to advance oldest client/flush tid"; | |
86 | case MDS_HEALTH_CLIENT_OLDEST_TID_MANY: | |
87 | return "%num% MDSs have clients failing to advance oldest client/flush tid"; | |
88 | case MDS_HEALTH_DAMAGE: | |
89 | return "%num% MDSs report damaged metadata"; | |
90 | case MDS_HEALTH_READ_ONLY: | |
91 | return "%num% MDSs are read only"; | |
92 | case MDS_HEALTH_SLOW_REQUEST: | |
93 | return "%num% MDSs report slow requests"; | |
94 | case MDS_HEALTH_CACHE_OVERSIZED: | |
95 | return "%num% MDSs report oversized cache"; | |
91327a77 AA |
96 | case MDS_HEALTH_SLOW_METADATA_IO: |
97 | return "%num% MDSs report slow metadata IOs"; | |
224ce89b WB |
98 | default: |
99 | return "???"; | |
100 | } | |
101 | } | |
102 | ||
7c673cae FG |
103 | /** |
104 | * This structure is designed to allow some flexibility in how we emit health | |
105 | * complaints, such that: | |
106 | * - The mon doesn't have to have foreknowledge of all possible metrics: we can | |
107 | * implement new messages in the MDS and have the mon pass them through to the user | |
108 | * (enables us to do complex checks inside the MDS, and allows mon to be older version | |
109 | * than MDS) | |
110 | * - The mon has enough information to perform reductions on some types of metric, for | |
111 | * example complaints about the same client from multiple MDSs where we might want | |
112 | * to reduce three "client X is stale on MDS y" metrics into one "client X is stale | |
113 | * on 3 MDSs" message. | |
114 | */ | |
115 | struct MDSHealthMetric | |
116 | { | |
117 | mds_metric_t type; | |
118 | health_status_t sev; | |
119 | std::string message; | |
120 | std::map<std::string, std::string> metadata; | |
121 | ||
122 | void encode(bufferlist& bl) const { | |
123 | ENCODE_START(1, 1, bl); | |
11fdf7f2 TL |
124 | ceph_assert(type != MDS_HEALTH_NULL); |
125 | encode((uint16_t)type, bl); | |
126 | encode((uint8_t)sev, bl); | |
127 | encode(message, bl); | |
128 | encode(metadata, bl); | |
7c673cae FG |
129 | ENCODE_FINISH(bl); |
130 | } | |
131 | ||
11fdf7f2 | 132 | void decode(bufferlist::const_iterator& bl) { |
7c673cae | 133 | DECODE_START(1, bl); |
f91f0fd5 TL |
134 | uint16_t raw_type; |
135 | decode(raw_type, bl); | |
136 | type = (mds_metric_t)raw_type; | |
11fdf7f2 | 137 | ceph_assert(type != MDS_HEALTH_NULL); |
f91f0fd5 TL |
138 | uint8_t raw_sev; |
139 | decode(raw_sev, bl); | |
140 | sev = (health_status_t)raw_sev; | |
11fdf7f2 TL |
141 | decode(message, bl); |
142 | decode(metadata, bl); | |
7c673cae FG |
143 | DECODE_FINISH(bl); |
144 | } | |
145 | ||
146 | bool operator==(MDSHealthMetric const &other) const | |
147 | { | |
148 | return (type == other.type && sev == other.sev && message == other.message); | |
149 | } | |
150 | ||
151 | MDSHealthMetric() : type(MDS_HEALTH_NULL), sev(HEALTH_OK) {} | |
11fdf7f2 | 152 | MDSHealthMetric(mds_metric_t type_, health_status_t sev_, std::string_view message_) |
7c673cae FG |
153 | : type(type_), sev(sev_), message(message_) {} |
154 | }; | |
155 | WRITE_CLASS_ENCODER(MDSHealthMetric) | |
156 | ||
157 | ||
158 | /** | |
159 | * Health metrics send by the MDS to the mon, so that the mon can generate | |
160 | * user friendly warnings about undesirable states. | |
161 | */ | |
162 | struct MDSHealth | |
163 | { | |
9f95a23c | 164 | std::vector<MDSHealthMetric> metrics; |
7c673cae FG |
165 | |
166 | void encode(bufferlist& bl) const { | |
167 | ENCODE_START(1, 1, bl); | |
11fdf7f2 | 168 | encode(metrics, bl); |
7c673cae FG |
169 | ENCODE_FINISH(bl); |
170 | } | |
171 | ||
11fdf7f2 | 172 | void decode(bufferlist::const_iterator& bl) { |
7c673cae | 173 | DECODE_START(1, bl); |
11fdf7f2 | 174 | decode(metrics, bl); |
7c673cae FG |
175 | DECODE_FINISH(bl); |
176 | } | |
177 | ||
178 | bool operator==(MDSHealth const &other) const | |
179 | { | |
180 | return metrics == other.metrics; | |
181 | } | |
182 | }; | |
183 | WRITE_CLASS_ENCODER(MDSHealth) | |
184 | ||
185 | ||
9f95a23c | 186 | class MMDSBeacon : public PaxosServiceMessage { |
11fdf7f2 | 187 | private: |
7c673cae | 188 | |
9f95a23c | 189 | static constexpr int HEAD_VERSION = 8; |
11fdf7f2 | 190 | static constexpr int COMPAT_VERSION = 6; |
7c673cae FG |
191 | |
192 | uuid_d fsid; | |
11fdf7f2 | 193 | mds_gid_t global_id = MDS_GID_NONE; |
7c673cae FG |
194 | string name; |
195 | ||
11fdf7f2 TL |
196 | MDSMap::DaemonState state = MDSMap::STATE_NULL; |
197 | version_t seq = 0; | |
7c673cae FG |
198 | |
199 | CompatSet compat; | |
200 | ||
201 | MDSHealth health; | |
202 | ||
203 | map<string, string> sys_info; | |
204 | ||
11fdf7f2 | 205 | uint64_t mds_features = 0; |
7c673cae | 206 | |
9f95a23c TL |
207 | string fs; |
208 | ||
11fdf7f2 | 209 | protected: |
9f95a23c | 210 | MMDSBeacon() : PaxosServiceMessage(MSG_MDS_BEACON, 0, HEAD_VERSION, COMPAT_VERSION) |
11fdf7f2 | 211 | { |
91327a77 AA |
212 | set_priority(CEPH_MSG_PRIO_HIGH); |
213 | } | |
11fdf7f2 | 214 | MMDSBeacon(const uuid_d &f, mds_gid_t g, const string& n, epoch_t les, MDSMap::DaemonState st, version_t se, uint64_t feat) : |
9f95a23c | 215 | PaxosServiceMessage(MSG_MDS_BEACON, les, HEAD_VERSION, COMPAT_VERSION), |
7c673cae | 216 | fsid(f), global_id(g), name(n), state(st), seq(se), |
11fdf7f2 | 217 | mds_features(feat) { |
91327a77 | 218 | set_priority(CEPH_MSG_PRIO_HIGH); |
7c673cae | 219 | } |
7c673cae FG |
220 | ~MMDSBeacon() override {} |
221 | ||
222 | public: | |
11fdf7f2 TL |
223 | const uuid_d& get_fsid() const { return fsid; } |
224 | mds_gid_t get_global_id() const { return global_id; } | |
225 | const string& get_name() const { return name; } | |
226 | epoch_t get_last_epoch_seen() const { return version; } | |
227 | MDSMap::DaemonState get_state() const { return state; } | |
228 | version_t get_seq() const { return seq; } | |
229 | std::string_view get_type_name() const override { return "mdsbeacon"; } | |
7c673cae FG |
230 | uint64_t get_mds_features() const { return mds_features; } |
231 | ||
232 | CompatSet const& get_compat() const { return compat; } | |
233 | void set_compat(const CompatSet& c) { compat = c; } | |
234 | ||
235 | MDSHealth const& get_health() const { return health; } | |
236 | void set_health(const MDSHealth &h) { health = h; } | |
237 | ||
9f95a23c TL |
238 | const string& get_fs() const { return fs; } |
239 | void set_fs(std::string_view s) { fs = s; } | |
240 | ||
7c673cae FG |
241 | const map<string, string>& get_sys_info() const { return sys_info; } |
242 | void set_sys_info(const map<string, string>& i) { sys_info = i; } | |
243 | ||
244 | void print(ostream& out) const override { | |
9f95a23c TL |
245 | out << "mdsbeacon(" << global_id << "/" << name |
246 | << " " << ceph_mds_state_name(state); | |
247 | if (fs.size()) { | |
248 | out << " fs=" << fs; | |
249 | } | |
250 | out << " seq=" << seq << " v" << version << ")"; | |
7c673cae FG |
251 | } |
252 | ||
253 | void encode_payload(uint64_t features) override { | |
11fdf7f2 | 254 | using ceph::encode; |
7c673cae | 255 | paxos_encode(); |
11fdf7f2 TL |
256 | encode(fsid, payload); |
257 | encode(global_id, payload); | |
258 | encode((__u32)state, payload); | |
259 | encode(seq, payload); | |
260 | encode(name, payload); | |
261 | encode(MDS_RANK_NONE, payload); | |
262 | encode(std::string(), payload); | |
263 | encode(compat, payload); | |
264 | encode(health, payload); | |
7c673cae | 265 | if (state == MDSMap::STATE_BOOT) { |
11fdf7f2 | 266 | encode(sys_info, payload); |
7c673cae | 267 | } |
11fdf7f2 TL |
268 | encode(mds_features, payload); |
269 | encode(FS_CLUSTER_ID_NONE, payload); | |
270 | encode(false, payload); | |
9f95a23c | 271 | encode(fs, payload); |
7c673cae FG |
272 | } |
273 | void decode_payload() override { | |
11fdf7f2 TL |
274 | using ceph::decode; |
275 | auto p = payload.cbegin(); | |
7c673cae | 276 | paxos_decode(p); |
11fdf7f2 TL |
277 | decode(fsid, p); |
278 | decode(global_id, p); | |
f91f0fd5 TL |
279 | __u32 raw_state; |
280 | decode(raw_state, p); | |
281 | state = (MDSMap::DaemonState)raw_state; | |
11fdf7f2 TL |
282 | decode(seq, p); |
283 | decode(name, p); | |
284 | { | |
285 | mds_rank_t standby_for_rank; | |
286 | decode(standby_for_rank, p); | |
287 | } | |
288 | { | |
289 | std::string standby_for_name; | |
290 | decode(standby_for_name, p); | |
291 | } | |
292 | decode(compat, p); | |
293 | decode(health, p); | |
7c673cae | 294 | if (state == MDSMap::STATE_BOOT) { |
11fdf7f2 TL |
295 | decode(sys_info, p); |
296 | } | |
297 | decode(mds_features, p); | |
298 | { | |
299 | fs_cluster_id_t standby_for_fscid; | |
300 | decode(standby_for_fscid, p); | |
7c673cae | 301 | } |
7c673cae | 302 | if (header.version >= 7) { |
11fdf7f2 TL |
303 | bool standby_replay; |
304 | decode(standby_replay, p); | |
7c673cae FG |
305 | } |
306 | ||
307 | if (header.version < 7 && state == MDSMap::STATE_STANDBY_REPLAY) { | |
308 | // Old MDS daemons request the state, instead of explicitly | |
309 | // advertising that they are configured as a replay daemon. | |
7c673cae FG |
310 | state = MDSMap::STATE_STANDBY; |
311 | } | |
9f95a23c TL |
312 | if (header.version >= 8) { |
313 | decode(fs, p); | |
314 | } | |
7c673cae | 315 | } |
9f95a23c TL |
316 | private: |
317 | template<class T, typename... Args> | |
318 | friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); | |
7c673cae FG |
319 | }; |
320 | ||
321 | #endif |