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