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"
12 #include <boost/utility/string_view.hpp>
14 #include "common/config.h"
15 #include "common/Clock.h"
16 #include "common/DecayCounter.h"
17 #include "common/entity_name.h"
19 #include "include/Context.h"
20 #include "include/frag.h"
21 #include "include/xlist.h"
22 #include "include/interval_set.h"
23 #include "include/compact_map.h"
24 #include "include/compact_set.h"
25 #include "include/fs_types.h"
27 #include "inode_backtrace.h"
29 #include <boost/spirit/include/qi.hpp>
30 #include <boost/pool/pool.hpp>
31 #include "include/assert.h"
32 #include <boost/serialization/strong_typedef.hpp>
34 #define CEPH_FS_ONDISK_MAGIC "ceph fs volume v011"
36 #define MDS_PORT_CACHE 0x200
37 #define MDS_PORT_LOCKER 0x300
38 #define MDS_PORT_MIGRATOR 0x400
43 #define MDS_INO_ROOT 1
45 // No longer created but recognised in existing filesystems
46 // so that we don't try to fragment it.
47 #define MDS_INO_CEPH 2
49 #define MDS_INO_MDSDIR_OFFSET (1*MAX_MDS)
50 #define MDS_INO_STRAY_OFFSET (6*MAX_MDS)
52 // Locations for journal data
53 #define MDS_INO_LOG_OFFSET (2*MAX_MDS)
54 #define MDS_INO_LOG_BACKUP_OFFSET (3*MAX_MDS)
55 #define MDS_INO_LOG_POINTER_OFFSET (4*MAX_MDS)
56 #define MDS_INO_PURGE_QUEUE (5*MAX_MDS)
58 #define MDS_INO_SYSTEM_BASE ((6*MAX_MDS) + (MAX_MDS * NUM_STRAY))
60 #define MDS_INO_STRAY(x,i) (MDS_INO_STRAY_OFFSET+((((unsigned)(x))*NUM_STRAY)+((unsigned)(i))))
61 #define MDS_INO_MDSDIR(x) (MDS_INO_MDSDIR_OFFSET+((unsigned)x))
63 #define MDS_INO_IS_STRAY(i) ((i) >= MDS_INO_STRAY_OFFSET && (i) < (MDS_INO_STRAY_OFFSET+(MAX_MDS*NUM_STRAY)))
64 #define MDS_INO_IS_MDSDIR(i) ((i) >= MDS_INO_MDSDIR_OFFSET && (i) < (MDS_INO_MDSDIR_OFFSET+MAX_MDS))
65 #define MDS_INO_MDSDIR_OWNER(i) (signed ((unsigned (i)) - MDS_INO_MDSDIR_OFFSET))
66 #define MDS_INO_IS_BASE(i) (MDS_INO_ROOT == (i) || MDS_INO_IS_MDSDIR(i))
67 #define MDS_INO_STRAY_OWNER(i) (signed (((unsigned (i)) - MDS_INO_STRAY_OFFSET) / NUM_STRAY))
68 #define MDS_INO_STRAY_INDEX(i) (((unsigned (i)) - MDS_INO_STRAY_OFFSET) % NUM_STRAY)
70 #define MDS_TRAVERSE_FORWARD 1
71 #define MDS_TRAVERSE_DISCOVER 2 // skips permissions checks etc.
72 #define MDS_TRAVERSE_DISCOVERXLOCK 3 // succeeds on (foreign?) null, xlocked dentries.
75 typedef int32_t mds_rank_t
;
76 typedef int32_t fs_cluster_id_t
;
78 BOOST_STRONG_TYPEDEF(uint64_t, mds_gid_t
)
79 extern const mds_gid_t MDS_GID_NONE
;
80 constexpr fs_cluster_id_t FS_CLUSTER_ID_NONE
= {-1};
81 // The namespace ID of the anonymous default filesystem from legacy systems
82 constexpr fs_cluster_id_t FS_CLUSTER_ID_ANONYMOUS
= {0};
83 extern const mds_rank_t MDS_RANK_NONE
;
88 fs_cluster_id_t fscid
;
91 mds_role_t(fs_cluster_id_t fscid_
, mds_rank_t rank_
)
92 : fscid(fscid_
), rank(rank_
)
95 : fscid(FS_CLUSTER_ID_NONE
), rank(MDS_RANK_NONE
)
97 bool operator<(mds_role_t
const &rhs
) const
99 if (fscid
< rhs
.fscid
) {
101 } else if (fscid
== rhs
.fscid
) {
102 return rank
< rhs
.rank
;
110 return (rank
== MDS_RANK_NONE
);
113 std::ostream
& operator<<(std::ostream
&out
, const mds_role_t
&role
);
118 inline string
gcap_string(int cap
)
121 if (cap
& CEPH_CAP_GSHARED
) s
+= "s";
122 if (cap
& CEPH_CAP_GEXCL
) s
+= "x";
123 if (cap
& CEPH_CAP_GCACHE
) s
+= "c";
124 if (cap
& CEPH_CAP_GRD
) s
+= "r";
125 if (cap
& CEPH_CAP_GWR
) s
+= "w";
126 if (cap
& CEPH_CAP_GBUFFER
) s
+= "b";
127 if (cap
& CEPH_CAP_GWREXTEND
) s
+= "a";
128 if (cap
& CEPH_CAP_GLAZYIO
) s
+= "l";
131 inline string
ccap_string(int cap
)
134 if (cap
& CEPH_CAP_PIN
) s
+= "p";
136 int a
= (cap
>> CEPH_CAP_SAUTH
) & 3;
137 if (a
) s
+= 'A' + gcap_string(a
);
139 a
= (cap
>> CEPH_CAP_SLINK
) & 3;
140 if (a
) s
+= 'L' + gcap_string(a
);
142 a
= (cap
>> CEPH_CAP_SXATTR
) & 3;
143 if (a
) s
+= 'X' + gcap_string(a
);
145 a
= cap
>> CEPH_CAP_SFILE
;
146 if (a
) s
+= 'F' + gcap_string(a
);
154 struct scatter_info_t
{
155 version_t version
= 0;
160 struct frag_info_t
: public scatter_info_t
{
163 uint64_t change_attr
= 0;
164 int64_t nfiles
= 0; // files
165 int64_t nsubdirs
= 0; // subdirs
169 int64_t size() const { return nfiles
+ nsubdirs
; }
172 *this = frag_info_t();
175 // *this += cur - acc;
176 void add_delta(const frag_info_t
&cur
, const frag_info_t
&acc
, bool *touched_mtime
=0, bool *touched_chattr
=0) {
177 if (cur
.mtime
> mtime
) {
180 *touched_mtime
= true;
182 if (cur
.change_attr
> change_attr
) {
183 change_attr
= cur
.change_attr
;
185 *touched_chattr
= true;
187 nfiles
+= cur
.nfiles
- acc
.nfiles
;
188 nsubdirs
+= cur
.nsubdirs
- acc
.nsubdirs
;
191 void add(const frag_info_t
& other
) {
192 if (other
.mtime
> mtime
)
194 if (other
.change_attr
> change_attr
)
195 change_attr
= other
.change_attr
;
196 nfiles
+= other
.nfiles
;
197 nsubdirs
+= other
.nsubdirs
;
200 bool same_sums(const frag_info_t
&o
) const {
201 return mtime
<= o
.mtime
&&
202 nfiles
== o
.nfiles
&&
203 nsubdirs
== o
.nsubdirs
;
206 void encode(bufferlist
&bl
) const;
207 void decode(bufferlist::iterator
& bl
);
208 void dump(Formatter
*f
) const;
209 static void generate_test_instances(list
<frag_info_t
*>& ls
);
211 WRITE_CLASS_ENCODER(frag_info_t
)
213 inline bool operator==(const frag_info_t
&l
, const frag_info_t
&r
) {
214 return memcmp(&l
, &r
, sizeof(l
)) == 0;
216 inline bool operator!=(const frag_info_t
&l
, const frag_info_t
&r
) {
220 std::ostream
& operator<<(std::ostream
&out
, const frag_info_t
&f
);
223 struct nest_info_t
: public scatter_info_t
{
224 // this frag + children
228 int64_t rsubdirs
= 0;
229 int64_t rsize() const { return rfiles
+ rsubdirs
; }
231 int64_t rsnaprealms
= 0;
236 *this = nest_info_t();
239 void sub(const nest_info_t
&other
) {
242 void add(const nest_info_t
&other
, int fac
=1) {
243 if (other
.rctime
> rctime
)
244 rctime
= other
.rctime
;
245 rbytes
+= fac
*other
.rbytes
;
246 rfiles
+= fac
*other
.rfiles
;
247 rsubdirs
+= fac
*other
.rsubdirs
;
248 rsnaprealms
+= fac
*other
.rsnaprealms
;
251 // *this += cur - acc;
252 void add_delta(const nest_info_t
&cur
, const nest_info_t
&acc
) {
253 if (cur
.rctime
> rctime
)
255 rbytes
+= cur
.rbytes
- acc
.rbytes
;
256 rfiles
+= cur
.rfiles
- acc
.rfiles
;
257 rsubdirs
+= cur
.rsubdirs
- acc
.rsubdirs
;
258 rsnaprealms
+= cur
.rsnaprealms
- acc
.rsnaprealms
;
261 bool same_sums(const nest_info_t
&o
) const {
262 return rctime
<= o
.rctime
&&
263 rbytes
== o
.rbytes
&&
264 rfiles
== o
.rfiles
&&
265 rsubdirs
== o
.rsubdirs
&&
266 rsnaprealms
== o
.rsnaprealms
;
269 void encode(bufferlist
&bl
) const;
270 void decode(bufferlist::iterator
& bl
);
271 void dump(Formatter
*f
) const;
272 static void generate_test_instances(list
<nest_info_t
*>& ls
);
274 WRITE_CLASS_ENCODER(nest_info_t
)
276 inline bool operator==(const nest_info_t
&l
, const nest_info_t
&r
) {
277 return memcmp(&l
, &r
, sizeof(l
)) == 0;
279 inline bool operator!=(const nest_info_t
&l
, const nest_info_t
&r
) {
283 std::ostream
& operator<<(std::ostream
&out
, const nest_info_t
&n
);
290 vinodeno_t(inodeno_t i
, snapid_t s
) : ino(i
), snapid(s
) {}
292 void encode(bufferlist
& bl
) const {
294 ::encode(snapid
, bl
);
296 void decode(bufferlist::iterator
& p
) {
301 WRITE_CLASS_ENCODER(vinodeno_t
)
303 inline bool operator==(const vinodeno_t
&l
, const vinodeno_t
&r
) {
304 return l
.ino
== r
.ino
&& l
.snapid
== r
.snapid
;
306 inline bool operator!=(const vinodeno_t
&l
, const vinodeno_t
&r
) {
309 inline bool operator<(const vinodeno_t
&l
, const vinodeno_t
&r
) {
312 (l
.ino
== r
.ino
&& l
.snapid
< r
.snapid
);
317 int64_t max_bytes
= 0;
318 int64_t max_files
= 0;
322 void encode(bufferlist
& bl
) const {
323 ENCODE_START(1, 1, bl
);
324 ::encode(max_bytes
, bl
);
325 ::encode(max_files
, bl
);
328 void decode(bufferlist::iterator
& p
) {
329 DECODE_START_LEGACY_COMPAT_LEN(1, 1, 1, p
);
330 ::decode(max_bytes
, p
);
331 ::decode(max_files
, p
);
335 void dump(Formatter
*f
) const;
336 static void generate_test_instances(list
<quota_info_t
*>& ls
);
338 bool is_valid() const {
339 return max_bytes
>=0 && max_files
>=0;
341 bool is_enable() const {
342 return max_bytes
|| max_files
;
345 WRITE_CLASS_ENCODER(quota_info_t
)
347 inline bool operator==(const quota_info_t
&l
, const quota_info_t
&r
) {
348 return memcmp(&l
, &r
, sizeof(l
)) == 0;
351 ostream
& operator<<(ostream
&out
, const quota_info_t
&n
);
354 template<> struct hash
<vinodeno_t
> {
355 size_t operator()(const vinodeno_t
&vino
) const {
358 return H(vino
.ino
) ^ I(vino
.snapid
);
366 inline std::ostream
& operator<<(std::ostream
&out
, const vinodeno_t
&vino
) {
368 if (vino
.snapid
== CEPH_NOSNAP
)
370 else if (vino
.snapid
)
371 out
<< '.' << vino
.snapid
;
377 * client_writeable_range_t
379 struct client_writeable_range_t
{
380 struct byte_range_t
{
381 uint64_t first
= 0, last
= 0; // interval client can write to
386 snapid_t follows
= 0; // aka "data+metadata flushed thru"
388 client_writeable_range_t() {}
390 void encode(bufferlist
&bl
) const;
391 void decode(bufferlist::iterator
& bl
);
392 void dump(Formatter
*f
) const;
393 static void generate_test_instances(std::list
<client_writeable_range_t
*>& ls
);
396 inline void decode(client_writeable_range_t::byte_range_t
& range
, bufferlist::iterator
& bl
) {
397 ::decode(range
.first
, bl
);
398 ::decode(range
.last
, bl
);
401 WRITE_CLASS_ENCODER(client_writeable_range_t
)
403 std::ostream
& operator<<(std::ostream
& out
, const client_writeable_range_t
& r
);
405 inline bool operator==(const client_writeable_range_t
& l
,
406 const client_writeable_range_t
& r
) {
407 return l
.range
.first
== r
.range
.first
&& l
.range
.last
== r
.range
.last
&&
408 l
.follows
== r
.follows
;
411 struct inline_data_t
{
413 std::unique_ptr
<bufferlist
> blp
;
415 version_t version
= 1;
420 bufferlist
& get_data() {
422 blp
.reset(new bufferlist
);
425 size_t length() const { return blp
? blp
->length() : 0; }
428 inline_data_t(const inline_data_t
& o
) : version(o
.version
) {
432 inline_data_t
& operator=(const inline_data_t
& o
) {
440 bool operator==(const inline_data_t
& o
) const {
441 return length() == o
.length() &&
443 (*const_cast<bufferlist
*>(blp
.get()) == *const_cast<bufferlist
*>(o
.blp
.get())));
445 bool operator!=(const inline_data_t
& o
) const {
446 return !(*this == o
);
448 void encode(bufferlist
&bl
) const;
449 void decode(bufferlist::iterator
& bl
);
451 WRITE_CLASS_ENCODER(inline_data_t
)
454 DAMAGE_STATS
, // statistics (dirstat, size, etc)
455 DAMAGE_RSTATS
, // recursive statistics (rstat, accounted_rstat)
456 DAMAGE_FRAGTREE
// fragtree -- repair by searching
458 typedef uint32_t damage_flags_t
;
463 template<template<typename
> class Allocator
= std::allocator
>
467 * Do not forget to add any new fields to the compare() function.
472 uint32_t rdev
= 0; // if special file
474 // affected by any inode change...
475 utime_t ctime
; // inode change time
476 utime_t btime
; // birth time
478 // perm (namespace permissions)
486 // file (data access)
487 ceph_dir_layout dir_layout
; // [dir only]
488 file_layout_t layout
;
489 compact_set
<int64_t, std::less
<int64_t>, Allocator
<int64_t>> old_pools
;
490 uint64_t size
= 0; // on directory, # dentries
491 uint64_t max_size_ever
= 0; // max size the file has ever been
492 uint32_t truncate_seq
= 0;
493 uint64_t truncate_size
= 0, truncate_from
= 0;
494 uint32_t truncate_pending
= 0;
495 utime_t mtime
; // file data modify time.
496 utime_t atime
; // file data access time.
497 uint32_t time_warp_seq
= 0; // count of (potential) mtime/atime timewarps (i.e., utimes())
498 inline_data_t inline_data
; // FIXME check
501 uint64_t change_attr
= 0;
503 using client_range_map
= std::map
<client_t
,client_writeable_range_t
,std::less
<client_t
>,Allocator
<std::pair
<const client_t
,client_writeable_range_t
>>>;
504 client_range_map client_ranges
; // client(s) can write to these ranges
506 // dirfrag, recursive accountin
507 frag_info_t dirstat
; // protected by my filelock
508 nest_info_t rstat
; // protected by my nestlock
509 nest_info_t accounted_rstat
; // protected by parent's nestlock
513 mds_rank_t export_pin
= MDS_RANK_NONE
;
516 version_t version
= 0; // auth only
517 version_t file_data_version
= 0; // auth only
518 version_t xattr_version
= 0;
520 utime_t last_scrub_stamp
; // start time of last complete scrub
521 version_t last_scrub_version
= 0;// (parent) start version of last complete scrub
523 version_t backtrace_version
= 0;
525 snapid_t oldest_snap
;
527 std::basic_string
<char,std::char_traits
<char>,Allocator
<char>> stray_prior_path
; //stores path before unlink
532 memset(&dir_layout
, 0, sizeof(dir_layout
));
533 memset("a
, 0, sizeof(quota
));
537 bool is_symlink() const { return (mode
& S_IFMT
) == S_IFLNK
; }
538 bool is_dir() const { return (mode
& S_IFMT
) == S_IFDIR
; }
539 bool is_file() const { return (mode
& S_IFMT
) == S_IFREG
; }
541 bool is_truncating() const { return (truncate_pending
> 0); }
542 void truncate(uint64_t old_size
, uint64_t new_size
) {
543 assert(new_size
< old_size
);
544 if (old_size
> max_size_ever
)
545 max_size_ever
= old_size
;
546 truncate_from
= old_size
;
548 rstat
.rbytes
= new_size
;
549 truncate_size
= size
;
554 bool has_layout() const {
555 return layout
!= file_layout_t();
558 void clear_layout() {
559 layout
= file_layout_t();
562 uint64_t get_layout_size_increment() const {
563 return layout
.get_period();
566 bool is_dirty_rstat() const { return !(rstat
== accounted_rstat
); }
568 uint64_t get_max_size() const {
570 for (std::map
<client_t
,client_writeable_range_t
>::const_iterator p
= client_ranges
.begin();
571 p
!= client_ranges
.end();
573 if (p
->second
.range
.last
> max
)
574 max
= p
->second
.range
.last
;
577 void set_max_size(uint64_t new_max
) {
579 client_ranges
.clear();
581 for (std::map
<client_t
,client_writeable_range_t
>::iterator p
= client_ranges
.begin();
582 p
!= client_ranges
.end();
584 p
->second
.range
.last
= new_max
;
588 void trim_client_ranges(snapid_t last
) {
589 std::map
<client_t
, client_writeable_range_t
>::iterator p
= client_ranges
.begin();
590 while (p
!= client_ranges
.end()) {
591 if (p
->second
.follows
>= last
)
592 client_ranges
.erase(p
++);
598 bool is_backtrace_updated() const {
599 return backtrace_version
== version
;
601 void update_backtrace(version_t pv
=0) {
602 backtrace_version
= pv
? pv
: version
;
605 void add_old_pool(int64_t l
) {
606 backtrace_version
= version
;
610 void encode(bufferlist
&bl
, uint64_t features
) const;
611 void decode(bufferlist::iterator
& bl
);
612 void dump(Formatter
*f
) const;
613 static void generate_test_instances(std::list
<inode_t
*>& ls
);
615 * Compare this inode_t with another that represent *the same inode*
616 * at different points in time.
617 * @pre The inodes are the same ino
619 * @param other The inode_t to compare ourselves with
620 * @param divergent A bool pointer which will be set to true
621 * if the values are different in a way that can't be explained
622 * by one being a newer version than the other.
624 * @returns 1 if we are newer than the other, 0 if equal, -1 if older.
626 int compare(const inode_t
&other
, bool *divergent
) const;
628 bool older_is_consistent(const inode_t
&other
) const;
631 // These methods may be moved back to mdstypes.cc when we have pmr
632 template<template<typename
> class Allocator
>
633 void inode_t
<Allocator
>::encode(bufferlist
&bl
, uint64_t features
) const
635 ENCODE_START(15, 6, bl
);
649 ::encode(anchored
, bl
);
652 ::encode(dir_layout
, bl
);
653 ::encode(layout
, bl
, features
);
655 ::encode(truncate_seq
, bl
);
656 ::encode(truncate_size
, bl
);
657 ::encode(truncate_from
, bl
);
658 ::encode(truncate_pending
, bl
);
661 ::encode(time_warp_seq
, bl
);
662 ::encode(client_ranges
, bl
);
664 ::encode(dirstat
, bl
);
666 ::encode(accounted_rstat
, bl
);
668 ::encode(version
, bl
);
669 ::encode(file_data_version
, bl
);
670 ::encode(xattr_version
, bl
);
671 ::encode(backtrace_version
, bl
);
672 ::encode(old_pools
, bl
);
673 ::encode(max_size_ever
, bl
);
674 ::encode(inline_data
, bl
);
677 ::encode(stray_prior_path
, bl
);
679 ::encode(last_scrub_version
, bl
);
680 ::encode(last_scrub_stamp
, bl
);
683 ::encode(change_attr
, bl
);
685 ::encode(export_pin
, bl
);
690 template<template<typename
> class Allocator
>
691 void inode_t
<Allocator
>::decode(bufferlist::iterator
&p
)
693 DECODE_START_LEGACY_COMPAT_LEN(15, 6, 6, p
);
706 ::decode(anchored
, p
);
710 ::decode(dir_layout
, p
);
712 memset(&dir_layout
, 0, sizeof(dir_layout
));
715 ::decode(truncate_seq
, p
);
716 ::decode(truncate_size
, p
);
717 ::decode(truncate_from
, p
);
719 ::decode(truncate_pending
, p
);
721 truncate_pending
= 0;
724 ::decode(time_warp_seq
, p
);
726 ::decode(client_ranges
, p
);
728 map
<client_t
, client_writeable_range_t::byte_range_t
> m
;
730 for (map
<client_t
, client_writeable_range_t::byte_range_t
>::iterator
731 q
= m
.begin(); q
!= m
.end(); ++q
)
732 client_ranges
[q
->first
].range
= q
->second
;
735 ::decode(dirstat
, p
);
737 ::decode(accounted_rstat
, p
);
739 ::decode(version
, p
);
740 ::decode(file_data_version
, p
);
741 ::decode(xattr_version
, p
);
743 ::decode(backtrace_version
, p
);
745 ::decode(old_pools
, p
);
747 ::decode(max_size_ever
, p
);
749 ::decode(inline_data
, p
);
751 inline_data
.version
= CEPH_INLINE_NONE
;
754 backtrace_version
= 0; // force update backtrace
758 if (struct_v
>= 12) {
761 stray_prior_path
= std::basic_string
<char,std::char_traits
<char>,Allocator
<char>>(boost::string_view(tmp
));
764 if (struct_v
>= 13) {
765 ::decode(last_scrub_version
, p
);
766 ::decode(last_scrub_stamp
, p
);
768 if (struct_v
>= 14) {
770 ::decode(change_attr
, p
);
776 if (struct_v
>= 15) {
777 ::decode(export_pin
, p
);
779 export_pin
= MDS_RANK_NONE
;
785 template<template<typename
> class Allocator
>
786 void inode_t
<Allocator
>::dump(Formatter
*f
) const
788 f
->dump_unsigned("ino", ino
);
789 f
->dump_unsigned("rdev", rdev
);
790 f
->dump_stream("ctime") << ctime
;
791 f
->dump_stream("btime") << btime
;
792 f
->dump_unsigned("mode", mode
);
793 f
->dump_unsigned("uid", uid
);
794 f
->dump_unsigned("gid", gid
);
795 f
->dump_unsigned("nlink", nlink
);
797 f
->open_object_section("dir_layout");
798 ::dump(dir_layout
, f
);
801 f
->dump_object("layout", layout
);
803 f
->open_array_section("old_pools");
804 for (const auto &p
: old_pools
) {
805 f
->dump_int("pool", p
);
809 f
->dump_unsigned("size", size
);
810 f
->dump_unsigned("truncate_seq", truncate_seq
);
811 f
->dump_unsigned("truncate_size", truncate_size
);
812 f
->dump_unsigned("truncate_from", truncate_from
);
813 f
->dump_unsigned("truncate_pending", truncate_pending
);
814 f
->dump_stream("mtime") << mtime
;
815 f
->dump_stream("atime") << atime
;
816 f
->dump_unsigned("time_warp_seq", time_warp_seq
);
817 f
->dump_unsigned("change_attr", change_attr
);
818 f
->dump_int("export_pin", export_pin
);
820 f
->open_array_section("client_ranges");
821 for (const auto &p
: client_ranges
) {
822 f
->open_object_section("client");
823 f
->dump_unsigned("client", p
.first
.v
);
829 f
->open_object_section("dirstat");
833 f
->open_object_section("rstat");
837 f
->open_object_section("accounted_rstat");
838 accounted_rstat
.dump(f
);
841 f
->dump_unsigned("version", version
);
842 f
->dump_unsigned("file_data_version", file_data_version
);
843 f
->dump_unsigned("xattr_version", xattr_version
);
844 f
->dump_unsigned("backtrace_version", backtrace_version
);
846 f
->dump_string("stray_prior_path", stray_prior_path
);
849 template<template<typename
> class Allocator
>
850 void inode_t
<Allocator
>::generate_test_instances(list
<inode_t
*>& ls
)
852 ls
.push_back(new inode_t
<Allocator
>);
853 ls
.push_back(new inode_t
<Allocator
>);
858 template<template<typename
> class Allocator
>
859 int inode_t
<Allocator
>::compare(const inode_t
<Allocator
> &other
, bool *divergent
) const
861 assert(ino
== other
.ino
);
863 if (version
== other
.version
) {
864 if (rdev
!= other
.rdev
||
865 ctime
!= other
.ctime
||
866 btime
!= other
.btime
||
867 mode
!= other
.mode
||
870 nlink
!= other
.nlink
||
871 memcmp(&dir_layout
, &other
.dir_layout
, sizeof(dir_layout
)) ||
872 layout
!= other
.layout
||
873 old_pools
!= other
.old_pools
||
874 size
!= other
.size
||
875 max_size_ever
!= other
.max_size_ever
||
876 truncate_seq
!= other
.truncate_seq
||
877 truncate_size
!= other
.truncate_size
||
878 truncate_from
!= other
.truncate_from
||
879 truncate_pending
!= other
.truncate_pending
||
880 change_attr
!= other
.change_attr
||
881 mtime
!= other
.mtime
||
882 atime
!= other
.atime
||
883 time_warp_seq
!= other
.time_warp_seq
||
884 inline_data
!= other
.inline_data
||
885 client_ranges
!= other
.client_ranges
||
886 !(dirstat
== other
.dirstat
) ||
887 !(rstat
== other
.rstat
) ||
888 !(accounted_rstat
== other
.accounted_rstat
) ||
889 file_data_version
!= other
.file_data_version
||
890 xattr_version
!= other
.xattr_version
||
891 backtrace_version
!= other
.backtrace_version
) {
895 } else if (version
> other
.version
) {
896 *divergent
= !older_is_consistent(other
);
899 assert(version
< other
.version
);
900 *divergent
= !other
.older_is_consistent(*this);
905 template<template<typename
> class Allocator
>
906 bool inode_t
<Allocator
>::older_is_consistent(const inode_t
<Allocator
> &other
) const
908 if (max_size_ever
< other
.max_size_ever
||
909 truncate_seq
< other
.truncate_seq
||
910 time_warp_seq
< other
.time_warp_seq
||
911 inline_data
.version
< other
.inline_data
.version
||
912 dirstat
.version
< other
.dirstat
.version
||
913 rstat
.version
< other
.rstat
.version
||
914 accounted_rstat
.version
< other
.accounted_rstat
.version
||
915 file_data_version
< other
.file_data_version
||
916 xattr_version
< other
.xattr_version
||
917 backtrace_version
< other
.backtrace_version
) {
923 template<template<typename
> class Allocator
>
924 inline void encode(const inode_t
<Allocator
> &c
, ::ceph::bufferlist
&bl
, uint64_t features
)
927 c
.encode(bl
, features
);
928 ENCODE_DUMP_POST(cl
);
930 template<template<typename
> class Allocator
>
931 inline void decode(inode_t
<Allocator
> &c
, ::ceph::bufferlist::iterator
&p
)
936 template<template<typename
> class Allocator
>
937 using alloc_string
= std::basic_string
<char,std::char_traits
<char>,Allocator
<char>>;
939 template<template<typename
> class Allocator
>
940 using xattr_map
= compact_map
<alloc_string
<Allocator
>, bufferptr
, std::less
<alloc_string
<Allocator
>>, Allocator
<std::pair
<const alloc_string
<Allocator
>, bufferptr
>>>; // FIXME bufferptr not in mempool
945 template<template<typename
> class Allocator
= std::allocator
>
948 inode_t
<Allocator
> inode
;
949 xattr_map
<Allocator
> xattrs
;
951 void encode(bufferlist
&bl
, uint64_t features
) const;
952 void decode(bufferlist::iterator
& bl
);
953 void dump(Formatter
*f
) const;
954 static void generate_test_instances(std::list
<old_inode_t
*>& ls
);
957 // These methods may be moved back to mdstypes.cc when we have pmr
958 template<template<typename
> class Allocator
>
959 void old_inode_t
<Allocator
>::encode(bufferlist
& bl
, uint64_t features
) const
961 ENCODE_START(2, 2, bl
);
963 ::encode(inode
, bl
, features
);
964 ::encode(xattrs
, bl
);
968 template<template<typename
> class Allocator
>
969 void old_inode_t
<Allocator
>::decode(bufferlist::iterator
& bl
)
971 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl
);
974 ::decode(xattrs
, bl
);
978 template<template<typename
> class Allocator
>
979 void old_inode_t
<Allocator
>::dump(Formatter
*f
) const
981 f
->dump_unsigned("first", first
);
983 f
->open_object_section("xattrs");
984 for (const auto &p
: xattrs
) {
985 std::string
v(p
.second
.c_str(), p
.second
.length());
986 f
->dump_string(p
.first
.c_str(), v
);
991 template<template<typename
> class Allocator
>
992 void old_inode_t
<Allocator
>::generate_test_instances(std::list
<old_inode_t
<Allocator
>*>& ls
)
994 ls
.push_back(new old_inode_t
<Allocator
>);
995 ls
.push_back(new old_inode_t
<Allocator
>);
996 ls
.back()->first
= 2;
997 std::list
<inode_t
<Allocator
>*> ils
;
998 inode_t
<Allocator
>::generate_test_instances(ils
);
999 ls
.back()->inode
= *ils
.back();
1000 ls
.back()->xattrs
["user.foo"] = buffer::copy("asdf", 4);
1001 ls
.back()->xattrs
["user.unprintable"] = buffer::copy("\000\001\002", 3);
1004 template<template<typename
> class Allocator
>
1005 inline void encode(const old_inode_t
<Allocator
> &c
, ::ceph::bufferlist
&bl
, uint64_t features
)
1008 c
.encode(bl
, features
);
1009 ENCODE_DUMP_POST(cl
);
1011 template<template<typename
> class Allocator
>
1012 inline void decode(old_inode_t
<Allocator
> &c
, ::ceph::bufferlist::iterator
&p
)
1019 * like an inode, but for a dir frag
1022 version_t version
= 0;
1023 snapid_t snap_purged_thru
; // the max_last_destroy snapid we've been purged thru
1024 frag_info_t fragstat
, accounted_fragstat
;
1025 nest_info_t rstat
, accounted_rstat
;
1026 damage_flags_t damage_flags
= 0;
1028 // we know we and all our descendants have been scrubbed since this version
1029 version_t recursive_scrub_version
= 0;
1030 utime_t recursive_scrub_stamp
;
1031 // version at which we last scrubbed our personal data structures
1032 version_t localized_scrub_version
= 0;
1033 utime_t localized_scrub_stamp
;
1035 void encode(bufferlist
&bl
) const;
1036 void decode(bufferlist::iterator
& bl
);
1037 void dump(Formatter
*f
) const;
1038 static void generate_test_instances(list
<fnode_t
*>& ls
);
1041 WRITE_CLASS_ENCODER(fnode_t
)
1044 struct old_rstat_t
{
1046 nest_info_t rstat
, accounted_rstat
;
1048 void encode(bufferlist
& bl
) const;
1049 void decode(bufferlist::iterator
& p
);
1050 void dump(Formatter
*f
) const;
1051 static void generate_test_instances(list
<old_rstat_t
*>& ls
);
1053 WRITE_CLASS_ENCODER(old_rstat_t
)
1055 inline std::ostream
& operator<<(std::ostream
& out
, const old_rstat_t
& o
) {
1056 return out
<< "old_rstat(first " << o
.first
<< " " << o
.rstat
<< " " << o
.accounted_rstat
<< ")";
1064 struct session_info_t
{
1066 std::map
<ceph_tid_t
,inodeno_t
> completed_requests
;
1067 interval_set
<inodeno_t
> prealloc_inos
; // preallocated, ready to use.
1068 interval_set
<inodeno_t
> used_inos
; // journaling use
1069 std::map
<std::string
, std::string
> client_metadata
;
1070 std::set
<ceph_tid_t
> completed_flushes
;
1071 EntityName auth_name
;
1073 client_t
get_client() const { return client_t(inst
.name
.num()); }
1074 const entity_name_t
& get_source() const { return inst
.name
; }
1077 prealloc_inos
.clear();
1079 completed_requests
.clear();
1080 completed_flushes
.clear();
1083 void encode(bufferlist
& bl
, uint64_t features
) const;
1084 void decode(bufferlist::iterator
& p
);
1085 void dump(Formatter
*f
) const;
1086 static void generate_test_instances(list
<session_info_t
*>& ls
);
1088 WRITE_CLASS_ENCODER_FEATURES(session_info_t
)
1094 struct dentry_key_t
{
1095 snapid_t snapid
= 0;
1096 boost::string_view name
;
1099 dentry_key_t(snapid_t s
, boost::string_view n
, __u32 h
=0) :
1100 snapid(s
), name(n
), hash(h
) {}
1102 bool is_valid() { return name
.length() || snapid
; }
1104 // encode into something that can be decoded as a string.
1105 // name_ (head) or name_%x (!head)
1106 void encode(bufferlist
& bl
) const {
1111 void encode(string
& key
) const {
1113 if (snapid
!= CEPH_NOSNAP
) {
1114 uint64_t val(snapid
);
1115 snprintf(b
, sizeof(b
), "%" PRIx64
, val
);
1117 snprintf(b
, sizeof(b
), "%s", "head");
1120 oss
<< name
<< "_" << b
;
1123 static void decode_helper(bufferlist::iterator
& bl
, string
& nm
, snapid_t
& sn
) {
1126 decode_helper(key
, nm
, sn
);
1128 static void decode_helper(boost::string_view key
, string
& nm
, snapid_t
& sn
) {
1129 size_t i
= key
.find_last_of('_');
1130 assert(i
!= string::npos
);
1131 if (key
.compare(i
+1, boost::string_view::npos
, "head") == 0) {
1136 long long unsigned x
= 0;
1137 std::string
x_str(key
.substr(i
+1));
1138 sscanf(x_str
.c_str(), "%llx", &x
);
1141 nm
= std::string(key
.substr(0, i
));
1145 inline std::ostream
& operator<<(std::ostream
& out
, const dentry_key_t
&k
)
1147 return out
<< "(" << k
.name
<< "," << k
.snapid
<< ")";
1150 inline bool operator<(const dentry_key_t
& k1
, const dentry_key_t
& k2
)
1153 * order by hash, name, snap
1155 int c
= ceph_frag_value(k1
.hash
) - ceph_frag_value(k2
.hash
);
1158 c
= k1
.name
.compare(k2
.name
);
1161 return k1
.snapid
< k2
.snapid
;
1166 * string_snap_t is a simple (string, snapid_t) pair
1168 struct string_snap_t
{
1172 string_snap_t(boost::string_view n
, snapid_t s
) : name(n
), snapid(s
) {}
1173 string_snap_t(const char *n
, snapid_t s
) : name(n
), snapid(s
) {}
1175 void encode(bufferlist
& bl
) const;
1176 void decode(bufferlist::iterator
& p
);
1177 void dump(Formatter
*f
) const;
1178 static void generate_test_instances(list
<string_snap_t
*>& ls
);
1180 WRITE_CLASS_ENCODER(string_snap_t
)
1182 inline bool operator<(const string_snap_t
& l
, const string_snap_t
& r
) {
1183 int c
= l
.name
.compare(r
.name
);
1184 return c
< 0 || (c
== 0 && l
.snapid
< r
.snapid
);
1187 inline std::ostream
& operator<<(std::ostream
& out
, const string_snap_t
&k
)
1189 return out
<< "(" << k
.name
<< "," << k
.snapid
<< ")";
1193 * mds_table_pending_t
1195 * mds's requesting any pending ops. child needs to encode the corresponding
1196 * pending mutation state in the table.
1198 struct mds_table_pending_t
{
1202 mds_table_pending_t() {}
1203 void encode(bufferlist
& bl
) const;
1204 void decode(bufferlist::iterator
& bl
);
1205 void dump(Formatter
*f
) const;
1206 static void generate_test_instances(list
<mds_table_pending_t
*>& ls
);
1208 WRITE_CLASS_ENCODER(mds_table_pending_t
)
1214 struct metareqid_t
{
1218 metareqid_t(entity_name_t n
, ceph_tid_t t
) : name(n
), tid(t
) {}
1219 void encode(bufferlist
& bl
) const {
1223 void decode(bufferlist::iterator
&p
) {
1228 WRITE_CLASS_ENCODER(metareqid_t
)
1230 inline std::ostream
& operator<<(std::ostream
& out
, const metareqid_t
& r
) {
1231 return out
<< r
.name
<< ":" << r
.tid
;
1234 inline bool operator==(const metareqid_t
& l
, const metareqid_t
& r
) {
1235 return (l
.name
== r
.name
) && (l
.tid
== r
.tid
);
1237 inline bool operator!=(const metareqid_t
& l
, const metareqid_t
& r
) {
1238 return (l
.name
!= r
.name
) || (l
.tid
!= r
.tid
);
1240 inline bool operator<(const metareqid_t
& l
, const metareqid_t
& r
) {
1241 return (l
.name
< r
.name
) ||
1242 (l
.name
== r
.name
&& l
.tid
< r
.tid
);
1244 inline bool operator<=(const metareqid_t
& l
, const metareqid_t
& r
) {
1245 return (l
.name
< r
.name
) ||
1246 (l
.name
== r
.name
&& l
.tid
<= r
.tid
);
1248 inline bool operator>(const metareqid_t
& l
, const metareqid_t
& r
) { return !(l
<= r
); }
1249 inline bool operator>=(const metareqid_t
& l
, const metareqid_t
& r
) { return !(l
< r
); }
1252 template<> struct hash
<metareqid_t
> {
1253 size_t operator()(const metareqid_t
&r
) const {
1255 return H(r
.name
.num()) ^ H(r
.name
.type()) ^ H(r
.tid
);
1261 // cap info for client reconnect
1262 struct cap_reconnect_t
{
1264 mutable ceph_mds_cap_reconnect capinfo
;
1265 snapid_t snap_follows
;
1269 memset(&capinfo
, 0, sizeof(capinfo
));
1272 cap_reconnect_t(uint64_t cap_id
, inodeno_t pino
, boost::string_view p
, int w
, int i
,
1273 inodeno_t sr
, snapid_t sf
, bufferlist
& lb
) :
1275 capinfo
.cap_id
= cap_id
;
1278 capinfo
.snaprealm
= sr
;
1279 capinfo
.pathbase
= pino
;
1280 capinfo
.flock_len
= 0;
1284 void encode(bufferlist
& bl
) const;
1285 void decode(bufferlist::iterator
& bl
);
1286 void encode_old(bufferlist
& bl
) const;
1287 void decode_old(bufferlist::iterator
& bl
);
1289 void dump(Formatter
*f
) const;
1290 static void generate_test_instances(list
<cap_reconnect_t
*>& ls
);
1292 WRITE_CLASS_ENCODER(cap_reconnect_t
)
1295 // compat for pre-FLOCK feature
1296 struct old_ceph_mds_cap_reconnect
{
1301 struct ceph_timespec old_mtime
, old_atime
;
1303 __le64 pathbase
; /* base ino for our path to this ino */
1304 } __attribute__ ((packed
));
1305 WRITE_RAW_ENCODER(old_ceph_mds_cap_reconnect
)
1307 struct old_cap_reconnect_t
{
1309 old_ceph_mds_cap_reconnect capinfo
;
1311 const old_cap_reconnect_t
& operator=(const cap_reconnect_t
& n
) {
1313 capinfo
.cap_id
= n
.capinfo
.cap_id
;
1314 capinfo
.wanted
= n
.capinfo
.wanted
;
1315 capinfo
.issued
= n
.capinfo
.issued
;
1316 capinfo
.snaprealm
= n
.capinfo
.snaprealm
;
1317 capinfo
.pathbase
= n
.capinfo
.pathbase
;
1320 operator cap_reconnect_t() {
1323 n
.capinfo
.cap_id
= capinfo
.cap_id
;
1324 n
.capinfo
.wanted
= capinfo
.wanted
;
1325 n
.capinfo
.issued
= capinfo
.issued
;
1326 n
.capinfo
.snaprealm
= capinfo
.snaprealm
;
1327 n
.capinfo
.pathbase
= capinfo
.pathbase
;
1331 void encode(bufferlist
& bl
) const {
1333 ::encode(capinfo
, bl
);
1335 void decode(bufferlist::iterator
& bl
) {
1337 ::decode(capinfo
, bl
);
1340 WRITE_CLASS_ENCODER(old_cap_reconnect_t
)
1343 // ================================================================
1351 dirfrag_t(inodeno_t i
, frag_t f
) : ino(i
), frag(f
) { }
1353 void encode(bufferlist
& bl
) const {
1357 void decode(bufferlist::iterator
& bl
) {
1362 WRITE_CLASS_ENCODER(dirfrag_t
)
1365 inline std::ostream
& operator<<(std::ostream
& out
, const dirfrag_t
&df
) {
1367 if (!df
.frag
.is_root()) out
<< "." << df
.frag
;
1370 inline bool operator<(dirfrag_t l
, dirfrag_t r
) {
1371 if (l
.ino
< r
.ino
) return true;
1372 if (l
.ino
== r
.ino
&& l
.frag
< r
.frag
) return true;
1375 inline bool operator==(dirfrag_t l
, dirfrag_t r
) {
1376 return l
.ino
== r
.ino
&& l
.frag
== r
.frag
;
1380 template<> struct hash
<dirfrag_t
> {
1381 size_t operator()(const dirfrag_t
&df
) const {
1382 static rjhash
<uint64_t> H
;
1383 static rjhash
<uint32_t> I
;
1384 return H(df
.ino
) ^ I(df
.frag
);
1391 // ================================================================
1393 #define META_POP_IRD 0
1394 #define META_POP_IWR 1
1395 #define META_POP_READDIR 2
1396 #define META_POP_FETCH 3
1397 #define META_POP_STORE 4
1400 class inode_load_vec_t
{
1401 static const int NUM
= 2;
1402 std::array
<DecayCounter
, NUM
> vec
;
1404 explicit inode_load_vec_t(const utime_t
&now
)
1405 : vec
{DecayCounter(now
), DecayCounter(now
)}
1407 // for dencoder infrastructure
1408 inode_load_vec_t() {}
1409 DecayCounter
&get(int t
) {
1413 void zero(utime_t now
) {
1414 for (int i
=0; i
<NUM
; i
++)
1417 void encode(bufferlist
&bl
) const;
1418 void decode(const utime_t
&t
, bufferlist::iterator
&p
);
1420 void decode(bufferlist::iterator
& p
) { utime_t sample
; decode(sample
, p
); }
1421 void dump(Formatter
*f
);
1422 static void generate_test_instances(list
<inode_load_vec_t
*>& ls
);
1424 inline void encode(const inode_load_vec_t
&c
, bufferlist
&bl
) { c
.encode(bl
); }
1425 inline void decode(inode_load_vec_t
& c
, const utime_t
&t
, bufferlist::iterator
&p
) {
1429 inline void decode(inode_load_vec_t
& c
, bufferlist::iterator
&p
) {
1431 c
.decode(sample
, p
);
1434 class dirfrag_load_vec_t
{
1436 static const int NUM
= 5;
1437 std::array
<DecayCounter
, NUM
> vec
;
1438 explicit dirfrag_load_vec_t(const utime_t
&now
)
1447 // for dencoder infrastructure
1448 dirfrag_load_vec_t() {}
1449 void encode(bufferlist
&bl
) const {
1450 ENCODE_START(2, 2, bl
);
1451 for (const auto &i
: vec
) {
1456 void decode(const utime_t
&t
, bufferlist::iterator
&p
) {
1457 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, p
);
1458 for (auto &i
: vec
) {
1463 // for dencoder infrastructure
1464 void decode(bufferlist::iterator
& p
) {
1468 void dump(Formatter
*f
) const;
1469 static void generate_test_instances(list
<dirfrag_load_vec_t
*>& ls
);
1471 DecayCounter
&get(int t
) {
1475 void adjust(utime_t now
, const DecayRate
& rate
, double d
) {
1476 for (auto &i
: vec
) {
1477 i
.adjust(now
, rate
, d
);
1480 void zero(utime_t now
) {
1481 for (auto &i
: vec
) {
1485 double meta_load(utime_t now
, const DecayRate
& rate
) {
1487 1*vec
[META_POP_IRD
].get(now
, rate
) +
1488 2*vec
[META_POP_IWR
].get(now
, rate
) +
1489 1*vec
[META_POP_READDIR
].get(now
, rate
) +
1490 2*vec
[META_POP_FETCH
].get(now
, rate
) +
1491 4*vec
[META_POP_STORE
].get(now
, rate
);
1493 double meta_load() {
1495 1*vec
[META_POP_IRD
].get_last() +
1496 2*vec
[META_POP_IWR
].get_last() +
1497 1*vec
[META_POP_READDIR
].get_last() +
1498 2*vec
[META_POP_FETCH
].get_last() +
1499 4*vec
[META_POP_STORE
].get_last();
1502 void add(utime_t now
, DecayRate
& rate
, dirfrag_load_vec_t
& r
) {
1503 for (int i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
1504 vec
[i
].adjust(r
.vec
[i
].get(now
, rate
));
1506 void sub(utime_t now
, DecayRate
& rate
, dirfrag_load_vec_t
& r
) {
1507 for (int i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
1508 vec
[i
].adjust(-r
.vec
[i
].get(now
, rate
));
1510 void scale(double f
) {
1511 for (int i
=0; i
<dirfrag_load_vec_t::NUM
; i
++)
1516 inline void encode(const dirfrag_load_vec_t
&c
, bufferlist
&bl
) { c
.encode(bl
); }
1517 inline void decode(dirfrag_load_vec_t
& c
, const utime_t
&t
, bufferlist::iterator
&p
) {
1520 // this for dencoder
1521 inline void decode(dirfrag_load_vec_t
& c
, bufferlist::iterator
&p
) {
1523 c
.decode(sample
, p
);
1526 inline std::ostream
& operator<<(std::ostream
& out
, dirfrag_load_vec_t
& dl
)
1529 utime_t now
= ceph_clock_now();
1530 DecayRate
rate(g_conf
->mds_decay_halflife
);
1531 return out
<< "[" << dl
.vec
[0].get(now
, rate
) << "," << dl
.vec
[1].get(now
, rate
)
1532 << " " << dl
.meta_load(now
, rate
)
1546 dirfrag_load_vec_t auth
;
1547 dirfrag_load_vec_t all
;
1549 double req_rate
= 0.0;
1550 double cache_hit_rate
= 0.0;
1551 double queue_len
= 0.0;
1553 double cpu_load_avg
= 0.0;
1555 explicit mds_load_t(const utime_t
&t
) : auth(t
), all(t
) {}
1556 // mostly for the dencoder infrastructure
1557 mds_load_t() : auth(), all() {}
1559 double mds_load(); // defiend in MDBalancer.cc
1560 void encode(bufferlist
& bl
) const;
1561 void decode(const utime_t
& now
, bufferlist::iterator
& bl
);
1562 //this one is for dencoder infrastructure
1563 void decode(bufferlist::iterator
& bl
) { utime_t sample
; decode(sample
, bl
); }
1564 void dump(Formatter
*f
) const;
1565 static void generate_test_instances(list
<mds_load_t
*>& ls
);
1567 inline void encode(const mds_load_t
&c
, bufferlist
&bl
) { c
.encode(bl
); }
1568 inline void decode(mds_load_t
&c
, const utime_t
&t
, bufferlist::iterator
&p
) {
1571 // this one is for dencoder
1572 inline void decode(mds_load_t
&c
, bufferlist::iterator
&p
) {
1574 c
.decode(sample
, p
);
1577 inline std::ostream
& operator<<( std::ostream
& out
, mds_load_t
& load
)
1579 return out
<< "mdsload<" << load
.auth
<< "/" << load
.all
1580 << ", req " << load
.req_rate
1581 << ", hr " << load
.cache_hit_rate
1582 << ", qlen " << load
.queue_len
1583 << ", cpu " << load
.cpu_load_avg
1587 class load_spread_t
{
1589 static const int MAX
= 4;
1595 load_spread_t() : count(ceph_clock_now())
1597 for (int i
=0; i
<MAX
; i
++)
1601 double hit(utime_t now
, const DecayRate
& rate
, int who
) {
1602 for (int i
=0; i
<n
; i
++)
1604 return count
.get_last();
1609 if (n
== 1) return 0.0;
1611 if (p
== MAX
) p
= 0;
1613 return count
.hit(now
, rate
);
1615 double get(utime_t now
, const DecayRate
& rate
) {
1616 return count
.get(now
, rate
);
1622 // ================================================================
1623 typedef std::pair
<mds_rank_t
, mds_rank_t
> mds_authority_t
;
1625 // -- authority delegation --
1626 // directory authority types
1627 // >= 0 is the auth mds
1628 #define CDIR_AUTH_PARENT mds_rank_t(-1) // default
1629 #define CDIR_AUTH_UNKNOWN mds_rank_t(-2)
1630 #define CDIR_AUTH_DEFAULT mds_authority_t(CDIR_AUTH_PARENT, CDIR_AUTH_UNKNOWN)
1631 #define CDIR_AUTH_UNDEF mds_authority_t(CDIR_AUTH_UNKNOWN, CDIR_AUTH_UNKNOWN)
1632 //#define CDIR_AUTH_ROOTINODE pair<int,int>( 0, -2)
1634 class MDSCacheObjectInfo
{
1641 MDSCacheObjectInfo() {}
1643 void encode(bufferlist
& bl
) const;
1644 void decode(bufferlist::iterator
& bl
);
1645 void dump(Formatter
*f
) const;
1646 static void generate_test_instances(list
<MDSCacheObjectInfo
*>& ls
);
1649 inline std::ostream
& operator<<(std::ostream
& out
, const MDSCacheObjectInfo
&info
) {
1650 if (info
.ino
) return out
<< info
.ino
<< "." << info
.snapid
;
1651 if (info
.dname
.length()) return out
<< info
.dirfrag
<< "/" << info
.dname
1652 << " snap " << info
.snapid
;
1653 return out
<< info
.dirfrag
;
1656 inline bool operator==(const MDSCacheObjectInfo
& l
, const MDSCacheObjectInfo
& r
) {
1658 return l
.ino
== r
.ino
&& l
.snapid
== r
.snapid
;
1660 return l
.dirfrag
== r
.dirfrag
&& l
.dname
== r
.dname
;
1662 WRITE_CLASS_ENCODER(MDSCacheObjectInfo
)
1665 // parse a map of keys/values.
1666 namespace qi
= boost::spirit::qi
;
1668 template <typename Iterator
>
1669 struct keys_and_values
1670 : qi::grammar
<Iterator
, std::map
<string
, string
>()>
1673 : keys_and_values::base_type(query
)
1675 query
= pair
>> *(qi::lit(' ') >> pair
);
1676 pair
= key
>> '=' >> value
;
1677 key
= qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
1678 value
= +qi::char_("a-zA-Z_0-9");
1680 qi::rule
<Iterator
, std::map
<string
, string
>()> query
;
1681 qi::rule
<Iterator
, std::pair
<string
, string
>()> pair
;
1682 qi::rule
<Iterator
, string()> key
, value
;