]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/MDSMap.h
import ceph quincy 17.2.4
[ceph.git] / ceph / src / mds / MDSMap.h
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_MDSMAP_H
16 #define CEPH_MDSMAP_H
17
18 #include <algorithm>
19 #include <map>
20 #include <set>
21 #include <string>
22 #include <string_view>
23
24 #include <errno.h>
25
26 #include "include/types.h"
27 #include "include/ceph_features.h"
28 #include "include/health.h"
29 #include "include/CompatSet.h"
30 #include "include/common_fwd.h"
31
32 #include "common/Clock.h"
33 #include "common/Formatter.h"
34 #include "common/ceph_releases.h"
35 #include "common/config.h"
36
37 #include "mds/mdstypes.h"
38 #include "mds/cephfs_features.h"
39
40 static inline const auto MDS_FEATURE_INCOMPAT_BASE = CompatSet::Feature(1, "base v0.20");
41 static inline const auto MDS_FEATURE_INCOMPAT_CLIENTRANGES = CompatSet::Feature(2, "client writeable ranges");
42 static inline const auto MDS_FEATURE_INCOMPAT_FILELAYOUT = CompatSet::Feature(3, "default file layouts on dirs");
43 static inline const auto MDS_FEATURE_INCOMPAT_DIRINODE = CompatSet::Feature(4, "dir inode in separate object");
44 static inline const auto MDS_FEATURE_INCOMPAT_ENCODING = CompatSet::Feature(5, "mds uses versioned encoding");
45 static inline const auto MDS_FEATURE_INCOMPAT_OMAPDIRFRAG = CompatSet::Feature(6, "dirfrag is stored in omap");
46 static inline const auto MDS_FEATURE_INCOMPAT_INLINE = CompatSet::Feature(7, "mds uses inline data");
47 static inline const auto MDS_FEATURE_INCOMPAT_NOANCHOR = CompatSet::Feature(8, "no anchor table");
48 static inline const auto MDS_FEATURE_INCOMPAT_FILE_LAYOUT_V2 = CompatSet::Feature(9, "file layout v2");
49 static inline const auto MDS_FEATURE_INCOMPAT_SNAPREALM_V2 = CompatSet::Feature(10, "snaprealm v2");
50
51 #define MDS_FS_NAME_DEFAULT "cephfs"
52
53 class health_check_map_t;
54
55 class MDSMap {
56 public:
57 /* These states are the union of the set of possible states of an MDS daemon,
58 * and the set of possible states of an MDS rank. See
59 * doc/cephfs/mds-states.rst for state descriptions and a visual state diagram, and
60 * doc/cephfs/mds-state-diagram.dot to update the diagram.
61 */
62 typedef enum {
63 // States of an MDS daemon not currently holding a rank
64 // ====================================================
65 STATE_NULL = CEPH_MDS_STATE_NULL, // null value for fns returning this type.
66 STATE_BOOT = CEPH_MDS_STATE_BOOT, // up, boot announcement. destiny unknown.
67 STATE_STANDBY = CEPH_MDS_STATE_STANDBY, // up, idle. waiting for assignment by monitor.
68
69 // States of an MDS rank, and of any MDS daemon holding that rank
70 // ==============================================================
71 STATE_STANDBY_REPLAY = CEPH_MDS_STATE_STANDBY_REPLAY, // up, replaying active node, ready to take over and not serving clients. Note: Up to two MDS hold the rank being replayed.
72 STATE_STOPPED = CEPH_MDS_STATE_STOPPED, // down, once existed, but no subtrees. empty log. may not be held by a daemon.
73
74 STATE_CREATING = CEPH_MDS_STATE_CREATING, // up, creating MDS instance (new journal, idalloc..).
75 STATE_STARTING = CEPH_MDS_STATE_STARTING, // up, starting prior stopped MDS instance.
76
77 STATE_REPLAY = CEPH_MDS_STATE_REPLAY, // up, starting prior failed instance. scanning journal.
78 STATE_RESOLVE = CEPH_MDS_STATE_RESOLVE, // up, disambiguating distributed operations (import, rename, etc.)
79 STATE_RECONNECT = CEPH_MDS_STATE_RECONNECT, // up, reconnect to clients
80 STATE_REJOIN = CEPH_MDS_STATE_REJOIN, // up, replayed journal, rejoining distributed cache
81 STATE_CLIENTREPLAY = CEPH_MDS_STATE_CLIENTREPLAY, // up, active
82 STATE_ACTIVE = CEPH_MDS_STATE_ACTIVE, // up, active
83 STATE_STOPPING = CEPH_MDS_STATE_STOPPING, // up, exporting metadata (-> standby or out)
84 STATE_DNE = CEPH_MDS_STATE_DNE, // down, rank does not exist
85
86 // State which a daemon may send to MDSMonitor in its beacon
87 // to indicate that offline repair is required. Daemon must stop
88 // immediately after indicating this state.
89 STATE_DAMAGED = CEPH_MDS_STATE_DAMAGED
90
91 /*
92 * In addition to explicit states, an MDS rank implicitly in state:
93 * - STOPPED if it is not currently associated with an MDS daemon gid but it
94 * is in MDSMap::stopped
95 * - FAILED if it is not currently associated with an MDS daemon gid but it
96 * is in MDSMap::failed
97 * - DNE if it is not currently associated with an MDS daemon gid and it is
98 * missing from both MDSMap::failed and MDSMap::stopped
99 */
100 } DaemonState;
101
102 typedef enum
103 {
104 AVAILABLE = 0,
105 TRANSIENT_UNAVAILABLE = 1,
106 STUCK_UNAVAILABLE = 2
107
108 } availability_t;
109
110 struct mds_info_t {
111 enum mds_flags : uint64_t {
112 FROZEN = 1 << 0,
113 };
114
115 mds_info_t() = default;
116
117 bool laggy() const { return !(laggy_since == utime_t()); }
118 void clear_laggy() { laggy_since = utime_t(); }
119
120 bool is_degraded() const {
121 return STATE_REPLAY <= state && state <= STATE_CLIENTREPLAY;
122 }
123
124 void freeze() { flags |= mds_flags::FROZEN; }
125 void unfreeze() { flags &= ~mds_flags::FROZEN; }
126 bool is_frozen() const { return flags&mds_flags::FROZEN; }
127
128 const entity_addrvec_t& get_addrs() const {
129 return addrs;
130 }
131
132 void encode(ceph::buffer::list& bl, uint64_t features) const {
133 if ((features & CEPH_FEATURE_MDSENC) == 0 ) encode_unversioned(bl);
134 else encode_versioned(bl, features);
135 }
136 void decode(ceph::buffer::list::const_iterator& p);
137 void dump(ceph::Formatter *f) const;
138 void dump(std::ostream&) const;
139
140 // The long form name for use in cluster log messages`
141 std::string human_name() const;
142
143 static void generate_test_instances(std::list<mds_info_t*>& ls);
144
145 mds_gid_t global_id = MDS_GID_NONE;
146 std::string name;
147 mds_rank_t rank = MDS_RANK_NONE;
148 int32_t inc = 0;
149 MDSMap::DaemonState state = STATE_STANDBY;
150 version_t state_seq = 0;
151 entity_addrvec_t addrs;
152 utime_t laggy_since;
153 std::set<mds_rank_t> export_targets;
154 fs_cluster_id_t join_fscid = FS_CLUSTER_ID_NONE;
155 uint64_t mds_features = 0;
156 uint64_t flags = 0;
157 CompatSet compat;
158 private:
159 void encode_versioned(ceph::buffer::list& bl, uint64_t features) const;
160 void encode_unversioned(ceph::buffer::list& bl) const;
161 };
162
163 friend class MDSMonitor;
164 friend class Filesystem;
165 friend class FSMap;
166
167 static CompatSet get_compat_set_all();
168 static CompatSet get_compat_set_default();
169 static CompatSet get_compat_set_base(); // pre v0.20
170 static CompatSet get_compat_set_v16_2_4(); // pre-v16.2.5 CompatSet in MDS beacon
171
172 static MDSMap create_null_mdsmap() {
173 MDSMap null_map;
174 /* Use the largest epoch so it's always bigger than whatever the MDS has. */
175 null_map.epoch = std::numeric_limits<decltype(epoch)>::max();
176 return null_map;
177 }
178
179 bool get_inline_data_enabled() const { return inline_data_enabled; }
180 void set_inline_data_enabled(bool enabled) { inline_data_enabled = enabled; }
181
182 utime_t get_session_timeout() const {
183 return utime_t(session_timeout,0);
184 }
185 void set_session_timeout(uint32_t t) {
186 session_timeout = t;
187 }
188
189 utime_t get_session_autoclose() const {
190 return utime_t(session_autoclose, 0);
191 }
192 void set_session_autoclose(uint32_t t) {
193 session_autoclose = t;
194 }
195
196 uint64_t get_max_filesize() const { return max_file_size; }
197 void set_max_filesize(uint64_t m) { max_file_size = m; }
198
199 void set_min_compat_client(ceph_release_t version);
200
201 void add_required_client_feature(size_t bit) {
202 required_client_features.insert(bit);
203 }
204 void remove_required_client_feature(size_t bit) {
205 required_client_features.erase(bit);
206 }
207 const auto& get_required_client_features() const {
208 return required_client_features;
209 }
210
211 int get_flags() const { return flags; }
212 bool test_flag(int f) const { return flags & f; }
213 void set_flag(int f) { flags |= f; }
214 void clear_flag(int f) { flags &= ~f; }
215
216 std::string_view get_fs_name() const {return fs_name;}
217 void set_fs_name(std::string new_fs_name) { fs_name = std::move(new_fs_name); }
218
219 void set_snaps_allowed() {
220 set_flag(CEPH_MDSMAP_ALLOW_SNAPS);
221 ever_allowed_features |= CEPH_MDSMAP_ALLOW_SNAPS;
222 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_SNAPS;
223 }
224 void clear_snaps_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
225 bool allows_snaps() const { return test_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
226 bool was_snaps_ever_allowed() const { return ever_allowed_features & CEPH_MDSMAP_ALLOW_SNAPS; }
227
228 void set_standby_replay_allowed() {
229 set_flag(CEPH_MDSMAP_ALLOW_STANDBY_REPLAY);
230 ever_allowed_features |= CEPH_MDSMAP_ALLOW_STANDBY_REPLAY;
231 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_STANDBY_REPLAY;
232 }
233 void clear_standby_replay_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_STANDBY_REPLAY); }
234 bool allows_standby_replay() const { return test_flag(CEPH_MDSMAP_ALLOW_STANDBY_REPLAY); }
235 bool was_standby_replay_ever_allowed() const { return ever_allowed_features & CEPH_MDSMAP_ALLOW_STANDBY_REPLAY; }
236
237 void set_multimds_snaps_allowed() {
238 set_flag(CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS);
239 ever_allowed_features |= CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS;
240 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS;
241 }
242 void clear_multimds_snaps_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS); }
243 bool allows_multimds_snaps() const { return test_flag(CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS); }
244 bool joinable() const { return !test_flag(CEPH_MDSMAP_NOT_JOINABLE); }
245
246 epoch_t get_epoch() const { return epoch; }
247 void inc_epoch() { epoch++; }
248
249 bool get_enabled() const { return enabled; }
250
251 const utime_t& get_created() const { return created; }
252 void set_created(utime_t ct) { modified = created = ct; }
253 const utime_t& get_modified() const { return modified; }
254 void set_modified(utime_t mt) { modified = mt; }
255
256 epoch_t get_last_failure() const { return last_failure; }
257 epoch_t get_last_failure_osd_epoch() const { return last_failure_osd_epoch; }
258
259 mds_rank_t get_max_mds() const { return max_mds; }
260 void set_max_mds(mds_rank_t m) { max_mds = m; }
261 void set_old_max_mds() { old_max_mds = max_mds; }
262 mds_rank_t get_old_max_mds() const { return old_max_mds; }
263
264 mds_rank_t get_standby_count_wanted(mds_rank_t standby_daemon_count) const {
265 ceph_assert(standby_daemon_count >= 0);
266 std::set<mds_rank_t> s;
267 get_standby_replay_mds_set(s);
268 mds_rank_t standbys_avail = (mds_rank_t)s.size()+standby_daemon_count;
269 mds_rank_t wanted = std::max(0, standby_count_wanted);
270 return wanted > standbys_avail ? wanted - standbys_avail : 0;
271 }
272 void set_standby_count_wanted(mds_rank_t n) { standby_count_wanted = n; }
273 bool check_health(mds_rank_t standby_daemon_count);
274
275 const std::string get_balancer() const { return balancer; }
276 void set_balancer(std::string val) { balancer.assign(val); }
277
278 mds_rank_t get_tableserver() const { return tableserver; }
279 mds_rank_t get_root() const { return root; }
280
281 const std::vector<int64_t> &get_data_pools() const { return data_pools; }
282 int64_t get_first_data_pool() const { return *data_pools.begin(); }
283 int64_t get_metadata_pool() const { return metadata_pool; }
284 bool is_data_pool(int64_t poolid) const {
285 auto p = std::find(data_pools.begin(), data_pools.end(), poolid);
286 if (p == data_pools.end())
287 return false;
288 return true;
289 }
290
291 bool pool_in_use(int64_t poolid) const {
292 return get_enabled() && (is_data_pool(poolid) || metadata_pool == poolid);
293 }
294
295 const auto& get_mds_info() const { return mds_info; }
296 const auto& get_mds_info_gid(mds_gid_t gid) const {
297 return mds_info.at(gid);
298 }
299 const mds_info_t& get_mds_info(mds_rank_t m) const {
300 ceph_assert(up.count(m) && mds_info.count(up.at(m)));
301 return mds_info.at(up.at(m));
302 }
303 mds_gid_t find_mds_gid_by_name(std::string_view s) const;
304
305 // counts
306 unsigned get_num_in_mds() const {
307 return in.size();
308 }
309 unsigned get_num_up_mds() const {
310 return up.size();
311 }
312 mds_rank_t get_last_in_mds() const {
313 auto p = in.rbegin();
314 return p == in.rend() ? MDS_RANK_NONE : *p;
315 }
316 int get_num_failed_mds() const {
317 return failed.size();
318 }
319 unsigned get_num_standby_replay_mds() const {
320 unsigned num = 0;
321 for (auto& i : mds_info) {
322 if (i.second.state == MDSMap::STATE_STANDBY_REPLAY) {
323 ++num;
324 }
325 }
326 return num;
327 }
328 unsigned get_num_mds(int state) const;
329 // data pools
330 void add_data_pool(int64_t poolid) {
331 data_pools.push_back(poolid);
332 }
333 int remove_data_pool(int64_t poolid) {
334 std::vector<int64_t>::iterator p = std::find(data_pools.begin(), data_pools.end(), poolid);
335 if (p == data_pools.end())
336 return -CEPHFS_ENOENT;
337 data_pools.erase(p);
338 return 0;
339 }
340
341 // sets
342 void get_mds_set(std::set<mds_rank_t>& s) const {
343 s = in;
344 }
345 void get_up_mds_set(std::set<mds_rank_t>& s) const;
346 void get_active_mds_set(std::set<mds_rank_t>& s) const {
347 get_mds_set(s, MDSMap::STATE_ACTIVE);
348 }
349 void get_standby_replay_mds_set(std::set<mds_rank_t>& s) const {
350 get_mds_set(s, MDSMap::STATE_STANDBY_REPLAY);
351 }
352 void get_failed_mds_set(std::set<mds_rank_t>& s) const {
353 s = failed;
354 }
355 void get_damaged_mds_set(std::set<mds_rank_t>& s) const {
356 s = damaged;
357 }
358
359 // features
360 uint64_t get_up_features();
361
362 /**
363 * Get MDS ranks which are in but not up.
364 */
365 void get_down_mds_set(std::set<mds_rank_t> *s) const
366 {
367 ceph_assert(s != NULL);
368 s->insert(failed.begin(), failed.end());
369 s->insert(damaged.begin(), damaged.end());
370 }
371
372 int get_failed() const {
373 if (!failed.empty()) return *failed.begin();
374 return -1;
375 }
376 void get_stopped_mds_set(std::set<mds_rank_t>& s) const {
377 s = stopped;
378 }
379 void get_recovery_mds_set(std::set<mds_rank_t>& s) const;
380
381 void get_mds_set_lower_bound(std::set<mds_rank_t>& s, DaemonState first) const;
382 void get_mds_set(std::set<mds_rank_t>& s, DaemonState state) const;
383
384 void get_health(std::list<std::pair<health_status_t,std::string> >& summary,
385 std::list<std::pair<health_status_t,std::string> > *detail) const;
386
387 void get_health_checks(health_check_map_t *checks) const;
388
389 /**
390 * Return indication of whether cluster is available. This is a
391 * heuristic for clients to see if they should bother waiting to talk to
392 * MDSs, or whether they should error out at startup/mount.
393 *
394 * A TRANSIENT_UNAVAILABLE result indicates that the cluster is in a
395 * transition state like replaying, or is potentially about the fail over.
396 * Clients should wait for an updated map before making a final decision
397 * about whether the filesystem is mountable.
398 *
399 * A STUCK_UNAVAILABLE result indicates that we can't see a way that
400 * the cluster is about to recover on its own, so it'll probably require
401 * administrator intervention: clients should probably not bother trying
402 * to mount.
403 */
404 availability_t is_cluster_available() const;
405
406 /**
407 * Return whether this MDSMap is suitable for resizing based on the state
408 * of the ranks.
409 */
410 bool is_resizeable() const {
411 return !is_degraded() &&
412 get_num_mds(CEPH_MDS_STATE_CREATING) == 0 &&
413 get_num_mds(CEPH_MDS_STATE_STARTING) == 0 &&
414 get_num_mds(CEPH_MDS_STATE_STOPPING) == 0;
415 }
416
417 // mds states
418 bool is_down(mds_rank_t m) const { return up.count(m) == 0; }
419 bool is_up(mds_rank_t m) const { return up.count(m); }
420 bool is_in(mds_rank_t m) const { return up.count(m) || failed.count(m); }
421 bool is_out(mds_rank_t m) const { return !is_in(m); }
422
423 bool is_failed(mds_rank_t m) const { return failed.count(m); }
424 bool is_stopped(mds_rank_t m) const { return stopped.count(m); }
425
426 bool is_dne(mds_rank_t m) const { return in.count(m) == 0; }
427 bool is_dne_gid(mds_gid_t gid) const { return mds_info.count(gid) == 0; }
428
429 /**
430 * Get MDS daemon status by GID
431 */
432 auto get_state_gid(mds_gid_t gid) const {
433 auto it = mds_info.find(gid);
434 if (it == mds_info.end())
435 return STATE_NULL;
436 return it->second.state;
437 }
438
439 /**
440 * Get MDS rank state if the rank is up, else STATE_NULL
441 */
442 auto get_state(mds_rank_t m) const {
443 auto it = up.find(m);
444 if (it == up.end())
445 return STATE_NULL;
446 return get_state_gid(it->second);
447 }
448
449 auto get_gid(mds_rank_t r) const {
450 return up.at(r);
451 }
452 const auto& get_info(mds_rank_t m) const {
453 return mds_info.at(up.at(m));
454 }
455 const auto& get_info_gid(mds_gid_t gid) const {
456 return mds_info.at(gid);
457 }
458
459 bool is_boot(mds_rank_t m) const { return get_state(m) == STATE_BOOT; }
460 bool is_bootstrapping(mds_rank_t m) const {
461 return is_creating(m) || is_starting(m) || is_replay(m);
462 }
463 bool is_creating(mds_rank_t m) const { return get_state(m) == STATE_CREATING; }
464 bool is_starting(mds_rank_t m) const { return get_state(m) == STATE_STARTING; }
465 bool is_replay(mds_rank_t m) const { return get_state(m) == STATE_REPLAY; }
466 bool is_resolve(mds_rank_t m) const { return get_state(m) == STATE_RESOLVE; }
467 bool is_reconnect(mds_rank_t m) const { return get_state(m) == STATE_RECONNECT; }
468 bool is_rejoin(mds_rank_t m) const { return get_state(m) == STATE_REJOIN; }
469 bool is_clientreplay(mds_rank_t m) const { return get_state(m) == STATE_CLIENTREPLAY; }
470 bool is_active(mds_rank_t m) const { return get_state(m) == STATE_ACTIVE; }
471 bool is_stopping(mds_rank_t m) const { return get_state(m) == STATE_STOPPING; }
472 bool is_active_or_stopping(mds_rank_t m) const {
473 return is_active(m) || is_stopping(m);
474 }
475 bool is_clientreplay_or_active_or_stopping(mds_rank_t m) const {
476 return is_clientreplay(m) || is_active(m) || is_stopping(m);
477 }
478
479 mds_gid_t get_standby_replay(mds_rank_t r) const;
480 bool has_standby_replay(mds_rank_t r) const {
481 return get_standby_replay(r) != MDS_GID_NONE;
482 }
483
484 bool is_followable(mds_rank_t r) const {
485 if (auto it1 = up.find(r); it1 != up.end()) {
486 if (auto it2 = mds_info.find(it1->second); it2 != mds_info.end()) {
487 auto& info = it2->second;
488 if (!info.is_degraded() && !has_standby_replay(r)) {
489 return true;
490 }
491 }
492 }
493 return false;
494 }
495
496 bool is_laggy_gid(mds_gid_t gid) const {
497 auto it = mds_info.find(gid);
498 return it == mds_info.end() ? false : it->second.laggy();
499 }
500
501 // degraded = some recovery in process. fixes active membership and
502 // recovery_set.
503 bool is_degraded() const;
504 bool is_any_failed() const {
505 return !failed.empty();
506 }
507 bool is_any_damaged() const {
508 return !damaged.empty();
509 }
510 bool is_resolving() const {
511 return
512 get_num_mds(STATE_RESOLVE) > 0 &&
513 get_num_mds(STATE_REPLAY) == 0 &&
514 failed.empty() && damaged.empty();
515 }
516 bool is_rejoining() const {
517 // nodes are rejoining cache state
518 return
519 get_num_mds(STATE_REJOIN) > 0 &&
520 get_num_mds(STATE_REPLAY) == 0 &&
521 get_num_mds(STATE_RECONNECT) == 0 &&
522 get_num_mds(STATE_RESOLVE) == 0 &&
523 failed.empty() && damaged.empty();
524 }
525 bool is_stopped() const {
526 return up.empty();
527 }
528
529 /**
530 * Get whether a rank is 'up', i.e. has
531 * an MDS daemon's entity_inst_t associated
532 * with it.
533 */
534 bool have_inst(mds_rank_t m) const {
535 return up.count(m);
536 }
537
538 /**
539 * Get the MDS daemon entity_inst_t for a rank
540 * known to be up.
541 */
542 entity_addrvec_t get_addrs(mds_rank_t m) const {
543 return mds_info.at(up.at(m)).get_addrs();
544 }
545
546 mds_rank_t get_rank_gid(mds_gid_t gid) const {
547 if (mds_info.count(gid)) {
548 return mds_info.at(gid).rank;
549 } else {
550 return MDS_RANK_NONE;
551 }
552 }
553
554 /**
555 * Get MDS rank incarnation if the rank is up, else -1
556 */
557 mds_gid_t get_incarnation(mds_rank_t m) const {
558 auto it = up.find(m);
559 if (it == up.end())
560 return MDS_GID_NONE;
561 return (mds_gid_t)get_inc_gid(it->second);
562 }
563
564 int get_inc_gid(mds_gid_t gid) const {
565 auto mds_info_entry = mds_info.find(gid);
566 if (mds_info_entry != mds_info.end())
567 return mds_info_entry->second.inc;
568 return -1;
569 }
570 void encode(ceph::buffer::list& bl, uint64_t features) const;
571 void decode(ceph::buffer::list::const_iterator& p);
572 void decode(const ceph::buffer::list& bl) {
573 auto p = bl.cbegin();
574 decode(p);
575 }
576 void sanitize(const std::function<bool(int64_t pool)>& pool_exists);
577
578 void print(std::ostream& out) const;
579 void print_summary(ceph::Formatter *f, std::ostream *out) const;
580 void print_flags(std::ostream& out) const;
581
582 void dump(ceph::Formatter *f) const;
583 void dump_flags_state(Formatter *f) const;
584 static void generate_test_instances(std::list<MDSMap*>& ls);
585
586 static bool state_transition_valid(DaemonState prev, DaemonState next);
587
588 CompatSet compat;
589 protected:
590 // base map
591 epoch_t epoch = 0;
592 bool enabled = false;
593 std::string fs_name = MDS_FS_NAME_DEFAULT;
594 uint32_t flags = CEPH_MDSMAP_DEFAULTS; // flags
595 epoch_t last_failure = 0; // mds epoch of last failure
596 epoch_t last_failure_osd_epoch = 0; // osd epoch of last failure; any mds entering replay needs
597 // at least this osdmap to ensure the blocklist propagates.
598 utime_t created;
599 utime_t modified;
600
601 mds_rank_t tableserver = 0; // which MDS has snaptable
602 mds_rank_t root = 0; // which MDS has root directory
603
604 __u32 session_timeout = 60;
605 __u32 session_autoclose = 300;
606 uint64_t max_file_size = 1ULL<<40; /* 1TB */
607
608 feature_bitset_t required_client_features;
609
610 std::vector<int64_t> data_pools; // file data pools available to clients (via an ioctl). first is the default.
611 int64_t cas_pool = -1; // where CAS objects go
612 int64_t metadata_pool = -1; // where fs metadata objects go
613
614 /*
615 * in: the set of logical mds #'s that define the cluster. this is the set
616 * of mds's the metadata may be distributed over.
617 * up: map from logical mds #'s to the addrs filling those roles.
618 * failed: subset of @in that are failed.
619 * stopped: set of nodes that have been initialized, but are not active.
620 *
621 * @up + @failed = @in. @in * @stopped = {}.
622 */
623
624 mds_rank_t max_mds = 1; /* The maximum number of active MDSes. Also, the maximum rank. */
625 mds_rank_t old_max_mds = 0; /* Value to restore when MDS cluster is marked up */
626 mds_rank_t standby_count_wanted = -1;
627 std::string balancer; /* The name/version of the mantle balancer (i.e. the rados obj name) */
628
629 std::set<mds_rank_t> in; // currently defined cluster
630
631 // which ranks are failed, stopped, damaged (i.e. not held by a daemon)
632 std::set<mds_rank_t> failed, stopped, damaged;
633 std::map<mds_rank_t, mds_gid_t> up; // who is in those roles
634 std::map<mds_gid_t, mds_info_t> mds_info;
635
636 uint8_t ever_allowed_features = 0; //< bitmap of features the cluster has allowed
637 uint8_t explicitly_allowed_features = 0; //< bitmap of features explicitly enabled
638
639 bool inline_data_enabled = false;
640
641 uint64_t cached_up_features = 0;
642 private:
643 inline static const std::map<int, std::string> flag_display = {
644 {CEPH_MDSMAP_NOT_JOINABLE, "joinable"}, //inverse for user display
645 {CEPH_MDSMAP_ALLOW_SNAPS, "allow_snaps"},
646 {CEPH_MDSMAP_ALLOW_MULTIMDS_SNAPS, "allow_multimds_snaps"},
647 {CEPH_MDSMAP_ALLOW_STANDBY_REPLAY, "allow_standby_replay"}
648 };
649 };
650 WRITE_CLASS_ENCODER_FEATURES(MDSMap::mds_info_t)
651 WRITE_CLASS_ENCODER_FEATURES(MDSMap)
652
653 inline std::ostream& operator<<(std::ostream &out, const MDSMap &m) {
654 m.print_summary(NULL, &out);
655 return out;
656 }
657
658 inline std::ostream& operator<<(std::ostream& o, const MDSMap::mds_info_t& info) {
659 info.dump(o);
660 return o;
661 }
662 #endif