1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #ifndef CEPH_MDSTYPES_H
4 #define CEPH_MDSTYPES_H
6 #include "include/int_types.h"
11 #include <string_view>
13 #include "common/config.h"
14 #include "common/Clock.h"
15 #include "common/DecayCounter.h"
16 #include "common/StackStringStream.h"
17 #include "common/entity_name.h"
19 #include "include/compat.h"
20 #include "include/Context.h"
21 #include "include/frag.h"
22 #include "include/xlist.h"
23 #include "include/interval_set.h"
24 #include "include/compact_set.h"
25 #include "include/fs_types.h"
26 #include "include/ceph_fs.h"
28 #include "inode_backtrace.h"
30 #include <boost/spirit/include/qi.hpp>
31 #include <boost/pool/pool.hpp>
32 #include "include/ceph_assert.h"
33 #include "common/ceph_json.h"
34 #include "include/cephfs/types.h"
36 #define MDS_PORT_CACHE 0x200
37 #define MDS_PORT_LOCKER 0x300
38 #define MDS_PORT_MIGRATOR 0x400
42 // Inode numbers 1,2 and 4 please see CEPH_INO_* in include/ceph_fs.h
44 #define MDS_INO_MDSDIR_OFFSET (1*MAX_MDS)
45 #define MDS_INO_STRAY_OFFSET (6*MAX_MDS)
47 // Locations for journal data
48 #define MDS_INO_LOG_OFFSET (2*MAX_MDS)
49 #define MDS_INO_LOG_BACKUP_OFFSET (3*MAX_MDS)
50 #define MDS_INO_LOG_POINTER_OFFSET (4*MAX_MDS)
51 #define MDS_INO_PURGE_QUEUE (5*MAX_MDS)
53 #define MDS_INO_SYSTEM_BASE ((6*MAX_MDS) + (MAX_MDS * NUM_STRAY))
55 #define MDS_INO_STRAY(x,i) (MDS_INO_STRAY_OFFSET+((((unsigned)(x))*NUM_STRAY)+((unsigned)(i))))
56 #define MDS_INO_MDSDIR(x) (MDS_INO_MDSDIR_OFFSET+((unsigned)x))
58 #define MDS_INO_IS_STRAY(i) ((i) >= MDS_INO_STRAY_OFFSET && (i) < (MDS_INO_STRAY_OFFSET+(MAX_MDS*NUM_STRAY)))
59 #define MDS_INO_IS_MDSDIR(i) ((i) >= MDS_INO_MDSDIR_OFFSET && (i) < (MDS_INO_MDSDIR_OFFSET+MAX_MDS))
60 #define MDS_INO_MDSDIR_OWNER(i) (signed ((unsigned (i)) - MDS_INO_MDSDIR_OFFSET))
61 #define MDS_INO_IS_BASE(i) ((i) == CEPH_INO_ROOT || (i) == CEPH_INO_GLOBAL_SNAPREALM || MDS_INO_IS_MDSDIR(i))
62 #define MDS_INO_STRAY_OWNER(i) (signed (((unsigned (i)) - MDS_INO_STRAY_OFFSET) / NUM_STRAY))
63 #define MDS_INO_STRAY_INDEX(i) (((unsigned (i)) - MDS_INO_STRAY_OFFSET) % NUM_STRAY)
65 #define MDS_IS_PRIVATE_INO(i) ((i) < MDS_INO_SYSTEM_BASE && (i) >= MDS_INO_MDSDIR_OFFSET)
69 mds_role_t(fs_cluster_id_t fscid_
, mds_rank_t rank_
)
70 : fscid(fscid_
), rank(rank_
)
74 bool operator<(mds_role_t
const &rhs
) const {
75 if (fscid
< rhs
.fscid
) {
77 } else if (fscid
== rhs
.fscid
) {
78 return rank
< rhs
.rank
;
84 bool is_none() const {
85 return (rank
== MDS_RANK_NONE
);
88 fs_cluster_id_t fscid
= FS_CLUSTER_ID_NONE
;
89 mds_rank_t rank
= MDS_RANK_NONE
;
91 inline std::ostream
& operator<<(std::ostream
& out
, const mds_role_t
& role
) {
92 return out
<< role
.fscid
<< ":" << role
.rank
;
96 inline std::string
gcap_string(int cap
)
99 if (cap
& CEPH_CAP_GSHARED
) s
+= "s";
100 if (cap
& CEPH_CAP_GEXCL
) s
+= "x";
101 if (cap
& CEPH_CAP_GCACHE
) s
+= "c";
102 if (cap
& CEPH_CAP_GRD
) s
+= "r";
103 if (cap
& CEPH_CAP_GWR
) s
+= "w";
104 if (cap
& CEPH_CAP_GBUFFER
) s
+= "b";
105 if (cap
& CEPH_CAP_GWREXTEND
) s
+= "a";
106 if (cap
& CEPH_CAP_GLAZYIO
) s
+= "l";
109 inline std::string
ccap_string(int cap
)
112 if (cap
& CEPH_CAP_PIN
) s
+= "p";
114 int a
= (cap
>> CEPH_CAP_SAUTH
) & 3;
115 if (a
) s
+= 'A' + gcap_string(a
);
117 a
= (cap
>> CEPH_CAP_SLINK
) & 3;
118 if (a
) s
+= 'L' + gcap_string(a
);
120 a
= (cap
>> CEPH_CAP_SXATTR
) & 3;
121 if (a
) s
+= 'X' + gcap_string(a
);
123 a
= cap
>> CEPH_CAP_SFILE
;
124 if (a
) s
+= 'F' + gcap_string(a
);
132 template<> struct hash
<vinodeno_t
> {
133 size_t operator()(const vinodeno_t
&vino
) const {
136 return H(vino
.ino
) ^ I(vino
.snapid
);
141 inline std::ostream
& operator<<(std::ostream
&out
, const vinodeno_t
&vino
) {
143 if (vino
.snapid
== CEPH_NOSNAP
)
145 else if (vino
.snapid
)
146 out
<< '.' << vino
.snapid
;
150 typedef uint32_t damage_flags_t
;
152 template<template<typename
> class Allocator
>
153 using alloc_string
= std::basic_string
<char,std::char_traits
<char>,Allocator
<char>>;
155 template<template<typename
> class Allocator
>
156 using xattr_map
= std::map
<alloc_string
<Allocator
>,
158 std::less
<alloc_string
<Allocator
>>,
159 Allocator
<std::pair
<const alloc_string
<Allocator
>,
160 ceph::bufferptr
>>>; // FIXME bufferptr not in mempool
162 template<template<typename
> class Allocator
>
163 inline void decode_noshare(xattr_map
<Allocator
>& xattrs
, ceph::buffer::list::const_iterator
&p
)
168 alloc_string
<Allocator
> key
;
172 p
.copy_deep(len
, xattrs
[key
]);
176 template<template<typename
> class Allocator
= std::allocator
>
179 inode_t
<Allocator
> inode
;
180 xattr_map
<Allocator
> xattrs
;
182 void encode(ceph::buffer::list
&bl
, uint64_t features
) const;
183 void decode(ceph::buffer::list::const_iterator
& bl
);
184 void dump(ceph::Formatter
*f
) const;
185 static void generate_test_instances(std::list
<old_inode_t
*>& ls
);
188 // These methods may be moved back to mdstypes.cc when we have pmr
189 template<template<typename
> class Allocator
>
190 void old_inode_t
<Allocator
>::encode(ceph::buffer::list
& bl
, uint64_t features
) const
192 ENCODE_START(2, 2, bl
);
194 encode(inode
, bl
, features
);
199 template<template<typename
> class Allocator
>
200 void old_inode_t
<Allocator
>::decode(ceph::buffer::list::const_iterator
& bl
)
202 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl
);
205 decode_noshare
<Allocator
>(xattrs
, bl
);
209 template<template<typename
> class Allocator
>
210 void old_inode_t
<Allocator
>::dump(ceph::Formatter
*f
) const
212 f
->dump_unsigned("first", first
);
214 f
->open_object_section("xattrs");
215 for (const auto &p
: xattrs
) {
216 std::string
v(p
.second
.c_str(), p
.second
.length());
217 f
->dump_string(p
.first
.c_str(), v
);
222 template<template<typename
> class Allocator
>
223 void old_inode_t
<Allocator
>::generate_test_instances(std::list
<old_inode_t
<Allocator
>*>& ls
)
225 ls
.push_back(new old_inode_t
<Allocator
>);
226 ls
.push_back(new old_inode_t
<Allocator
>);
227 ls
.back()->first
= 2;
228 std::list
<inode_t
<Allocator
>*> ils
;
229 inode_t
<Allocator
>::generate_test_instances(ils
);
230 ls
.back()->inode
= *ils
.back();
231 ls
.back()->xattrs
["user.foo"] = ceph::buffer::copy("asdf", 4);
232 ls
.back()->xattrs
["user.unprintable"] = ceph::buffer::copy("\000\001\002", 3);
235 template<template<typename
> class Allocator
>
236 inline void encode(const old_inode_t
<Allocator
> &c
, ::ceph::buffer::list
&bl
, uint64_t features
)
239 c
.encode(bl
, features
);
240 ENCODE_DUMP_POST(cl
);
242 template<template<typename
> class Allocator
>
243 inline void decode(old_inode_t
<Allocator
> &c
, ::ceph::buffer::list::const_iterator
&p
)
249 * like an inode, but for a dir frag
252 void encode(ceph::buffer::list
&bl
) const;
253 void decode(ceph::buffer::list::const_iterator
& bl
);
254 void dump(ceph::Formatter
*f
) const;
255 void decode_json(JSONObj
*obj
);
256 static void generate_test_instances(std::list
<fnode_t
*>& ls
);
258 version_t version
= 0;
259 snapid_t snap_purged_thru
; // the max_last_destroy snapid we've been purged thru
260 frag_info_t fragstat
, accounted_fragstat
;
261 nest_info_t rstat
, accounted_rstat
;
262 damage_flags_t damage_flags
= 0;
264 // we know we and all our descendants have been scrubbed since this version
265 version_t recursive_scrub_version
= 0;
266 utime_t recursive_scrub_stamp
;
267 // version at which we last scrubbed our personal data structures
268 version_t localized_scrub_version
= 0;
269 utime_t localized_scrub_stamp
;
271 WRITE_CLASS_ENCODER(fnode_t
)
275 void encode(ceph::buffer::list
& bl
) const;
276 void decode(ceph::buffer::list::const_iterator
& p
);
277 void dump(ceph::Formatter
*f
) const;
278 static void generate_test_instances(std::list
<old_rstat_t
*>& ls
);
281 nest_info_t rstat
, accounted_rstat
;
283 WRITE_CLASS_ENCODER(old_rstat_t
)
285 inline std::ostream
& operator<<(std::ostream
& out
, const old_rstat_t
& o
) {
286 return out
<< "old_rstat(first " << o
.first
<< " " << o
.rstat
<< " " << o
.accounted_rstat
<< ")";
289 class feature_bitset_t
{
291 typedef uint64_t block_type
;
292 static const size_t bits_per_block
= sizeof(block_type
) * 8;
294 feature_bitset_t(const feature_bitset_t
& other
) : _vec(other
._vec
) {}
295 feature_bitset_t(feature_bitset_t
&& other
) : _vec(std::move(other
._vec
)) {}
296 feature_bitset_t(unsigned long value
= 0);
297 feature_bitset_t(const std::vector
<size_t>& array
);
298 feature_bitset_t
& operator=(const feature_bitset_t
& other
) {
302 feature_bitset_t
& operator=(feature_bitset_t
&& other
) {
303 _vec
= std::move(other
._vec
);
306 feature_bitset_t
& operator-=(const feature_bitset_t
& other
);
308 //block_type is a uint64_t. If the vector is only composed of 0s, then it's still "empty"
309 for (auto& v
: _vec
) {
315 bool test(size_t bit
) const {
316 if (bit
>= bits_per_block
* _vec
.size())
318 return _vec
[bit
/ bits_per_block
] & ((block_type
)1 << (bit
% bits_per_block
));
320 void insert(size_t bit
) {
321 size_t n
= bit
/ bits_per_block
;
322 if (n
>= _vec
.size())
324 _vec
[n
] |= ((block_type
)1 << (bit
% bits_per_block
));
326 void erase(size_t bit
) {
327 size_t n
= bit
/ bits_per_block
;
328 if (n
>= _vec
.size())
330 _vec
[n
] &= ~((block_type
)1 << (bit
% bits_per_block
));
331 if (n
+ 1 == _vec
.size()) {
332 while (!_vec
.empty() && _vec
.back() == 0)
339 bool operator==(const feature_bitset_t
& other
) const {
340 return _vec
== other
._vec
;
342 bool operator!=(const feature_bitset_t
& other
) const {
343 return _vec
!= other
._vec
;
345 void encode(ceph::buffer::list
& bl
) const;
346 void decode(ceph::buffer::list::const_iterator
&p
);
347 void dump(ceph::Formatter
*f
) const;
348 void print(std::ostream
& out
) const;
350 std::vector
<block_type
> _vec
;
352 WRITE_CLASS_ENCODER(feature_bitset_t
)
354 inline std::ostream
& operator<<(std::ostream
& out
, const feature_bitset_t
& s
) {
359 struct metric_spec_t
{
361 metric_spec_t(const metric_spec_t
& other
) :
362 metric_flags(other
.metric_flags
) {}
363 metric_spec_t(metric_spec_t
&& other
) :
364 metric_flags(std::move(other
.metric_flags
)) {}
365 metric_spec_t(const feature_bitset_t
& mf
) :
367 metric_spec_t(feature_bitset_t
&& mf
) :
368 metric_flags(std::move(mf
)) {}
370 metric_spec_t
& operator=(const metric_spec_t
& other
) {
371 metric_flags
= other
.metric_flags
;
374 metric_spec_t
& operator=(metric_spec_t
&& other
) {
375 metric_flags
= std::move(other
.metric_flags
);
380 return metric_flags
.empty();
384 metric_flags
.clear();
387 void encode(ceph::buffer::list
& bl
) const;
388 void decode(ceph::buffer::list::const_iterator
& p
);
389 void dump(ceph::Formatter
*f
) const;
390 void print(std::ostream
& out
) const;
392 // set of metrics that a client is capable of forwarding
393 feature_bitset_t metric_flags
;
395 WRITE_CLASS_ENCODER(metric_spec_t
)
397 inline std::ostream
& operator<<(std::ostream
& out
, const metric_spec_t
& mst
) {
405 struct client_metadata_t
{
406 using kv_map_t
= std::map
<std::string
,std::string
>;
407 using iterator
= kv_map_t::const_iterator
;
409 client_metadata_t() {}
410 client_metadata_t(const kv_map_t
& kv
, const feature_bitset_t
&f
, const metric_spec_t
&mst
) :
414 client_metadata_t
& operator=(const client_metadata_t
& other
) {
415 kv_map
= other
.kv_map
;
416 features
= other
.features
;
417 metric_spec
= other
.metric_spec
;
421 bool empty() const { return kv_map
.empty() && features
.empty() && metric_spec
.empty(); }
422 iterator
find(const std::string
& key
) const { return kv_map
.find(key
); }
423 iterator
begin() const { return kv_map
.begin(); }
424 iterator
end() const { return kv_map
.end(); }
425 void erase(iterator it
) { kv_map
.erase(it
); }
426 std::string
& operator[](const std::string
& key
) { return kv_map
[key
]; }
427 void merge(const client_metadata_t
& other
) {
428 kv_map
.insert(other
.kv_map
.begin(), other
.kv_map
.end());
429 features
= other
.features
;
430 metric_spec
= other
.metric_spec
;
438 void encode(ceph::buffer::list
& bl
) const;
439 void decode(ceph::buffer::list::const_iterator
& p
);
440 void dump(ceph::Formatter
*f
) const;
443 feature_bitset_t features
;
444 metric_spec_t metric_spec
;
446 WRITE_CLASS_ENCODER(client_metadata_t
)
449 * session_info_t - durable part of a Session
451 struct session_info_t
{
452 client_t
get_client() const { return client_t(inst
.name
.num()); }
453 bool has_feature(size_t bit
) const { return client_metadata
.features
.test(bit
); }
454 const entity_name_t
& get_source() const { return inst
.name
; }
457 prealloc_inos
.clear();
458 completed_requests
.clear();
459 completed_flushes
.clear();
460 client_metadata
.clear();
463 void encode(ceph::buffer::list
& bl
, uint64_t features
) const;
464 void decode(ceph::buffer::list::const_iterator
& p
);
465 void dump(ceph::Formatter
*f
) const;
466 static void generate_test_instances(std::list
<session_info_t
*>& ls
);
469 std::map
<ceph_tid_t
,inodeno_t
> completed_requests
;
470 interval_set
<inodeno_t
> prealloc_inos
; // preallocated, ready to use.
471 client_metadata_t client_metadata
;
472 std::set
<ceph_tid_t
> completed_flushes
;
473 EntityName auth_name
;
475 WRITE_CLASS_ENCODER_FEATURES(session_info_t
)
478 struct dentry_key_t
{
480 dentry_key_t(snapid_t s
, std::string_view n
, __u32 h
=0) :
481 snapid(s
), name(n
), hash(h
) {}
483 bool is_valid() { return name
.length() || snapid
; }
485 // encode into something that can be decoded as a string.
486 // name_ (head) or name_%x (!head)
487 void encode(ceph::buffer::list
& bl
) const {
493 void encode(std::string
& key
) const {
495 if (snapid
!= CEPH_NOSNAP
) {
496 uint64_t val(snapid
);
497 snprintf(b
, sizeof(b
), "%" PRIx64
, val
);
499 snprintf(b
, sizeof(b
), "%s", "head");
501 CachedStackStringStream css
;
502 *css
<< name
<< "_" << b
;
505 static void decode_helper(ceph::buffer::list::const_iterator
& bl
, std::string
& nm
,
510 decode_helper(key
, nm
, sn
);
512 static void decode_helper(std::string_view key
, std::string
& nm
, snapid_t
& sn
) {
513 size_t i
= key
.find_last_of('_');
514 ceph_assert(i
!= std::string::npos
);
515 if (key
.compare(i
+1, std::string_view::npos
, "head") == 0) {
520 long long unsigned x
= 0;
521 std::string
x_str(key
.substr(i
+1));
522 sscanf(x_str
.c_str(), "%llx", &x
);
525 nm
= key
.substr(0, i
);
529 std::string_view name
;
533 inline std::ostream
& operator<<(std::ostream
& out
, const dentry_key_t
&k
)
535 return out
<< "(" << k
.name
<< "," << k
.snapid
<< ")";
538 inline bool operator<(const dentry_key_t
& k1
, const dentry_key_t
& k2
)
541 * order by hash, name, snap
543 int c
= ceph_frag_value(k1
.hash
) - ceph_frag_value(k2
.hash
);
546 c
= k1
.name
.compare(k2
.name
);
549 return k1
.snapid
< k2
.snapid
;
553 * string_snap_t is a simple (string, snapid_t) pair
555 struct string_snap_t
{
557 string_snap_t(std::string_view n
, snapid_t s
) : name(n
), snapid(s
) {}
559 int compare(const string_snap_t
& r
) const {
560 int ret
= name
.compare(r
.name
);
563 if (snapid
== r
.snapid
)
565 return snapid
> r
.snapid
? 1 : -1;
568 void encode(ceph::buffer::list
& bl
) const;
569 void decode(ceph::buffer::list::const_iterator
& p
);
570 void dump(ceph::Formatter
*f
) const;
571 static void generate_test_instances(std::list
<string_snap_t
*>& ls
);
576 WRITE_CLASS_ENCODER(string_snap_t
)
578 inline bool operator==(const string_snap_t
& l
, const string_snap_t
& r
) {
579 return l
.name
== r
.name
&& l
.snapid
== r
.snapid
;
582 inline bool operator<(const string_snap_t
& l
, const string_snap_t
& r
) {
583 int c
= l
.name
.compare(r
.name
);
584 return c
< 0 || (c
== 0 && l
.snapid
< r
.snapid
);
587 inline std::ostream
& operator<<(std::ostream
& out
, const string_snap_t
&k
)
589 return out
<< "(" << k
.name
<< "," << k
.snapid
<< ")";
593 * mds_table_pending_t
595 * For mds's requesting any pending ops, child needs to encode the corresponding
596 * pending mutation state in the table.
598 struct mds_table_pending_t
{
599 void encode(ceph::buffer::list
& bl
) const;
600 void decode(ceph::buffer::list::const_iterator
& bl
);
601 void dump(ceph::Formatter
*f
) const;
602 static void generate_test_instances(std::list
<mds_table_pending_t
*>& ls
);
608 WRITE_CLASS_ENCODER(mds_table_pending_t
)
613 metareqid_t(entity_name_t n
, ceph_tid_t t
) : name(n
), tid(t
) {}
614 void encode(ceph::buffer::list
& bl
) const {
619 void decode(ceph::buffer::list::const_iterator
&p
) {
624 void dump(ceph::Formatter
*f
) const;
629 WRITE_CLASS_ENCODER(metareqid_t
)
631 inline std::ostream
& operator<<(std::ostream
& out
, const metareqid_t
& r
) {
632 return out
<< r
.name
<< ":" << r
.tid
;
635 inline bool operator==(const metareqid_t
& l
, const metareqid_t
& r
) {
636 return (l
.name
== r
.name
) && (l
.tid
== r
.tid
);
638 inline bool operator!=(const metareqid_t
& l
, const metareqid_t
& r
) {
639 return (l
.name
!= r
.name
) || (l
.tid
!= r
.tid
);
641 inline bool operator<(const metareqid_t
& l
, const metareqid_t
& r
) {
642 return (l
.name
< r
.name
) ||
643 (l
.name
== r
.name
&& l
.tid
< r
.tid
);
645 inline bool operator<=(const metareqid_t
& l
, const metareqid_t
& r
) {
646 return (l
.name
< r
.name
) ||
647 (l
.name
== r
.name
&& l
.tid
<= r
.tid
);
649 inline bool operator>(const metareqid_t
& l
, const metareqid_t
& r
) { return !(l
<= r
); }
650 inline bool operator>=(const metareqid_t
& l
, const metareqid_t
& r
) { return !(l
< r
); }
653 template<> struct hash
<metareqid_t
> {
654 size_t operator()(const metareqid_t
&r
) const {
656 return H(r
.name
.num()) ^ H(r
.name
.type()) ^ H(r
.tid
);
661 // cap info for client reconnect
662 struct cap_reconnect_t
{
664 cap_reconnect_t(uint64_t cap_id
, inodeno_t pino
, std::string_view p
, int w
, int i
,
665 inodeno_t sr
, snapid_t sf
, ceph::buffer::list
& lb
) :
667 capinfo
.cap_id
= cap_id
;
670 capinfo
.snaprealm
= sr
;
671 capinfo
.pathbase
= pino
;
672 capinfo
.flock_len
= 0;
674 flockbl
= std::move(lb
);
676 void encode(ceph::buffer::list
& bl
) const;
677 void decode(ceph::buffer::list::const_iterator
& bl
);
678 void encode_old(ceph::buffer::list
& bl
) const;
679 void decode_old(ceph::buffer::list::const_iterator
& bl
);
681 void dump(ceph::Formatter
*f
) const;
682 static void generate_test_instances(std::list
<cap_reconnect_t
*>& ls
);
685 mutable ceph_mds_cap_reconnect capinfo
= {};
686 snapid_t snap_follows
= 0;
687 ceph::buffer::list flockbl
;
689 WRITE_CLASS_ENCODER(cap_reconnect_t
)
691 struct snaprealm_reconnect_t
{
692 snaprealm_reconnect_t() {}
693 snaprealm_reconnect_t(inodeno_t ino
, snapid_t seq
, inodeno_t parent
) {
696 realm
.parent
= parent
;
698 void encode(ceph::buffer::list
& bl
) const;
699 void decode(ceph::buffer::list::const_iterator
& bl
);
700 void encode_old(ceph::buffer::list
& bl
) const;
701 void decode_old(ceph::buffer::list::const_iterator
& bl
);
703 void dump(ceph::Formatter
*f
) const;
704 static void generate_test_instances(std::list
<snaprealm_reconnect_t
*>& ls
);
706 mutable ceph_mds_snaprealm_reconnect realm
= {};
708 WRITE_CLASS_ENCODER(snaprealm_reconnect_t
)
710 // compat for pre-FLOCK feature
711 struct old_ceph_mds_cap_reconnect
{
716 struct ceph_timespec old_mtime
, old_atime
;
718 ceph_le64 pathbase
; /* base ino for our path to this ino */
719 } __attribute__ ((packed
));
720 WRITE_RAW_ENCODER(old_ceph_mds_cap_reconnect
)
722 struct old_cap_reconnect_t
{
723 const old_cap_reconnect_t
& operator=(const cap_reconnect_t
& n
) {
725 capinfo
.cap_id
= n
.capinfo
.cap_id
;
726 capinfo
.wanted
= n
.capinfo
.wanted
;
727 capinfo
.issued
= n
.capinfo
.issued
;
728 capinfo
.snaprealm
= n
.capinfo
.snaprealm
;
729 capinfo
.pathbase
= n
.capinfo
.pathbase
;
732 operator cap_reconnect_t() {
735 n
.capinfo
.cap_id
= capinfo
.cap_id
;
736 n
.capinfo
.wanted
= capinfo
.wanted
;
737 n
.capinfo
.issued
= capinfo
.issued
;
738 n
.capinfo
.snaprealm
= capinfo
.snaprealm
;
739 n
.capinfo
.pathbase
= capinfo
.pathbase
;
743 void encode(ceph::buffer::list
& bl
) const {
748 void decode(ceph::buffer::list::const_iterator
& bl
) {
755 old_ceph_mds_cap_reconnect capinfo
;
757 WRITE_CLASS_ENCODER(old_cap_reconnect_t
)
762 dirfrag_t(inodeno_t i
, frag_t f
) : ino(i
), frag(f
) { }
764 void encode(ceph::buffer::list
& bl
) const {
769 void decode(ceph::buffer::list::const_iterator
& bl
) {
778 WRITE_CLASS_ENCODER(dirfrag_t
)
780 inline std::ostream
& operator<<(std::ostream
& out
, const dirfrag_t
&df
) {
782 if (!df
.frag
.is_root()) out
<< "." << df
.frag
;
785 inline bool operator<(dirfrag_t l
, dirfrag_t r
) {
786 if (l
.ino
< r
.ino
) return true;
787 if (l
.ino
== r
.ino
&& l
.frag
< r
.frag
) return true;
790 inline bool operator==(dirfrag_t l
, dirfrag_t r
) {
791 return l
.ino
== r
.ino
&& l
.frag
== r
.frag
;
795 template<> struct hash
<dirfrag_t
> {
796 size_t operator()(const dirfrag_t
&df
) const {
797 static rjhash
<uint64_t> H
;
798 static rjhash
<uint32_t> I
;
799 return H(df
.ino
) ^ I(df
.frag
);
804 // ================================================================
805 #define META_POP_IRD 0
806 #define META_POP_IWR 1
807 #define META_POP_READDIR 2
808 #define META_POP_FETCH 3
809 #define META_POP_STORE 4
812 class inode_load_vec_t
{
814 using time
= DecayCounter::time
;
815 using clock
= DecayCounter::clock
;
816 static const size_t NUM
= 2;
818 inode_load_vec_t() : vec
{DecayCounter(DecayRate()), DecayCounter(DecayRate())} {}
819 inode_load_vec_t(const DecayRate
&rate
) : vec
{DecayCounter(rate
), DecayCounter(rate
)} {}
821 DecayCounter
&get(int t
) {
825 for (auto &d
: vec
) {
829 void encode(ceph::buffer::list
&bl
) const;
830 void decode(ceph::buffer::list::const_iterator
& p
);
831 void dump(ceph::Formatter
*f
) const;
832 static void generate_test_instances(std::list
<inode_load_vec_t
*>& ls
);
835 std::array
<DecayCounter
, NUM
> vec
;
837 inline void encode(const inode_load_vec_t
&c
, ceph::buffer::list
&bl
) {
840 inline void decode(inode_load_vec_t
& c
, ceph::buffer::list::const_iterator
&p
) {
844 class dirfrag_load_vec_t
{
846 using time
= DecayCounter::time
;
847 using clock
= DecayCounter::clock
;
848 static const size_t NUM
= 5;
850 dirfrag_load_vec_t() :
851 vec
{DecayCounter(DecayRate()),
852 DecayCounter(DecayRate()),
853 DecayCounter(DecayRate()),
854 DecayCounter(DecayRate()),
855 DecayCounter(DecayRate())
858 dirfrag_load_vec_t(const DecayRate
&rate
) :
859 vec
{DecayCounter(rate
), DecayCounter(rate
), DecayCounter(rate
), DecayCounter(rate
), DecayCounter(rate
)}
862 void encode(ceph::buffer::list
&bl
) const {
863 ENCODE_START(2, 2, bl
);
864 for (const auto &i
: vec
) {
869 void decode(ceph::buffer::list::const_iterator
&p
) {
870 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, p
);
871 for (auto &i
: vec
) {
876 void dump(ceph::Formatter
*f
) const;
877 void dump(ceph::Formatter
*f
, const DecayRate
& rate
) const;
878 static void generate_test_instances(std::list
<dirfrag_load_vec_t
*>& ls
);
880 const DecayCounter
&get(int t
) const {
883 DecayCounter
&get(int t
) {
886 void adjust(double d
) {
887 for (auto &i
: vec
) {
892 for (auto &i
: vec
) {
896 double meta_load() const {
898 1*vec
[META_POP_IRD
].get() +
899 2*vec
[META_POP_IWR
].get() +
900 1*vec
[META_POP_READDIR
].get() +
901 2*vec
[META_POP_FETCH
].get() +
902 4*vec
[META_POP_STORE
].get();
905 void add(dirfrag_load_vec_t
& r
) {
906 for (size_t i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
907 vec
[i
].adjust(r
.vec
[i
].get());
909 void sub(dirfrag_load_vec_t
& r
) {
910 for (size_t i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
911 vec
[i
].adjust(-r
.vec
[i
].get());
913 void scale(double f
) {
914 for (size_t i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
919 friend inline std::ostream
& operator<<(std::ostream
& out
, const dirfrag_load_vec_t
& dl
);
920 std::array
<DecayCounter
, NUM
> vec
;
923 inline void encode(const dirfrag_load_vec_t
&c
, ceph::buffer::list
&bl
) {
926 inline void decode(dirfrag_load_vec_t
& c
, ceph::buffer::list::const_iterator
&p
) {
930 inline std::ostream
& operator<<(std::ostream
& out
, const dirfrag_load_vec_t
& dl
)
932 CachedStackStringStream css
;
933 *css
<< std::setprecision(1) << std::fixed
936 << " IWR:" << dl
.vec
[1]
937 << " RDR:" << dl
.vec
[2]
938 << " FET:" << dl
.vec
[3]
939 << " STR:" << dl
.vec
[4]
940 << " *LOAD:" << dl
.meta_load() << "]";
941 return out
<< css
->strv();
945 using clock
= dirfrag_load_vec_t::clock
;
946 using time
= dirfrag_load_vec_t::time
;
948 dirfrag_load_vec_t auth
;
949 dirfrag_load_vec_t all
;
951 mds_load_t() : auth(DecayRate()), all(DecayRate()) {}
952 mds_load_t(const DecayRate
&rate
) : auth(rate
), all(rate
) {}
954 double req_rate
= 0.0;
955 double cache_hit_rate
= 0.0;
956 double queue_len
= 0.0;
958 double cpu_load_avg
= 0.0;
960 double mds_load() const; // defiend in MDBalancer.cc
961 void encode(ceph::buffer::list
& bl
) const;
962 void decode(ceph::buffer::list::const_iterator
& bl
);
963 void dump(ceph::Formatter
*f
) const;
964 static void generate_test_instances(std::list
<mds_load_t
*>& ls
);
966 inline void encode(const mds_load_t
&c
, ceph::buffer::list
&bl
) {
969 inline void decode(mds_load_t
&c
, ceph::buffer::list::const_iterator
&p
) {
973 inline std::ostream
& operator<<(std::ostream
& out
, const mds_load_t
& load
)
975 return out
<< "mdsload<" << load
.auth
<< "/" << load
.all
976 << ", req " << load
.req_rate
977 << ", hr " << load
.cache_hit_rate
978 << ", qlen " << load
.queue_len
979 << ", cpu " << load
.cpu_load_avg
983 // ================================================================
984 typedef std::pair
<mds_rank_t
, mds_rank_t
> mds_authority_t
;
986 // -- authority delegation --
987 // directory authority types
988 // >= 0 is the auth mds
989 #define CDIR_AUTH_PARENT mds_rank_t(-1) // default
990 #define CDIR_AUTH_UNKNOWN mds_rank_t(-2)
991 #define CDIR_AUTH_DEFAULT mds_authority_t(CDIR_AUTH_PARENT, CDIR_AUTH_UNKNOWN)
992 #define CDIR_AUTH_UNDEF mds_authority_t(CDIR_AUTH_UNKNOWN, CDIR_AUTH_UNKNOWN)
993 //#define CDIR_AUTH_ROOTINODE pair<int,int>( 0, -2)
995 class MDSCacheObjectInfo
{
997 void encode(ceph::buffer::list
& bl
) const;
998 void decode(ceph::buffer::list::const_iterator
& bl
);
999 void dump(ceph::Formatter
*f
) const;
1000 static void generate_test_instances(std::list
<MDSCacheObjectInfo
*>& ls
);
1008 inline std::ostream
& operator<<(std::ostream
& out
, const MDSCacheObjectInfo
&info
) {
1009 if (info
.ino
) return out
<< info
.ino
<< "." << info
.snapid
;
1010 if (info
.dname
.length()) return out
<< info
.dirfrag
<< "/" << info
.dname
1011 << " snap " << info
.snapid
;
1012 return out
<< info
.dirfrag
;
1015 inline bool operator==(const MDSCacheObjectInfo
& l
, const MDSCacheObjectInfo
& r
) {
1017 return l
.ino
== r
.ino
&& l
.snapid
== r
.snapid
;
1019 return l
.dirfrag
== r
.dirfrag
&& l
.dname
== r
.dname
;
1021 WRITE_CLASS_ENCODER(MDSCacheObjectInfo
)