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.
23 #include <string_view>
27 #include "include/types.h"
28 #include "common/Clock.h"
29 #include "mds/MDSMap.h"
31 #include "include/CompatSet.h"
32 #include "include/ceph_features.h"
33 #include "include/common_fwd.h"
34 #include "common/Formatter.h"
35 #include "mds/mdstypes.h"
37 class health_check_map_t
;
40 * The MDSMap and any additional fields describing a particular
41 * filesystem (a unique fs_cluster_id_t).
46 using ref
= std::shared_ptr
<Filesystem
>;
47 using const_ref
= std::shared_ptr
<Filesystem
const>;
49 template<typename
... Args
>
50 static ref
create(Args
&&... args
)
52 return std::make_shared
<Filesystem
>(std::forward
<Args
>(args
)...);
55 void encode(bufferlist
& bl
, uint64_t features
) const;
56 void decode(bufferlist::const_iterator
& p
);
58 void dump(Formatter
*f
) const;
59 void print(std::ostream
& out
) const;
62 * Return true if a daemon is already assigned as
63 * STANDBY_REPLAY for the gid `who`
65 bool has_standby_replay(mds_gid_t who
) const
67 return get_standby_replay(who
) != MDS_GID_NONE
;
69 mds_gid_t
get_standby_replay(mds_gid_t who
) const;
70 bool is_standby_replay(mds_gid_t who
) const
72 auto p
= mds_map
.mds_info
.find(who
);
73 if (p
!= mds_map
.mds_info
.end() &&
74 p
->second
.state
== MDSMap::STATE_STANDBY_REPLAY
) {
80 fs_cluster_id_t fscid
= FS_CLUSTER_ID_NONE
;
83 WRITE_CLASS_ENCODER_FEATURES(Filesystem
)
87 friend class MDSMonitor
;
88 friend class PaxosFSMap
;
89 using mds_info_t
= MDSMap::mds_info_t
;
91 FSMap() : compat(MDSMap::get_compat_set_default()) {}
93 FSMap(const FSMap
&rhs
)
96 next_filesystem_id(rhs
.next_filesystem_id
),
97 legacy_client_fscid(rhs
.legacy_client_fscid
),
99 enable_multiple(rhs
.enable_multiple
),
100 ever_enabled_multiple(rhs
.ever_enabled_multiple
),
101 mds_roles(rhs
.mds_roles
),
102 standby_daemons(rhs
.standby_daemons
),
103 standby_epochs(rhs
.standby_epochs
)
106 for (const auto &i
: rhs
.filesystems
) {
107 const auto &fs
= i
.second
;
108 filesystems
[fs
->fscid
] = std::make_shared
<Filesystem
>(*fs
);
112 FSMap
&operator=(const FSMap
&rhs
);
114 const CompatSet
&get_compat() const {return compat
;}
116 void set_enable_multiple(const bool v
)
120 ever_enabled_multiple
= true;
124 bool get_enable_multiple() const
126 return enable_multiple
;
129 void set_legacy_client_fscid(fs_cluster_id_t fscid
)
131 ceph_assert(fscid
== FS_CLUSTER_ID_NONE
|| filesystems
.count(fscid
));
132 legacy_client_fscid
= fscid
;
135 fs_cluster_id_t
get_legacy_client_fscid() const
137 return legacy_client_fscid
;
140 size_t get_num_standby() const {
141 return standby_daemons
.size();
144 bool is_any_degraded() const;
147 * Get state of all daemons (for all filesystems, including all standbys)
149 std::map
<mds_gid_t
, mds_info_t
> get_mds_info() const;
151 const mds_info_t
* get_available_standby(fs_cluster_id_t fscid
) const;
154 * Resolve daemon name to GID
156 mds_gid_t
find_mds_gid_by_name(std::string_view s
) const;
159 * Resolve daemon name to status
161 const mds_info_t
* find_by_name(std::string_view name
) const;
164 * Does a daemon exist with this GID?
166 bool gid_exists(mds_gid_t gid
) const
168 return mds_roles
.count(gid
) > 0;
172 * Does a daemon with this GID exist, *and* have an MDS rank assigned?
174 bool gid_has_rank(mds_gid_t gid
) const
176 return gid_exists(gid
) && mds_roles
.at(gid
) != FS_CLUSTER_ID_NONE
;
179 fs_cluster_id_t
gid_fscid(mds_gid_t gid
) const
181 return mds_roles
.at(gid
);
185 * Insert a new MDS daemon, as a standby
187 void insert(const mds_info_t
& new_info
);
190 * Assign an MDS cluster standby replay rank to a standby daemon
192 void assign_standby_replay(
193 const mds_gid_t standby_gid
,
194 const fs_cluster_id_t leader_ns
,
195 const mds_rank_t leader_rank
);
198 * Assign an MDS cluster rank to a standby daemon
201 mds_gid_t standby_gid
,
202 Filesystem
& filesystem
,
203 mds_rank_t assigned_rank
);
206 * A daemon reports that it is STATE_STOPPED: remove it,
207 * and the rank it held.
209 * @returns a list of any additional GIDs that were removed from the map
210 * as a side effect (like standby replays)
212 std::vector
<mds_gid_t
> stop(mds_gid_t who
);
215 * The rank held by 'who', if any, is to be relinquished, and
216 * the state for the daemon GID is to be forgotten.
218 void erase(mds_gid_t who
, epoch_t blacklist_epoch
);
221 * Update to indicate that the rank held by 'who' is damaged
223 void damaged(mds_gid_t who
, epoch_t blacklist_epoch
);
226 * Update to indicate that the rank `rank` is to be removed
227 * from the damaged list of the filesystem `fscid`
229 bool undamaged(const fs_cluster_id_t fscid
, const mds_rank_t rank
);
232 * Initialize a Filesystem and assign a fscid. Update legacy_client_fscid
233 * to point to the new filesystem if it's the only one.
235 * Caller must already have validated all arguments vs. the existing
236 * FSMap and OSDMap contents.
238 Filesystem::ref
create_filesystem(
239 std::string_view name
, int64_t metadata_pool
,
240 int64_t data_pool
, uint64_t features
);
243 * Remove the filesystem (it must exist). Caller should already
244 * have failed out any MDSs that were assigned to the filesystem.
246 void erase_filesystem(fs_cluster_id_t fscid
);
249 * Reset all the state information (not configuration information)
250 * in a particular filesystem. Caller must have verified that
251 * the filesystem already exists.
253 void reset_filesystem(fs_cluster_id_t fscid
);
256 * Mutator helper for Filesystem objects: expose a non-const
257 * Filesystem pointer to `fn` and update epochs appropriately.
260 void modify_filesystem(fs_cluster_id_t fscid
, T
&& fn
)
262 auto& fs
= filesystems
.at(fscid
);
264 fs
->mds_map
.epoch
= epoch
;
268 * Apply a mutation to the mds_info_t structure for a particular
269 * daemon (identified by GID), and make appropriate updates to epochs.
272 void modify_daemon(mds_gid_t who
, T
&& fn
)
274 const auto& fscid
= mds_roles
.at(who
);
275 if (fscid
== FS_CLUSTER_ID_NONE
) {
276 auto& info
= standby_daemons
.at(who
);
278 ceph_assert(info
.state
== MDSMap::STATE_STANDBY
);
279 standby_epochs
[who
] = epoch
;
281 auto& fs
= filesystems
.at(fscid
);
282 auto& info
= fs
->mds_map
.mds_info
.at(who
);
284 fs
->mds_map
.epoch
= epoch
;
289 * Given that gid exists in a filesystem or as a standby, return
290 * a reference to its info.
292 const mds_info_t
& get_info_gid(mds_gid_t gid
) const
294 auto fscid
= mds_roles
.at(gid
);
295 if (fscid
== FS_CLUSTER_ID_NONE
) {
296 return standby_daemons
.at(gid
);
298 return filesystems
.at(fscid
)->mds_map
.mds_info
.at(gid
);
302 bool is_standby_replay(mds_gid_t who
) const
304 return filesystems
.at(mds_roles
.at(who
))->is_standby_replay(who
);
307 mds_gid_t
get_standby_replay(mds_gid_t who
) const
309 return filesystems
.at(mds_roles
.at(who
))->get_standby_replay(who
);
313 * A daemon has told us it's compat, and it's too new
314 * for the one we had previously. Impose the new one
315 * on all filesystems.
317 void update_compat(const CompatSet
&c
);
319 Filesystem::const_ref
get_legacy_filesystem()
321 if (legacy_client_fscid
== FS_CLUSTER_ID_NONE
) {
324 return filesystems
.at(legacy_client_fscid
);
329 * A daemon has informed us of its offload targets
331 void update_export_targets(mds_gid_t who
, const std::set
<mds_rank_t
> &targets
)
333 auto fscid
= mds_roles
.at(who
);
334 modify_filesystem(fscid
, [who
, &targets
](auto&& fs
) {
335 fs
->mds_map
.mds_info
.at(who
).export_targets
= targets
;
339 epoch_t
get_epoch() const { return epoch
; }
340 void inc_epoch() { epoch
++; }
342 size_t filesystem_count() const {return filesystems
.size();}
343 bool filesystem_exists(fs_cluster_id_t fscid
) const {return filesystems
.count(fscid
) > 0;}
344 Filesystem::const_ref
get_filesystem(fs_cluster_id_t fscid
) const {return std::const_pointer_cast
<const Filesystem
>(filesystems
.at(fscid
));}
345 Filesystem::ref
get_filesystem(fs_cluster_id_t fscid
) {return filesystems
.at(fscid
);}
346 Filesystem::const_ref
get_filesystem(void) const {return std::const_pointer_cast
<const Filesystem
>(filesystems
.begin()->second
);}
347 Filesystem::const_ref
get_filesystem(std::string_view name
) const;
349 std::vector
<Filesystem::const_ref
> get_filesystems(void) const;
351 int parse_filesystem(
352 std::string_view ns_str
,
353 Filesystem::const_ref
*result
357 std::string_view role_str
,
359 std::ostream
&ss
) const;
362 * Return true if this pool is in use by any of the filesystems
364 bool pool_in_use(int64_t poolid
) const;
366 const mds_info_t
* find_replacement_for(mds_role_t role
) const;
368 void get_health(list
<pair
<health_status_t
,std::string
> >& summary
,
369 list
<pair
<health_status_t
,std::string
> > *detail
) const;
371 void get_health_checks(health_check_map_t
*checks
) const;
373 bool check_health(void);
376 * Assert that the FSMap, Filesystem, MDSMap, mds_info_t relations are
377 * all self-consistent.
381 void encode(bufferlist
& bl
, uint64_t features
) const;
382 void decode(bufferlist::const_iterator
& p
);
383 void decode(bufferlist
& bl
) {
384 auto p
= bl
.cbegin();
387 void sanitize(const std::function
<bool(int64_t pool
)>& pool_exists
);
389 void print(ostream
& out
) const;
390 void print_summary(Formatter
*f
, ostream
*out
) const;
392 void dump(Formatter
*f
) const;
393 static void generate_test_instances(std::list
<FSMap
*>& ls
);
397 uint64_t next_filesystem_id
= FS_CLUSTER_ID_ANONYMOUS
+ 1;
398 fs_cluster_id_t legacy_client_fscid
= FS_CLUSTER_ID_NONE
;
400 bool enable_multiple
= false;
401 bool ever_enabled_multiple
= false; // < the cluster had multiple MDSes enabled once
403 std::map
<fs_cluster_id_t
, Filesystem::ref
> filesystems
;
405 // Remember which Filesystem an MDS daemon's info is stored in
406 // (or in standby_daemons for FS_CLUSTER_ID_NONE)
407 std::map
<mds_gid_t
, fs_cluster_id_t
> mds_roles
;
409 // For MDS daemons not yet assigned to a Filesystem
410 std::map
<mds_gid_t
, mds_info_t
> standby_daemons
;
411 std::map
<mds_gid_t
, epoch_t
> standby_epochs
;
413 WRITE_CLASS_ENCODER_FEATURES(FSMap
)
415 inline ostream
& operator<<(ostream
& out
, const FSMap
& m
) {
416 m
.print_summary(NULL
, &out
);