]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/FSMap.h
update sources to v12.2.5
[ceph.git] / ceph / src / mds / FSMap.h
CommitLineData
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
16#ifndef CEPH_FSMAP_H
17#define CEPH_FSMAP_H
18
94b18763
FG
19#include <map>
20#include <set>
21#include <string>
22#include <boost/utility/string_view.hpp>
23
7c673cae
FG
24#include <errno.h>
25
26#include "include/types.h"
27#include "common/Clock.h"
28#include "msg/Message.h"
29#include "mds/MDSMap.h"
30
7c673cae
FG
31#include "common/config.h"
32
33#include "include/CompatSet.h"
34#include "include/ceph_features.h"
35#include "common/Formatter.h"
36#include "mds/mdstypes.h"
37
38class CephContext;
224ce89b 39class health_check_map_t;
7c673cae 40
7c673cae
FG
41#define MDS_FS_NAME_DEFAULT "cephfs"
42
43/**
44 * The MDSMap and any additional fields describing a particular
45 * filesystem (a unique fs_cluster_id_t).
46 */
47class Filesystem
48{
49 public:
50 fs_cluster_id_t fscid;
51 MDSMap mds_map;
52
53 void encode(bufferlist& bl, uint64_t features) const;
54 void decode(bufferlist::iterator& p);
55
56 Filesystem()
57 :
58 fscid(FS_CLUSTER_ID_NONE)
59 {
60 }
61
62 void dump(Formatter *f) const;
63 void print(std::ostream& out) const;
64
65 /**
66 * Return true if a daemon is already assigned as
67 * STANDBY_REPLAY for the gid `who`
68 */
69 bool has_standby_replay(mds_gid_t who) const
70 {
71 for (const auto &i : mds_map.mds_info) {
72 const auto &info = i.second;
73 if (info.state == MDSMap::STATE_STANDBY_REPLAY
74 && info.rank == mds_map.mds_info.at(who).rank) {
75 return true;
76 }
77 }
78
79 return false;
80 }
81};
82WRITE_CLASS_ENCODER_FEATURES(Filesystem)
83
84class FSMap {
85protected:
86 epoch_t epoch;
87 uint64_t next_filesystem_id;
88 fs_cluster_id_t legacy_client_fscid;
89 CompatSet compat;
90 bool enable_multiple;
91 bool ever_enabled_multiple; // < the cluster had multiple MDSes enabled once
92
93 std::map<fs_cluster_id_t, std::shared_ptr<Filesystem> > filesystems;
94
95 // Remember which Filesystem an MDS daemon's info is stored in
96 // (or in standby_daemons for FS_CLUSTER_ID_NONE)
97 std::map<mds_gid_t, fs_cluster_id_t> mds_roles;
98
99 // For MDS daemons not yet assigned to a Filesystem
100 std::map<mds_gid_t, MDSMap::mds_info_t> standby_daemons;
101 std::map<mds_gid_t, epoch_t> standby_epochs;
102
103public:
104
105 friend class MDSMonitor;
106
107 FSMap()
108 : epoch(0),
109 next_filesystem_id(FS_CLUSTER_ID_ANONYMOUS + 1),
110 legacy_client_fscid(FS_CLUSTER_ID_NONE),
111 compat(get_mdsmap_compat_set_default()),
112 enable_multiple(false), ever_enabled_multiple(false)
113 { }
114
115 FSMap(const FSMap &rhs)
116 :
117 epoch(rhs.epoch),
118 next_filesystem_id(rhs.next_filesystem_id),
119 legacy_client_fscid(rhs.legacy_client_fscid),
120 compat(rhs.compat),
121 enable_multiple(rhs.enable_multiple),
122 ever_enabled_multiple(rhs.ever_enabled_multiple),
123 mds_roles(rhs.mds_roles),
124 standby_daemons(rhs.standby_daemons),
125 standby_epochs(rhs.standby_epochs)
126 {
b32b8144 127 filesystems.clear();
7c673cae
FG
128 for (const auto &i : rhs.filesystems) {
129 const auto &fs = i.second;
130 filesystems[fs->fscid] = std::make_shared<Filesystem>(*fs);
131 }
132 }
133
134 FSMap &operator=(const FSMap &rhs)
135 {
136 epoch = rhs.epoch;
137 next_filesystem_id = rhs.next_filesystem_id;
138 legacy_client_fscid = rhs.legacy_client_fscid;
139 compat = rhs.compat;
140 enable_multiple = rhs.enable_multiple;
141 mds_roles = rhs.mds_roles;
142 standby_daemons = rhs.standby_daemons;
143 standby_epochs = rhs.standby_epochs;
144
b32b8144 145 filesystems.clear();
7c673cae
FG
146 for (const auto &i : rhs.filesystems) {
147 const auto &fs = i.second;
148 filesystems[fs->fscid] = std::make_shared<Filesystem>(*fs);
149 }
150
151 return *this;
152 }
153
154 const CompatSet &get_compat() const {return compat;}
155
156 void set_enable_multiple(const bool v)
157 {
158 enable_multiple = v;
159 if (true == v) {
160 ever_enabled_multiple = true;
161 }
162 }
163
164 bool get_enable_multiple() const
165 {
166 return enable_multiple;
167 }
168
169 void set_legacy_client_fscid(fs_cluster_id_t fscid)
170 {
171 assert(fscid == FS_CLUSTER_ID_NONE || filesystems.count(fscid));
172 legacy_client_fscid = fscid;
173 }
174
175 fs_cluster_id_t get_legacy_client_fscid() const
176 {
177 return legacy_client_fscid;
178 }
179
180 /**
181 * Get state of all daemons (for all filesystems, including all standbys)
182 */
183 std::map<mds_gid_t, MDSMap::mds_info_t> get_mds_info() const
184 {
185 std::map<mds_gid_t, MDSMap::mds_info_t> result;
186 for (const auto &i : standby_daemons) {
187 result[i.first] = i.second;
188 }
189
190 for (const auto &i : filesystems) {
191 const auto &fs_info = i.second->mds_map.get_mds_info();
192 for (const auto &j : fs_info) {
193 result[j.first] = j.second;
194 }
195 }
196
197 return result;
198 }
199
200 /**
201 * Resolve daemon name to GID
202 */
94b18763 203 mds_gid_t find_mds_gid_by_name(boost::string_view s) const
7c673cae
FG
204 {
205 const auto info = get_mds_info();
206 for (const auto &p : info) {
207 if (p.second.name == s) {
208 return p.first;
209 }
210 }
211 return MDS_GID_NONE;
212 }
213
214 /**
215 * Resolve daemon name to status
216 */
94b18763 217 const MDSMap::mds_info_t* find_by_name(boost::string_view name) const
7c673cae
FG
218 {
219 std::map<mds_gid_t, MDSMap::mds_info_t> result;
220 for (const auto &i : standby_daemons) {
221 if (i.second.name == name) {
222 return &(i.second);
223 }
224 }
225
226 for (const auto &i : filesystems) {
227 const auto &fs_info = i.second->mds_map.get_mds_info();
228 for (const auto &j : fs_info) {
229 if (j.second.name == name) {
230 return &(j.second);
231 }
232 }
233 }
234
235 return nullptr;
236 }
237
238 /**
239 * Does a daemon exist with this GID?
240 */
241 bool gid_exists(mds_gid_t gid) const
242 {
243 return mds_roles.count(gid) > 0;
244 }
245
246 /**
247 * Does a daemon with this GID exist, *and* have an MDS rank assigned?
248 */
249 bool gid_has_rank(mds_gid_t gid) const
250 {
251 return gid_exists(gid) && mds_roles.at(gid) != FS_CLUSTER_ID_NONE;
252 }
253
254 /**
255 * Insert a new MDS daemon, as a standby
256 */
257 void insert(const MDSMap::mds_info_t &new_info);
258
259 /**
260 * Assign an MDS cluster standby replay rank to a standby daemon
261 */
262 void assign_standby_replay(
263 const mds_gid_t standby_gid,
264 const fs_cluster_id_t leader_ns,
265 const mds_rank_t leader_rank);
266
267 /**
268 * Assign an MDS cluster rank to a standby daemon
269 */
270 void promote(
271 mds_gid_t standby_gid,
272 const std::shared_ptr<Filesystem> &filesystem,
273 mds_rank_t assigned_rank);
274
275 /**
276 * A daemon reports that it is STATE_STOPPED: remove it,
277 * and the rank it held.
278 *
279 * @returns a list of any additional GIDs that were removed from the map
280 * as a side effect (like standby replays)
281 */
282 std::list<mds_gid_t> stop(mds_gid_t who);
283
284 /**
285 * The rank held by 'who', if any, is to be relinquished, and
286 * the state for the daemon GID is to be forgotten.
287 */
288 void erase(mds_gid_t who, epoch_t blacklist_epoch);
289
290 /**
291 * Update to indicate that the rank held by 'who' is damaged
292 */
293 void damaged(mds_gid_t who, epoch_t blacklist_epoch);
294
295 /**
296 * Update to indicate that the rank `rank` is to be removed
297 * from the damaged list of the filesystem `fscid`
298 */
299 bool undamaged(const fs_cluster_id_t fscid, const mds_rank_t rank);
300
301 /**
302 * Initialize a Filesystem and assign a fscid. Update legacy_client_fscid
303 * to point to the new filesystem if it's the only one.
304 *
305 * Caller must already have validated all arguments vs. the existing
306 * FSMap and OSDMap contents.
307 */
94b18763 308 void create_filesystem(boost::string_view name,
7c673cae
FG
309 int64_t metadata_pool, int64_t data_pool,
310 uint64_t features);
311
312 /**
313 * Remove the filesystem (it must exist). Caller should already
314 * have failed out any MDSs that were assigned to the filesystem.
315 */
316 void erase_filesystem(fs_cluster_id_t fscid)
317 {
318 filesystems.erase(fscid);
319 }
320
321 /**
322 * Reset all the state information (not configuration information)
323 * in a particular filesystem. Caller must have verified that
324 * the filesystem already exists.
325 */
326 void reset_filesystem(fs_cluster_id_t fscid);
327
328 /**
329 * Mutator helper for Filesystem objects: expose a non-const
330 * Filesystem pointer to `fn` and update epochs appropriately.
331 */
332 void modify_filesystem(
333 const fs_cluster_id_t fscid,
334 std::function<void(std::shared_ptr<Filesystem> )> fn)
335 {
336 auto fs = filesystems.at(fscid);
337 fn(fs);
338 fs->mds_map.epoch = epoch;
339 }
340
341 /**
342 * Apply a mutation to the mds_info_t structure for a particular
343 * daemon (identified by GID), and make appropriate updates to epochs.
344 */
345 void modify_daemon(
346 mds_gid_t who,
347 std::function<void(MDSMap::mds_info_t *info)> fn)
348 {
349 if (mds_roles.at(who) == FS_CLUSTER_ID_NONE) {
350 auto &info = standby_daemons.at(who);
351 fn(&info);
352 assert(info.state == MDSMap::STATE_STANDBY);
353 standby_epochs[who] = epoch;
354 } else {
355 const auto &fs = filesystems[mds_roles.at(who)];
356 auto &info = fs->mds_map.mds_info.at(who);
357 fn(&info);
358
359 fs->mds_map.epoch = epoch;
360 }
361 }
362
363 /**
364 * Given that gid exists in a filesystem or as a standby, return
365 * a reference to its info.
366 */
367 const MDSMap::mds_info_t& get_info_gid(mds_gid_t gid) const
368 {
369 auto fscid = mds_roles.at(gid);
370 if (fscid == FS_CLUSTER_ID_NONE) {
371 return standby_daemons.at(gid);
372 } else {
373 return filesystems.at(fscid)->mds_map.mds_info.at(gid);
374 }
375 }
376
377 /**
378 * A daemon has told us it's compat, and it's too new
379 * for the one we had previously. Impose the new one
380 * on all filesystems.
381 */
382 void update_compat(const CompatSet &c)
383 {
384 // We could do something more complicated here to enable
385 // different filesystems to be served by different MDS versions,
386 // but this is a lot simpler because it doesn't require us to
387 // track the compat versions for standby daemons.
388 compat = c;
389 for (const auto &i : filesystems) {
390 MDSMap &mds_map = i.second->mds_map;
391 mds_map.compat = c;
392 mds_map.epoch = epoch;
393 }
394 }
395
396 std::shared_ptr<const Filesystem> get_legacy_filesystem()
397 {
398 if (legacy_client_fscid == FS_CLUSTER_ID_NONE) {
399 return nullptr;
400 } else {
401 return filesystems.at(legacy_client_fscid);
402 }
403 }
404
405 /**
406 * A daemon has informed us of its offload targets
407 */
408 void update_export_targets(mds_gid_t who, const std::set<mds_rank_t> targets)
409 {
410 auto fscid = mds_roles.at(who);
411 modify_filesystem(fscid, [who, &targets](std::shared_ptr<Filesystem> fs) {
412 fs->mds_map.mds_info.at(who).export_targets = targets;
413 });
414 }
415
416 epoch_t get_epoch() const { return epoch; }
417 void inc_epoch() { epoch++; }
418
419 size_t filesystem_count() const {return filesystems.size();}
420 bool filesystem_exists(fs_cluster_id_t fscid) const {return filesystems.count(fscid) > 0;}
421 std::shared_ptr<const Filesystem> get_filesystem(fs_cluster_id_t fscid) const {return std::const_pointer_cast<const Filesystem>(filesystems.at(fscid));}
422 std::shared_ptr<const Filesystem> get_filesystem(void) const {return std::const_pointer_cast<const Filesystem>(filesystems.begin()->second);}
94b18763 423 std::shared_ptr<const Filesystem> get_filesystem(boost::string_view name) const
7c673cae
FG
424 {
425 for (const auto &i : filesystems) {
426 if (i.second->mds_map.fs_name == name) {
427 return std::const_pointer_cast<const Filesystem>(i.second);
428 }
429 }
430 return nullptr;
431 }
432 std::list<std::shared_ptr<const Filesystem> > get_filesystems(void) const
433 {
434 std::list<std::shared_ptr<const Filesystem> > ret;
435 for (const auto &i : filesystems) {
436 ret.push_back(std::const_pointer_cast<const Filesystem>(i.second));
437 }
438 return ret;
439 }
440
441 int parse_filesystem(
94b18763 442 boost::string_view ns_str,
7c673cae
FG
443 std::shared_ptr<const Filesystem> *result
444 ) const;
445
446 int parse_role(
94b18763 447 boost::string_view role_str,
7c673cae
FG
448 mds_role_t *role,
449 std::ostream &ss) const;
450
451 /**
452 * Return true if this pool is in use by any of the filesystems
453 */
454 bool pool_in_use(int64_t poolid) const {
455 for (auto const &i : filesystems) {
456 if (i.second->mds_map.is_data_pool(poolid)
457 || i.second->mds_map.metadata_pool == poolid) {
458 return true;
459 }
460 }
461 return false;
462 }
463
94b18763 464 mds_gid_t find_standby_for(mds_role_t mds, boost::string_view name) const;
7c673cae 465
31f18b77 466 mds_gid_t find_unused_for(mds_role_t mds, bool force_standby_active) const;
7c673cae 467
94b18763 468 mds_gid_t find_replacement_for(mds_role_t mds, boost::string_view name,
7c673cae
FG
469 bool force_standby_active) const;
470
471 void get_health(list<pair<health_status_t,std::string> >& summary,
472 list<pair<health_status_t,std::string> > *detail) const;
473
224ce89b
WB
474 void get_health_checks(health_check_map_t *checks) const;
475
7c673cae
FG
476 bool check_health(void);
477
478 /**
479 * Assert that the FSMap, Filesystem, MDSMap, mds_info_t relations are
480 * all self-consistent.
481 */
482 void sanity() const;
483
484 void encode(bufferlist& bl, uint64_t features) const;
485 void decode(bufferlist::iterator& p);
486 void decode(bufferlist& bl) {
487 bufferlist::iterator p = bl.begin();
488 decode(p);
489 }
3efd9988 490 void sanitize(std::function<bool(int64_t pool)> pool_exists);
7c673cae
FG
491
492 void print(ostream& out) const;
493 void print_summary(Formatter *f, ostream *out) const;
494
495 void dump(Formatter *f) const;
496 static void generate_test_instances(list<FSMap*>& ls);
497};
498WRITE_CLASS_ENCODER_FEATURES(FSMap)
499
500inline ostream& operator<<(ostream& out, const FSMap& m) {
501 m.print_summary(NULL, &out);
502 return out;
503}
504
505#endif