1 #ifndef CEPH_MDSCACHEOBJECT_H
2 #define CEPH_MDSCACHEOBJECT_H
7 #include "common/config.h"
9 #include "include/Context.h"
10 #include "include/ceph_assert.h"
11 #include "include/mempool.h"
12 #include "include/types.h"
13 #include "include/xlist.h"
16 #include "MDSContext.h"
17 #include "include/elist.h"
19 #define MDS_REF_SET // define me for improved debug output, sanity checking
20 //#define MDS_AUTHPIN_SET // define me for debugging auth pin leaks
21 //#define MDS_VERIFY_FRAGSTAT // do (slow) sanity checking on frags
24 * for metadata leases to clients
36 ClientLease(client_t c
, MDSCacheObject
*p
) :
38 item_session_lease(this),
40 ClientLease() = delete;
43 MDSCacheObject
*parent
;
47 xlist
<ClientLease
*>::item item_session_lease
; // per-session list
48 xlist
<ClientLease
*>::item item_lease
; // global list
52 struct mdsco_db_line_prefix
{
53 explicit mdsco_db_line_prefix(MDSCacheObject
*o
) : object(o
) {}
54 MDSCacheObject
*object
;
57 class MDSCacheObject
{
59 typedef mempool::mds_co::compact_map
<mds_rank_t
,unsigned> replica_map_type
;
62 bool operator()(const MDSCacheObject
* l
, const MDSCacheObject
* r
) const {
68 const static int PIN_REPLICATED
= 1000;
69 const static int PIN_DIRTY
= 1001;
70 const static int PIN_LOCK
= -1002;
71 const static int PIN_REQUEST
= -1003;
72 const static int PIN_WAITER
= 1004;
73 const static int PIN_DIRTYSCATTERED
= -1005;
74 static const int PIN_AUTHPIN
= 1006;
75 static const int PIN_PTRWAITER
= -1007;
76 const static int PIN_TEMPEXPORTING
= 1008; // temp pin between encode_ and finish_export
77 static const int PIN_CLIENTLEASE
= 1009;
78 static const int PIN_DISCOVERBASE
= 1010;
79 static const int PIN_SCRUBQUEUE
= 1011; // for scrub of inode and dir
82 const static int STATE_AUTH
= (1<<30);
83 const static int STATE_DIRTY
= (1<<29);
84 const static int STATE_NOTIFYREF
= (1<<28); // notify dropping ref drop through _put()
85 const static int STATE_REJOINING
= (1<<27); // replica has not joined w/ primary copy
86 const static int STATE_REJOINUNDEF
= (1<<26); // contents undefined.
89 const static uint64_t WAIT_ORDERED
= (1ull<<61);
90 const static uint64_t WAIT_SINGLEAUTH
= (1ull<<60);
91 const static uint64_t WAIT_UNFREEZE
= (1ull<<59); // pka AUTHPINNABLE
93 elist
<MDSCacheObject
*>::item item_scrub
; // for scrub inode or dir
96 virtual ~MDSCacheObject() {}
98 std::string_view
generic_pin_name(int p
) const;
101 virtual void print(std::ostream
& out
) = 0;
102 virtual std::ostream
& print_db_line_prefix(std::ostream
& out
) {
103 return out
<< "mdscacheobject(" << this << ") ";
106 unsigned get_state() const { return state
; }
107 unsigned state_test(unsigned mask
) const { return (state
& mask
); }
108 void state_clear(unsigned mask
) { state
&= ~mask
; }
109 void state_set(unsigned mask
) { state
|= mask
; }
110 void state_reset(unsigned s
) { state
= s
; }
112 bool is_auth() const { return state_test(STATE_AUTH
); }
113 bool is_dirty() const { return state_test(STATE_DIRTY
); }
114 bool is_clean() const { return !is_dirty(); }
115 bool is_rejoining() const { return state_test(STATE_REJOINING
); }
117 // --------------------------------------------
119 virtual mds_authority_t
authority() const = 0;
120 virtual bool is_ambiguous_auth() const {
121 return authority().second
!= CDIR_AUTH_UNKNOWN
;
124 int get_num_ref(int by
= -1) const {
127 if (ref_map
.find(by
) == ref_map
.end()) {
130 return ref_map
.find(by
)->second
;
136 virtual std::string_view
pin_name(int by
) const = 0;
137 //bool is_pinned_by(int by) { return ref_set.count(by); }
138 //multiset<int>& get_ref_set() { return ref_set; }
140 virtual void last_put() {}
141 virtual void bad_put(int by
) {
143 ceph_assert(ref_map
[by
] > 0);
145 ceph_assert(ref
> 0);
147 virtual void _put() {}
150 if (ref
== 0 || ref_map
[by
] == 0) {
162 if (state_test(STATE_NOTIFYREF
))
167 virtual void first_get() {}
168 virtual void bad_get(int by
) {
170 ceph_assert(by
< 0 || ref_map
[by
] == 0);
179 if (ref_map
.find(by
) == ref_map
.end())
185 void print_pin_set(std::ostream
& out
) const {
187 for(auto const &p
: ref_map
) {
188 out
<< " " << pin_name(p
.first
) << "=" << p
.second
;
191 out
<< " nref=" << ref
;
195 int get_num_auth_pins() const { return auth_pins
; }
196 #ifdef MDS_AUTHPIN_SET
197 void print_authpin_set(std::ostream
& out
) const {
198 out
<< " (" << auth_pin_set
<< ")";
202 void dump_states(ceph::Formatter
*f
) const;
203 void dump(ceph::Formatter
*f
) const;
207 // can_auth_pin() error codes
213 virtual bool can_auth_pin(int *err_code
=nullptr) const = 0;
214 virtual void auth_pin(void *who
) = 0;
215 virtual void auth_unpin(void *who
) = 0;
216 virtual bool is_frozen() const = 0;
217 virtual bool is_freezing() const = 0;
218 virtual bool is_freezing_or_frozen() const {
219 return is_frozen() || is_freezing();
222 bool is_replicated() const { return !get_replicas().empty(); }
223 bool is_replica(mds_rank_t mds
) const { return get_replicas().count(mds
); }
224 int num_replicas() const { return get_replicas().size(); }
225 unsigned add_replica(mds_rank_t mds
) {
226 if (get_replicas().count(mds
))
227 return ++get_replicas()[mds
]; // inc nonce
228 if (get_replicas().empty())
230 return get_replicas()[mds
] = 1;
232 void add_replica(mds_rank_t mds
, unsigned nonce
) {
233 if (get_replicas().empty())
235 get_replicas()[mds
] = nonce
;
237 unsigned get_replica_nonce(mds_rank_t mds
) {
238 ceph_assert(get_replicas().count(mds
));
239 return get_replicas()[mds
];
241 void remove_replica(mds_rank_t mds
) {
242 ceph_assert(get_replicas().count(mds
));
243 get_replicas().erase(mds
);
244 if (get_replicas().empty()) {
248 void clear_replica_map() {
249 if (!get_replicas().empty())
253 replica_map_type
& get_replicas() { return replica_map
; }
254 const replica_map_type
& get_replicas() const { return replica_map
; }
255 void list_replicas(std::set
<mds_rank_t
>& ls
) const {
256 for (const auto &p
: get_replicas()) {
261 unsigned get_replica_nonce() const { return replica_nonce
; }
262 void set_replica_nonce(unsigned n
) { replica_nonce
= n
; }
264 bool is_waiter_for(uint64_t mask
, uint64_t min
=0);
265 virtual void add_waiter(uint64_t mask
, MDSContext
*c
) {
270 if (mask
& WAIT_ORDERED
) {
271 seq
= ++last_wait_seq
;
272 mask
&= ~WAIT_ORDERED
;
274 waiting
.insert(std::pair
<uint64_t, std::pair
<uint64_t, MDSContext
*> >(
276 std::pair
<uint64_t, MDSContext
*>(seq
, c
)));
277 // pdout(10,g_conf()->debug_mds) << (mdsco_db_line_prefix(this))
278 // << "add_waiter " << hex << mask << dec << " " << c
279 // << " on " << *this
283 virtual void take_waiting(uint64_t mask
, MDSContext::vec
& ls
);
284 void finish_waiting(uint64_t mask
, int result
= 0);
286 // ---------------------------------------------
288 // noop unless overloaded.
289 virtual SimpleLock
* get_lock(int type
) { ceph_abort(); return 0; }
290 virtual void set_object_info(MDSCacheObjectInfo
&info
) { ceph_abort(); }
291 virtual void encode_lock_state(int type
, ceph::buffer::list
& bl
) { ceph_abort(); }
292 virtual void decode_lock_state(int type
, const ceph::buffer::list
& bl
) { ceph_abort(); }
293 virtual void finish_lock_waiters(int type
, uint64_t mask
, int r
=0) { ceph_abort(); }
294 virtual void add_lock_waiter(int type
, uint64_t mask
, MDSContext
*c
) { ceph_abort(); }
295 virtual bool is_lock_waiting(int type
, uint64_t mask
) { ceph_abort(); return false; }
297 virtual void clear_dirty_scattered(int type
) { ceph_abort(); }
299 // ---------------------------------------------
301 virtual bool is_lt(const MDSCacheObject
*r
) const = 0;
305 __u32 state
= 0; // state bits
308 __s32 ref
= 0; // reference count
310 mempool::mds_co::flat_map
<int,int> ref_map
;
314 #ifdef MDS_AUTHPIN_SET
315 mempool::mds_co::multiset
<void*> auth_pin_set
;
318 // replication (across mds cluster)
319 unsigned replica_nonce
= 0; // [replica] defined on replica
320 replica_map_type replica_map
; // [auth] mds -> nonce
322 // ---------------------------------------------
325 mempool::mds_co::compact_multimap
<uint64_t, std::pair
<uint64_t, MDSContext
*>> waiting
;
326 static uint64_t last_wait_seq
;
329 std::ostream
& operator<<(std::ostream
& out
, const mdsco_db_line_prefix
& o
);
331 std::ostream
& operator<<(std::ostream
& out
, const MDSCacheObject
&o
);
333 inline std::ostream
& operator<<(std::ostream
& out
, MDSCacheObject
&o
) {
338 inline std::ostream
& operator<<(std::ostream
& out
, const mdsco_db_line_prefix
& o
) {
339 o
.object
->print_db_line_prefix(out
);