1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
19 using std::stringstream
;
21 #include "mon/health_check.h"
25 CompatSet
get_mdsmap_compat_set_all() {
26 CompatSet::FeatureSet feature_compat
;
27 CompatSet::FeatureSet feature_ro_compat
;
28 CompatSet::FeatureSet feature_incompat
;
29 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_BASE
);
30 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_CLIENTRANGES
);
31 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_FILELAYOUT
);
32 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_DIRINODE
);
33 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_ENCODING
);
34 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_OMAPDIRFRAG
);
35 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_INLINE
);
36 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_NOANCHOR
);
37 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_FILE_LAYOUT_V2
);
39 return CompatSet(feature_compat
, feature_ro_compat
, feature_incompat
);
42 CompatSet
get_mdsmap_compat_set_default() {
43 CompatSet::FeatureSet feature_compat
;
44 CompatSet::FeatureSet feature_ro_compat
;
45 CompatSet::FeatureSet feature_incompat
;
46 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_BASE
);
47 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_CLIENTRANGES
);
48 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_FILELAYOUT
);
49 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_DIRINODE
);
50 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_ENCODING
);
51 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_OMAPDIRFRAG
);
52 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_NOANCHOR
);
53 feature_incompat
.insert(MDS_FEATURE_INCOMPAT_FILE_LAYOUT_V2
);
55 return CompatSet(feature_compat
, feature_ro_compat
, feature_incompat
);
59 CompatSet
get_mdsmap_compat_set_base() {
60 CompatSet::FeatureSet feature_compat_base
;
61 CompatSet::FeatureSet feature_incompat_base
;
62 feature_incompat_base
.insert(MDS_FEATURE_INCOMPAT_BASE
);
63 CompatSet::FeatureSet feature_ro_compat_base
;
65 return CompatSet(feature_compat_base
, feature_ro_compat_base
, feature_incompat_base
);
68 void MDSMap::mds_info_t::dump(Formatter
*f
) const
70 f
->dump_unsigned("gid", global_id
);
71 f
->dump_string("name", name
);
72 f
->dump_int("rank", rank
);
73 f
->dump_int("incarnation", inc
);
74 f
->dump_stream("state") << ceph_mds_state_name(state
);
75 f
->dump_int("state_seq", state_seq
);
76 f
->dump_stream("addr") << addr
;
77 if (laggy_since
!= utime_t())
78 f
->dump_stream("laggy_since") << laggy_since
;
80 f
->dump_int("standby_for_rank", standby_for_rank
);
81 f
->dump_int("standby_for_fscid", standby_for_fscid
);
82 f
->dump_string("standby_for_name", standby_for_name
);
83 f
->dump_bool("standby_replay", standby_replay
);
84 f
->open_array_section("export_targets");
85 for (set
<mds_rank_t
>::iterator p
= export_targets
.begin();
86 p
!= export_targets
.end(); ++p
) {
87 f
->dump_int("mds", *p
);
90 f
->dump_unsigned("features", mds_features
);
93 void MDSMap::mds_info_t::print_summary(ostream
&out
) const
95 out
<< global_id
<< ":\t"
97 << " '" << name
<< "'"
100 << " " << ceph_mds_state_name(state
)
101 << " seq " << state_seq
;
103 out
<< " laggy since " << laggy_since
;
105 if (standby_for_rank
!= -1 ||
106 !standby_for_name
.empty()) {
107 out
<< " (standby for";
108 //if (standby_for_rank >= 0)
109 out
<< " rank " << standby_for_rank
;
110 if (!standby_for_name
.empty()) {
111 out
<< " '" << standby_for_name
<< "'";
115 if (!export_targets
.empty()) {
116 out
<< " export_targets=" << export_targets
;
120 void MDSMap::mds_info_t::generate_test_instances(list
<mds_info_t
*>& ls
)
122 mds_info_t
*sample
= new mds_info_t();
123 ls
.push_back(sample
);
124 sample
= new mds_info_t();
125 sample
->global_id
= 1;
126 sample
->name
= "test_instance";
128 ls
.push_back(sample
);
131 void MDSMap::dump(Formatter
*f
) const
133 f
->dump_int("epoch", epoch
);
134 f
->dump_unsigned("flags", flags
);
135 f
->dump_unsigned("ever_allowed_features", ever_allowed_features
);
136 f
->dump_unsigned("explicitly_allowed_features", explicitly_allowed_features
);
137 f
->dump_stream("created") << created
;
138 f
->dump_stream("modified") << modified
;
139 f
->dump_int("tableserver", tableserver
);
140 f
->dump_int("root", root
);
141 f
->dump_int("session_timeout", session_timeout
);
142 f
->dump_int("session_autoclose", session_autoclose
);
143 f
->dump_int("max_file_size", max_file_size
);
144 f
->dump_int("last_failure", last_failure
);
145 f
->dump_int("last_failure_osd_epoch", last_failure_osd_epoch
);
146 f
->open_object_section("compat");
149 f
->dump_int("max_mds", max_mds
);
150 f
->open_array_section("in");
151 for (set
<mds_rank_t
>::const_iterator p
= in
.begin(); p
!= in
.end(); ++p
)
152 f
->dump_int("mds", *p
);
154 f
->open_object_section("up");
155 for (map
<mds_rank_t
,mds_gid_t
>::const_iterator p
= up
.begin(); p
!= up
.end(); ++p
) {
157 sprintf(s
, "mds_%d", int(p
->first
));
158 f
->dump_int(s
, p
->second
);
161 f
->open_array_section("failed");
162 for (set
<mds_rank_t
>::const_iterator p
= failed
.begin(); p
!= failed
.end(); ++p
)
163 f
->dump_int("mds", *p
);
165 f
->open_array_section("damaged");
166 for (set
<mds_rank_t
>::const_iterator p
= damaged
.begin(); p
!= damaged
.end(); ++p
)
167 f
->dump_int("mds", *p
);
169 f
->open_array_section("stopped");
170 for (set
<mds_rank_t
>::const_iterator p
= stopped
.begin(); p
!= stopped
.end(); ++p
)
171 f
->dump_int("mds", *p
);
173 f
->open_object_section("info");
174 for (map
<mds_gid_t
,mds_info_t
>::const_iterator p
= mds_info
.begin(); p
!= mds_info
.end(); ++p
) {
175 char s
[25]; // 'gid_' + len(str(ULLONG_MAX)) + '\0'
176 sprintf(s
, "gid_%llu", (long long unsigned)p
->first
);
177 f
->open_object_section(s
);
182 f
->open_array_section("data_pools");
183 for (const auto p
: data_pools
)
184 f
->dump_int("pool", p
);
186 f
->dump_int("metadata_pool", metadata_pool
);
187 f
->dump_bool("enabled", enabled
);
188 f
->dump_string("fs_name", fs_name
);
189 f
->dump_string("balancer", balancer
);
190 f
->dump_int("standby_count_wanted", std::max(0, standby_count_wanted
));
193 void MDSMap::generate_test_instances(list
<MDSMap
*>& ls
)
195 MDSMap
*m
= new MDSMap();
197 m
->data_pools
.push_back(0);
198 m
->metadata_pool
= 1;
200 m
->compat
= get_mdsmap_compat_set_all();
202 // these aren't the defaults, just in case anybody gets confused
203 m
->session_timeout
= 61;
204 m
->session_autoclose
= 301;
205 m
->max_file_size
= 1<<24;
209 void MDSMap::print(ostream
& out
) const
211 out
<< "fs_name\t" << fs_name
<< "\n";
212 out
<< "epoch\t" << epoch
<< "\n";
213 out
<< "flags\t" << hex
<< flags
<< dec
<< "\n";
214 out
<< "created\t" << created
<< "\n";
215 out
<< "modified\t" << modified
<< "\n";
216 out
<< "tableserver\t" << tableserver
<< "\n";
217 out
<< "root\t" << root
<< "\n";
218 out
<< "session_timeout\t" << session_timeout
<< "\n"
219 << "session_autoclose\t" << session_autoclose
<< "\n";
220 out
<< "max_file_size\t" << max_file_size
<< "\n";
221 out
<< "last_failure\t" << last_failure
<< "\n"
222 << "last_failure_osd_epoch\t" << last_failure_osd_epoch
<< "\n";
223 out
<< "compat\t" << compat
<< "\n";
224 out
<< "max_mds\t" << max_mds
<< "\n";
225 out
<< "in\t" << in
<< "\n"
226 << "up\t" << up
<< "\n"
227 << "failed\t" << failed
<< "\n"
228 << "damaged\t" << damaged
<< "\n"
229 << "stopped\t" << stopped
<< "\n";
230 out
<< "data_pools\t" << data_pools
<< "\n";
231 out
<< "metadata_pool\t" << metadata_pool
<< "\n";
232 out
<< "inline_data\t" << (inline_data_enabled
? "enabled" : "disabled") << "\n";
233 out
<< "balancer\t" << balancer
<< "\n";
234 out
<< "standby_count_wanted\t" << std::max(0, standby_count_wanted
) << "\n";
236 multimap
< pair
<mds_rank_t
, unsigned>, mds_gid_t
> foo
;
237 for (const auto &p
: mds_info
) {
238 foo
.insert(std::make_pair(
239 std::make_pair(p
.second
.rank
, p
.second
.inc
-1), p
.first
));
242 for (const auto &p
: foo
) {
243 const mds_info_t
& info
= mds_info
.at(p
.second
);
244 info
.print_summary(out
);
251 void MDSMap::print_summary(Formatter
*f
, ostream
*out
) const
253 map
<mds_rank_t
,string
> by_rank
;
254 map
<string
,int> by_state
;
257 f
->dump_unsigned("epoch", get_epoch());
258 f
->dump_unsigned("up", up
.size());
259 f
->dump_unsigned("in", in
.size());
260 f
->dump_unsigned("max", max_mds
);
262 *out
<< "e" << get_epoch() << ": " << up
.size() << "/" << in
.size() << "/" << max_mds
<< " up";
266 f
->open_array_section("by_rank");
267 for (const auto &p
: mds_info
) {
268 string s
= ceph_mds_state_name(p
.second
.state
);
269 if (p
.second
.laggy())
270 s
+= "(laggy or crashed)";
272 if (p
.second
.rank
>= 0 && p
.second
.state
!= MDSMap::STATE_STANDBY_REPLAY
) {
274 f
->open_object_section("mds");
275 f
->dump_unsigned("rank", p
.second
.rank
);
276 f
->dump_string("name", p
.second
.name
);
277 f
->dump_string("status", s
);
280 by_rank
[p
.second
.rank
] = p
.second
.name
+ "=" + s
;
289 if (!by_rank
.empty())
290 *out
<< " " << by_rank
;
293 for (map
<string
,int>::reverse_iterator p
= by_state
.rbegin(); p
!= by_state
.rend(); ++p
) {
295 f
->dump_unsigned(p
->first
.c_str(), p
->second
);
297 *out
<< ", " << p
->second
<< " " << p
->first
;
301 if (!failed
.empty()) {
303 f
->dump_unsigned("failed", failed
.size());
305 *out
<< ", " << failed
.size() << " failed";
309 if (!damaged
.empty()) {
311 f
->dump_unsigned("damaged", damaged
.size());
313 *out
<< ", " << damaged
.size() << " damaged";
316 //if (stopped.size())
317 //out << ", " << stopped.size() << " stopped";
320 void MDSMap::get_health(list
<pair
<health_status_t
,string
> >& summary
,
321 list
<pair
<health_status_t
,string
> > *detail
) const
323 if (!failed
.empty()) {
324 std::ostringstream oss
;
326 << ((failed
.size() > 1) ? "s ":" ")
328 << ((failed
.size() > 1) ? " have":" has")
330 summary
.push_back(make_pair(HEALTH_ERR
, oss
.str()));
332 for (set
<mds_rank_t
>::const_iterator p
= failed
.begin(); p
!= failed
.end(); ++p
) {
333 std::ostringstream oss
;
334 oss
<< "mds." << *p
<< " has failed";
335 detail
->push_back(make_pair(HEALTH_ERR
, oss
.str()));
340 if (!damaged
.empty()) {
341 std::ostringstream oss
;
343 << ((damaged
.size() > 1) ? "s ":" ")
345 << ((damaged
.size() > 1) ? " are":" is")
347 summary
.push_back(make_pair(HEALTH_ERR
, oss
.str()));
349 for (set
<mds_rank_t
>::const_iterator p
= damaged
.begin(); p
!= damaged
.end(); ++p
) {
350 std::ostringstream oss
;
351 oss
<< "mds." << *p
<< " is damaged";
352 detail
->push_back(make_pair(HEALTH_ERR
, oss
.str()));
358 summary
.push_back(make_pair(HEALTH_WARN
, "mds cluster is degraded"));
360 detail
->push_back(make_pair(HEALTH_WARN
, "mds cluster is degraded"));
361 for (mds_rank_t i
= mds_rank_t(0); i
< get_max_mds(); i
++) {
364 mds_gid_t gid
= up
.find(i
)->second
;
365 map
<mds_gid_t
,mds_info_t
>::const_iterator info
= mds_info
.find(gid
);
368 ss
<< "mds." << info
->second
.name
<< " at " << info
->second
.addr
<< " rank " << i
<< " is resolving";
370 ss
<< "mds." << info
->second
.name
<< " at " << info
->second
.addr
<< " rank " << i
<< " is replaying journal";
372 ss
<< "mds." << info
->second
.name
<< " at " << info
->second
.addr
<< " rank " << i
<< " is rejoining";
374 ss
<< "mds." << info
->second
.name
<< " at " << info
->second
.addr
<< " rank " << i
<< " is reconnecting to clients";
375 if (ss
.str().length())
376 detail
->push_back(make_pair(HEALTH_WARN
, ss
.str()));
381 map
<mds_gid_t
, mds_info_t
>::const_iterator m_end
= mds_info
.end();
383 for (const auto &u
: up
) {
384 map
<mds_gid_t
, mds_info_t
>::const_iterator m
= mds_info
.find(u
.second
);
386 std::cerr
<< "Up rank " << u
.first
<< " GID " << u
.second
<< " not found!" << std::endl
;
389 const mds_info_t
&mds_info(m
->second
);
390 if (mds_info
.laggy()) {
391 laggy
.insert(mds_info
.name
);
393 std::ostringstream oss
;
394 oss
<< "mds." << mds_info
.name
<< " at " << mds_info
.addr
<< " is laggy/unresponsive";
395 detail
->push_back(make_pair(HEALTH_WARN
, oss
.str()));
400 if (!laggy
.empty()) {
401 std::ostringstream oss
;
402 oss
<< "mds " << laggy
403 << ((laggy
.size() > 1) ? " are":" is")
405 summary
.push_back(make_pair(HEALTH_WARN
, oss
.str()));
409 void MDSMap::get_health_checks(health_check_map_t
*checks
) const
411 // FS_WITH_FAILED_MDS
413 if (!failed
.empty()) {
414 health_check_t
& fscheck
= checks
->add(
415 "FS_WITH_FAILED_MDS", HEALTH_WARN
,
416 "%num% filesystem%plurals% %isorare% have a failed mds daemon");
418 ss
<< "fs " << fs_name
<< " has " << failed
.size() << " failed mds"
419 << (failed
.size() > 1 ? "s" : "");
420 fscheck
.detail
.push_back(ss
.str());
422 health_check_t
& check
= checks
->add("MDS_FAILED", HEALTH_ERR
,
423 "%num% mds daemon%plurals% down");
424 for (auto p
: failed
) {
425 std::ostringstream oss
;
426 oss
<< "fs " << fs_name
<< " mds." << p
<< " has failed";
427 check
.detail
.push_back(oss
.str());
432 if (!damaged
.empty()) {
433 health_check_t
& check
= checks
->add("MDS_DAMAGED", HEALTH_ERR
,
434 "%num% mds daemon%plurals% damaged");
435 for (auto p
: damaged
) {
436 std::ostringstream oss
;
437 oss
<< "fs " << fs_name
<< " mds." << p
<< " is damaged";
438 check
.detail
.push_back(oss
.str());
445 health_check_t
& fscheck
= checks
->add(
446 "FS_DEGRADED", HEALTH_WARN
,
447 "%num% filesystem%plurals% %isorare% degraded");
449 ss
<< "fs " << fs_name
<< " is degraded";
450 fscheck
.detail
.push_back(ss
.str());
453 for (mds_rank_t i
= mds_rank_t(0); i
< get_max_mds(); i
++) {
456 mds_gid_t gid
= up
.find(i
)->second
;
457 map
<mds_gid_t
,mds_info_t
>::const_iterator info
= mds_info
.find(gid
);
459 ss
<< "fs " << fs_name
<< " mds." << info
->second
.name
<< " at "
460 << info
->second
.addr
<< " rank " << i
;
462 ss
<< " is resolving";
464 ss
<< " is replaying journal";
466 ss
<< " is rejoining";
468 ss
<< " is reconnecting to clients";
469 if (ss
.str().length())
470 detail
.push_back(ss
.str());
472 if (!detail
.empty()) {
473 health_check_t
& check
= checks
->add(
474 "MDS_DEGRADED", HEALTH_WARN
,
475 "%num% mds daemon%plurals% %isorare% degraded");
476 check
.detail
.insert(check
.detail
.end(), detail
.begin(), detail
.end());
481 void MDSMap::mds_info_t::encode_versioned(bufferlist
& bl
, uint64_t features
) const
483 ENCODE_START(7, 4, bl
);
484 ::encode(global_id
, bl
);
488 ::encode((int32_t)state
, bl
);
489 ::encode(state_seq
, bl
);
490 ::encode(addr
, bl
, features
);
491 ::encode(laggy_since
, bl
);
492 ::encode(standby_for_rank
, bl
);
493 ::encode(standby_for_name
, bl
);
494 ::encode(export_targets
, bl
);
495 ::encode(mds_features
, bl
);
496 ::encode(standby_for_fscid
, bl
);
497 ::encode(standby_replay
, bl
);
501 void MDSMap::mds_info_t::encode_unversioned(bufferlist
& bl
) const
504 ::encode(struct_v
, bl
);
505 ::encode(global_id
, bl
);
509 ::encode((int32_t)state
, bl
);
510 ::encode(state_seq
, bl
);
511 ::encode(addr
, bl
, 0);
512 ::encode(laggy_since
, bl
);
513 ::encode(standby_for_rank
, bl
);
514 ::encode(standby_for_name
, bl
);
515 ::encode(export_targets
, bl
);
518 void MDSMap::mds_info_t::decode(bufferlist::iterator
& bl
)
520 DECODE_START_LEGACY_COMPAT_LEN(7, 4, 4, bl
);
521 ::decode(global_id
, bl
);
525 ::decode((int32_t&)(state
), bl
);
526 ::decode(state_seq
, bl
);
528 ::decode(laggy_since
, bl
);
529 ::decode(standby_for_rank
, bl
);
530 ::decode(standby_for_name
, bl
);
532 ::decode(export_targets
, bl
);
534 ::decode(mds_features
, bl
);
536 ::decode(standby_for_fscid
, bl
);
539 ::decode(standby_replay
, bl
);
546 void MDSMap::encode(bufferlist
& bl
, uint64_t features
) const
548 std::map
<mds_rank_t
,int32_t> inc
; // Legacy field, fake it so that
549 // old-mon peers have something sane
551 for (const auto rank
: in
) {
552 inc
.insert(std::make_pair(rank
, epoch
));
555 if ((features
& CEPH_FEATURE_PGID64
) == 0) {
560 ::encode(last_failure
, bl
);
562 ::encode(session_timeout
, bl
);
563 ::encode(session_autoclose
, bl
);
564 ::encode(max_file_size
, bl
);
565 ::encode(max_mds
, bl
);
566 __u32 n
= mds_info
.size();
568 for (map
<mds_gid_t
, mds_info_t
>::const_iterator i
= mds_info
.begin();
569 i
!= mds_info
.end(); ++i
) {
570 ::encode(i
->first
, bl
);
571 ::encode(i
->second
, bl
, features
);
573 n
= data_pools
.size();
575 for (const auto p
: data_pools
) {
580 int32_t m
= cas_pool
;
583 } else if ((features
& CEPH_FEATURE_MDSENC
) == 0) {
588 ::encode(last_failure
, bl
);
590 ::encode(session_timeout
, bl
);
591 ::encode(session_autoclose
, bl
);
592 ::encode(max_file_size
, bl
);
593 ::encode(max_mds
, bl
);
594 __u32 n
= mds_info
.size();
596 for (map
<mds_gid_t
, mds_info_t
>::const_iterator i
= mds_info
.begin();
597 i
!= mds_info
.end(); ++i
) {
598 ::encode(i
->first
, bl
);
599 ::encode(i
->second
, bl
, features
);
601 ::encode(data_pools
, bl
);
602 ::encode(cas_pool
, bl
);
604 // kclient ignores everything from here
607 ::encode(compat
, bl
);
608 ::encode(metadata_pool
, bl
);
609 ::encode(created
, bl
);
610 ::encode(modified
, bl
);
611 ::encode(tableserver
, bl
);
615 ::encode(failed
, bl
);
616 ::encode(stopped
, bl
);
617 ::encode(last_failure_osd_epoch
, bl
);
621 ENCODE_START(5, 4, bl
);
624 ::encode(last_failure
, bl
);
626 ::encode(session_timeout
, bl
);
627 ::encode(session_autoclose
, bl
);
628 ::encode(max_file_size
, bl
);
629 ::encode(max_mds
, bl
);
630 ::encode(mds_info
, bl
, features
);
631 ::encode(data_pools
, bl
);
632 ::encode(cas_pool
, bl
);
634 // kclient ignores everything from here
637 ::encode(compat
, bl
);
638 ::encode(metadata_pool
, bl
);
639 ::encode(created
, bl
);
640 ::encode(modified
, bl
);
641 ::encode(tableserver
, bl
);
645 ::encode(failed
, bl
);
646 ::encode(stopped
, bl
);
647 ::encode(last_failure_osd_epoch
, bl
);
648 ::encode(ever_allowed_features
, bl
);
649 ::encode(explicitly_allowed_features
, bl
);
650 ::encode(inline_data_enabled
, bl
);
651 ::encode(enabled
, bl
);
652 ::encode(fs_name
, bl
);
653 ::encode(damaged
, bl
);
654 ::encode(balancer
, bl
);
655 ::encode(standby_count_wanted
, bl
);
659 void MDSMap::decode(bufferlist::iterator
& p
)
661 std::map
<mds_rank_t
,int32_t> inc
; // Legacy field, parse and drop
663 cached_up_features
= 0;
664 DECODE_START_LEGACY_COMPAT_LEN_16(5, 4, 4, p
);
667 ::decode(last_failure
, p
);
669 ::decode(session_timeout
, p
);
670 ::decode(session_autoclose
, p
);
671 ::decode(max_file_size
, p
);
672 ::decode(max_mds
, p
);
673 ::decode(mds_info
, p
);
680 data_pools
.push_back(m
);
686 ::decode(data_pools
, p
);
687 ::decode(cas_pool
, p
);
690 // kclient ignores everything from here
697 compat
= get_mdsmap_compat_set_base();
703 ::decode(metadata_pool
, p
);
705 ::decode(created
, p
);
706 ::decode(modified
, p
);
707 ::decode(tableserver
, p
);
712 ::decode(stopped
, p
);
714 ::decode(last_failure_osd_epoch
, p
);
717 // previously this was a bool about snaps, not a flag map
720 ever_allowed_features
= flag
? CEPH_MDSMAP_ALLOW_SNAPS
: 0;
721 ever_allowed_features
|= CEPH_MDSMAP_ALLOW_MULTIMDS
|CEPH_MDSMAP_ALLOW_DIRFRAGS
;
723 explicitly_allowed_features
= flag
? CEPH_MDSMAP_ALLOW_SNAPS
: 0;
725 set_multimds_allowed();
728 ::decode(ever_allowed_features
, p
);
729 ::decode(explicitly_allowed_features
, p
);
732 ever_allowed_features
= CEPH_MDSMAP_ALLOW_CLASSICS
;
733 explicitly_allowed_features
= 0;
735 set_multimds_allowed();
739 ::decode(inline_data_enabled
, p
);
742 assert(struct_v
>= 5);
743 ::decode(enabled
, p
);
744 ::decode(fs_name
, p
);
747 // If an MDS has ever been started, epoch will be greater than 1,
748 // assume filesystem is enabled.
751 // Upgrading from a cluster that never used an MDS, switch off
752 // filesystem until it's explicitly enabled.
758 ::decode(damaged
, p
);
762 ::decode(balancer
, p
);
766 ::decode(standby_count_wanted
, p
);
772 MDSMap::availability_t
MDSMap::is_cluster_available() const
775 // If I'm a client, this means I'm looking at an MDSMap instance
776 // that was never actually initialized from the mons. Client should
778 return TRANSIENT_UNAVAILABLE
;
781 // If a rank is marked damage (unavailable until operator intervenes)
782 if (damaged
.size()) {
783 return STUCK_UNAVAILABLE
;
786 // If no ranks are created (filesystem not initialized)
788 return STUCK_UNAVAILABLE
;
791 for (const auto rank
: in
) {
792 if (up
.count(rank
) && mds_info
.at(up
.at(rank
)).laggy()) {
793 // This might only be transient, but because we can't see
794 // standbys, we have no way of knowing whether there is a
795 // standby available to replace the laggy guy.
796 return STUCK_UNAVAILABLE
;
800 if (get_num_mds(CEPH_MDS_STATE_ACTIVE
) > 0) {
801 // Nobody looks stuck, so indicate to client they should go ahead
802 // and try mounting if anybody is active. This may include e.g.
803 // one MDS failing over and another active: the client should
804 // proceed to start talking to the active one and let the
805 // transiently-unavailable guy catch up later.
808 // Nothing indicating we were stuck, but nobody active (yet)
809 //return TRANSIENT_UNAVAILABLE;
811 // Because we don't have standbys in the MDSMap any more, we can't
812 // reliably indicate transient vs. stuck, so always say stuck so
813 // that the client doesn't block.
814 return STUCK_UNAVAILABLE
;
818 bool MDSMap::state_transition_valid(DaemonState prev
, DaemonState next
)
820 bool state_valid
= true;
822 if (prev
== MDSMap::STATE_REPLAY
) {
823 if (next
!= MDSMap::STATE_RESOLVE
&& next
!= MDSMap::STATE_RECONNECT
) {
826 } else if (prev
== MDSMap::STATE_REJOIN
) {
827 if (next
!= MDSMap::STATE_ACTIVE
828 && next
!= MDSMap::STATE_CLIENTREPLAY
829 && next
!= MDSMap::STATE_STOPPED
) {
832 } else if (prev
>= MDSMap::STATE_RECONNECT
&& prev
< MDSMap::STATE_ACTIVE
) {
833 // Once I have entered replay, the only allowable transitions are to
834 // the next next along in the sequence.
835 if (next
!= prev
+ 1) {
844 bool MDSMap::check_health(mds_rank_t standby_daemon_count
)
846 std::set
<mds_rank_t
> standbys
;
847 get_standby_replay_mds_set(standbys
);
848 std::set
<mds_rank_t
> actives
;
849 get_active_mds_set(actives
);
850 mds_rank_t standbys_avail
= (mds_rank_t
)standbys
.size()+standby_daemon_count
;
852 /* If there are standby daemons available/replaying and
853 * standby_count_wanted is unset (default), then we set it to 1. This will
854 * happen during health checks by the mons. Also, during initial creation
855 * of the FS we will have no actives so we don't want to change the default
858 if (standby_count_wanted
== -1 && actives
.size() > 0 && standbys_avail
> 0) {
859 set_standby_count_wanted(1);