]>
Commit | Line | Data |
---|---|---|
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. | |
f67539c2 | 12 | * |
7c673cae FG |
13 | */ |
14 | ||
7c673cae FG |
15 | #ifndef CEPH_CDENTRY_H |
16 | #define CEPH_CDENTRY_H | |
17 | ||
18 | #include <string> | |
11fdf7f2 | 19 | #include <string_view> |
7c673cae FG |
20 | #include <set> |
21 | ||
22 | #include "include/counter.h" | |
23 | #include "include/types.h" | |
24 | #include "include/buffer_fwd.h" | |
25 | #include "include/lru.h" | |
26 | #include "include/elist.h" | |
27 | #include "include/filepath.h" | |
28 | ||
9f95a23c | 29 | #include "BatchOp.h" |
7c673cae | 30 | #include "MDSCacheObject.h" |
11fdf7f2 | 31 | #include "MDSContext.h" |
39ae355f | 32 | #include "Mutation.h" |
7c673cae | 33 | #include "SimpleLock.h" |
f67539c2 | 34 | #include "LocalLockC.h" |
7c673cae FG |
35 | #include "ScrubHeader.h" |
36 | ||
37 | class CInode; | |
38 | class CDir; | |
39 | class Locker; | |
7c673cae FG |
40 | class CDentry; |
41 | class LogSegment; | |
42 | ||
43 | class Session; | |
44 | ||
7c673cae FG |
45 | // define an ordering |
46 | bool operator<(const CDentry& l, const CDentry& r); | |
47 | ||
48 | // dentry | |
49 | class CDentry : public MDSCacheObject, public LRUObject, public Counter<CDentry> { | |
50 | public: | |
181888fb | 51 | MEMPOOL_CLASS_HELPERS(); |
7c673cae FG |
52 | friend class CDir; |
53 | ||
54 | struct linkage_t { | |
94b18763 FG |
55 | CInode *inode = nullptr; |
56 | inodeno_t remote_ino = 0; | |
57 | unsigned char remote_d_type = 0; | |
7c673cae | 58 | |
94b18763 | 59 | linkage_t() {} |
7c673cae FG |
60 | |
61 | // dentry type is primary || remote || null | |
62 | // inode ptr is required for primary, optional for remote, undefined for null | |
63 | bool is_primary() const { return remote_ino == 0 && inode != 0; } | |
64 | bool is_remote() const { return remote_ino > 0; } | |
65 | bool is_null() const { return remote_ino == 0 && inode == 0; } | |
66 | ||
67 | CInode *get_inode() { return inode; } | |
68 | const CInode *get_inode() const { return inode; } | |
69 | inodeno_t get_remote_ino() const { return remote_ino; } | |
70 | unsigned char get_remote_d_type() const { return remote_d_type; } | |
71 | std::string get_remote_d_type_string() const; | |
72 | ||
f67539c2 | 73 | void set_remote(inodeno_t ino, unsigned char d_type) { |
7c673cae FG |
74 | remote_ino = ino; |
75 | remote_d_type = d_type; | |
76 | inode = 0; | |
77 | } | |
78 | void link_remote(CInode *in); | |
79 | }; | |
80 | ||
81 | ||
82 | // -- state -- | |
83 | static const int STATE_NEW = (1<<0); | |
84 | static const int STATE_FRAGMENTING = (1<<1); | |
85 | static const int STATE_PURGING = (1<<2); | |
86 | static const int STATE_BADREMOTEINO = (1<<3); | |
87 | static const int STATE_EVALUATINGSTRAY = (1<<4); | |
88 | static const int STATE_PURGINGPINNED = (1<<5); | |
31f18b77 | 89 | static const int STATE_BOTTOMLRU = (1<<6); |
39ae355f | 90 | static const int STATE_UNLINKING = (1<<7); |
7c673cae FG |
91 | // stray dentry needs notification of releasing reference |
92 | static const int STATE_STRAY = STATE_NOTIFYREF; | |
31f18b77 | 93 | static const int MASK_STATE_IMPORT_KEPT = STATE_BOTTOMLRU; |
7c673cae FG |
94 | |
95 | // -- pins -- | |
39ae355f TL |
96 | static const int PIN_INODEPIN = 1; // linked inode is pinned |
97 | static const int PIN_FRAGMENTING = -2; // containing dir is refragmenting | |
98 | static const int PIN_PURGING = 3; | |
99 | static const int PIN_SCRUBPARENT = 4; | |
100 | static const int PIN_WAITUNLINKSTATE = 5; | |
7c673cae FG |
101 | |
102 | static const unsigned EXPORT_NONCE = 1; | |
103 | ||
39ae355f TL |
104 | const static uint64_t WAIT_UNLINK_STATE = (1<<0); |
105 | const static uint64_t WAIT_UNLINK_FINISH = (1<<1); | |
106 | uint32_t replica_unlinking_ref = 0; | |
7c673cae | 107 | |
11fdf7f2 | 108 | CDentry(std::string_view n, __u32 h, |
f67539c2 | 109 | mempool::mds_co::string alternate_name, |
7c673cae | 110 | snapid_t f, snapid_t l) : |
94b18763 | 111 | hash(h), |
7c673cae FG |
112 | first(f), last(l), |
113 | item_dirty(this), | |
114 | lock(this, &lock_type), | |
115 | versionlock(this, &versionlock_type), | |
f67539c2 TL |
116 | name(n), |
117 | alternate_name(std::move(alternate_name)) | |
94b18763 | 118 | {} |
f67539c2 TL |
119 | CDentry(std::string_view n, __u32 h, |
120 | mempool::mds_co::string alternate_name, | |
121 | inodeno_t ino, unsigned char dt, | |
7c673cae | 122 | snapid_t f, snapid_t l) : |
94b18763 | 123 | hash(h), |
7c673cae FG |
124 | first(f), last(l), |
125 | item_dirty(this), | |
126 | lock(this, &lock_type), | |
127 | versionlock(this, &versionlock_type), | |
f67539c2 TL |
128 | name(n), |
129 | alternate_name(std::move(alternate_name)) | |
94b18763 | 130 | { |
7c673cae FG |
131 | linkage.remote_ino = ino; |
132 | linkage.remote_d_type = dt; | |
133 | } | |
134 | ||
9f95a23c TL |
135 | ~CDentry() override { |
136 | ceph_assert(batch_ops.empty()); | |
137 | } | |
138 | ||
11fdf7f2 | 139 | std::string_view pin_name(int p) const override { |
7c673cae FG |
140 | switch (p) { |
141 | case PIN_INODEPIN: return "inodepin"; | |
142 | case PIN_FRAGMENTING: return "fragmenting"; | |
143 | case PIN_PURGING: return "purging"; | |
144 | case PIN_SCRUBPARENT: return "scrubparent"; | |
39ae355f | 145 | case PIN_WAITUNLINKSTATE: return "waitunlinkstate"; |
7c673cae FG |
146 | default: return generic_pin_name(p); |
147 | } | |
148 | } | |
149 | ||
150 | // -- wait -- | |
151 | //static const int WAIT_LOCK_OFFSET = 8; | |
152 | ||
11fdf7f2 | 153 | void add_waiter(uint64_t tag, MDSContext *c) override; |
7c673cae FG |
154 | |
155 | bool is_lt(const MDSCacheObject *r) const override { | |
156 | return *this < *static_cast<const CDentry*>(r); | |
157 | } | |
158 | ||
159 | dentry_key_t key() { | |
160 | return dentry_key_t(last, name.c_str(), hash); | |
161 | } | |
162 | ||
1e59de90 TL |
163 | bool check_corruption(bool load); |
164 | ||
7c673cae FG |
165 | const CDir *get_dir() const { return dir; } |
166 | CDir *get_dir() { return dir; } | |
11fdf7f2 | 167 | std::string_view get_name() const { return std::string_view(name); } |
f67539c2 TL |
168 | std::string_view get_alternate_name() const { |
169 | return std::string_view(alternate_name); | |
170 | } | |
171 | void set_alternate_name(mempool::mds_co::string altn) { | |
172 | alternate_name = std::move(altn); | |
173 | } | |
174 | void set_alternate_name(std::string_view altn) { | |
175 | alternate_name = mempool::mds_co::string(altn); | |
176 | } | |
7c673cae FG |
177 | |
178 | __u32 get_hash() const { return hash; } | |
179 | ||
180 | // linkage | |
181 | const linkage_t *get_linkage() const { return &linkage; } | |
182 | linkage_t *get_linkage() { return &linkage; } | |
183 | ||
184 | linkage_t *_project_linkage() { | |
185 | projected.push_back(linkage_t()); | |
186 | return &projected.back(); | |
187 | } | |
188 | void push_projected_linkage(); | |
189 | void push_projected_linkage(inodeno_t ino, char d_type) { | |
190 | linkage_t *p = _project_linkage(); | |
191 | p->remote_ino = ino; | |
192 | p->remote_d_type = d_type; | |
193 | } | |
194 | void push_projected_linkage(CInode *inode); | |
195 | linkage_t *pop_projected_linkage(); | |
196 | ||
197 | bool is_projected() const { return !projected.empty(); } | |
198 | ||
199 | linkage_t *get_projected_linkage() { | |
200 | if (!projected.empty()) | |
201 | return &projected.back(); | |
202 | return &linkage; | |
203 | } | |
204 | ||
205 | const linkage_t *get_projected_linkage() const { | |
206 | if (!projected.empty()) | |
207 | return &projected.back(); | |
208 | return &linkage; | |
209 | } | |
210 | ||
211 | CInode *get_projected_inode() { | |
212 | return get_projected_linkage()->inode; | |
213 | } | |
214 | ||
215 | bool use_projected(client_t client, const MutationRef& mut) const { | |
216 | return lock.can_read_projected(client) || | |
217 | lock.get_xlock_by() == mut; | |
218 | } | |
219 | linkage_t *get_linkage(client_t client, const MutationRef& mut) { | |
220 | return use_projected(client, mut) ? get_projected_linkage() : get_linkage(); | |
221 | } | |
222 | ||
223 | // ref counts: pin ourselves in the LRU when we're pinned. | |
224 | void first_get() override { | |
225 | lru_pin(); | |
226 | } | |
227 | void last_put() override { | |
228 | lru_unpin(); | |
229 | } | |
230 | void _put() override; | |
231 | ||
232 | // auth pins | |
91327a77 | 233 | bool can_auth_pin(int *err_ret=nullptr) const override; |
7c673cae FG |
234 | void auth_pin(void *by) override; |
235 | void auth_unpin(void *by) override; | |
11fdf7f2 | 236 | void adjust_nested_auth_pins(int diradj, void *by); |
7c673cae FG |
237 | bool is_frozen() const override; |
238 | bool is_freezing() const override; | |
239 | int get_num_dir_auth_pins() const; | |
240 | ||
241 | // remote links | |
242 | void link_remote(linkage_t *dnl, CInode *in); | |
243 | void unlink_remote(linkage_t *dnl); | |
244 | ||
245 | // copy cons | |
246 | CDentry(const CDentry& m); | |
247 | const CDentry& operator= (const CDentry& right); | |
248 | ||
249 | // misc | |
250 | void make_path_string(std::string& s, bool projected=false) const; | |
251 | void make_path(filepath& fp, bool projected=false) const; | |
252 | ||
253 | // -- version -- | |
254 | version_t get_version() const { return version; } | |
255 | void set_version(version_t v) { projected_version = version = v; } | |
256 | version_t get_projected_version() const { return projected_version; } | |
257 | void set_projected_version(version_t v) { projected_version = v; } | |
258 | ||
259 | mds_authority_t authority() const override; | |
260 | ||
261 | version_t pre_dirty(version_t min=0); | |
262 | void _mark_dirty(LogSegment *ls); | |
f67539c2 | 263 | void mark_dirty(version_t pv, LogSegment *ls); |
7c673cae FG |
264 | void mark_clean(); |
265 | ||
266 | void mark_new(); | |
267 | bool is_new() const { return state_test(STATE_NEW); } | |
268 | void clear_new() { state_clear(STATE_NEW); } | |
1e59de90 TL |
269 | |
270 | void mark_auth(); | |
271 | void clear_auth(); | |
7c673cae | 272 | |
1e59de90 TL |
273 | bool scrub(snapid_t next_seq); |
274 | ||
7c673cae FG |
275 | // -- exporting |
276 | // note: this assumes the dentry already exists. | |
277 | // i.e., the name is already extracted... so we just need the other state. | |
f67539c2 | 278 | void encode_export(ceph::buffer::list& bl) { |
9f95a23c | 279 | ENCODE_START(1, 1, bl); |
11fdf7f2 TL |
280 | encode(first, bl); |
281 | encode(state, bl); | |
282 | encode(version, bl); | |
283 | encode(projected_version, bl); | |
284 | encode(lock, bl); | |
285 | encode(get_replicas(), bl); | |
7c673cae | 286 | get(PIN_TEMPEXPORTING); |
9f95a23c | 287 | ENCODE_FINISH(bl); |
7c673cae FG |
288 | } |
289 | void finish_export() { | |
290 | // twiddle | |
291 | clear_replica_map(); | |
292 | replica_nonce = EXPORT_NONCE; | |
1e59de90 | 293 | clear_auth(); |
7c673cae FG |
294 | if (is_dirty()) |
295 | mark_clean(); | |
296 | put(PIN_TEMPEXPORTING); | |
297 | } | |
298 | void abort_export() { | |
299 | put(PIN_TEMPEXPORTING); | |
300 | } | |
f67539c2 | 301 | void decode_import(ceph::buffer::list::const_iterator& blp, LogSegment *ls) { |
9f95a23c | 302 | DECODE_START(1, blp); |
11fdf7f2 | 303 | decode(first, blp); |
7c673cae | 304 | __u32 nstate; |
11fdf7f2 TL |
305 | decode(nstate, blp); |
306 | decode(version, blp); | |
307 | decode(projected_version, blp); | |
308 | decode(lock, blp); | |
309 | decode(get_replicas(), blp); | |
7c673cae FG |
310 | |
311 | // twiddle | |
31f18b77 | 312 | state &= MASK_STATE_IMPORT_KEPT; |
1e59de90 | 313 | mark_auth(); |
7c673cae FG |
314 | if (nstate & STATE_DIRTY) |
315 | _mark_dirty(ls); | |
181888fb | 316 | if (is_replicated()) |
7c673cae FG |
317 | get(PIN_REPLICATED); |
318 | replica_nonce = 0; | |
9f95a23c | 319 | DECODE_FINISH(blp); |
7c673cae FG |
320 | } |
321 | ||
322 | // -- locking -- | |
323 | SimpleLock* get_lock(int type) override { | |
11fdf7f2 | 324 | ceph_assert(type == CEPH_LOCK_DN); |
7c673cae FG |
325 | return &lock; |
326 | } | |
327 | void set_object_info(MDSCacheObjectInfo &info) override; | |
f67539c2 TL |
328 | void encode_lock_state(int type, ceph::buffer::list& bl) override; |
329 | void decode_lock_state(int type, const ceph::buffer::list& bl) override; | |
7c673cae FG |
330 | |
331 | // --------------------------------------------- | |
332 | // replicas (on clients) | |
333 | ||
334 | bool is_any_leases() const { | |
335 | return !client_lease_map.empty(); | |
336 | } | |
337 | const ClientLease *get_client_lease(client_t c) const { | |
338 | if (client_lease_map.count(c)) | |
339 | return client_lease_map.find(c)->second; | |
340 | return 0; | |
341 | } | |
342 | ClientLease *get_client_lease(client_t c) { | |
343 | if (client_lease_map.count(c)) | |
344 | return client_lease_map.find(c)->second; | |
345 | return 0; | |
346 | } | |
347 | bool have_client_lease(client_t c) const { | |
348 | const ClientLease *l = get_client_lease(c); | |
349 | if (l) | |
350 | return true; | |
351 | else | |
352 | return false; | |
353 | } | |
354 | ||
355 | ClientLease *add_client_lease(client_t c, Session *session); | |
356 | void remove_client_lease(ClientLease *r, Locker *locker); // returns remaining mask (if any), and kicks locker eval_gathers | |
357 | void remove_client_leases(Locker *locker); | |
358 | ||
f67539c2 TL |
359 | std::ostream& print_db_line_prefix(std::ostream& out) override; |
360 | void print(std::ostream& out) override; | |
361 | void dump(ceph::Formatter *f) const; | |
7c673cae | 362 | |
f67539c2 TL |
363 | static void encode_remote(inodeno_t& ino, unsigned char d_type, |
364 | std::string_view alternate_name, | |
365 | bufferlist &bl); | |
366 | static void decode_remote(char icode, inodeno_t& ino, unsigned char& d_type, | |
367 | mempool::mds_co::string& alternate_name, | |
368 | ceph::buffer::list::const_iterator& bl); | |
7c673cae | 369 | |
7c673cae FG |
370 | __u32 hash; |
371 | snapid_t first, last; | |
1e59de90 | 372 | bool corrupt_first_loaded = false; /* for Postgres corruption detection */ |
7c673cae | 373 | |
b32b8144 | 374 | elist<CDentry*>::item item_dirty, item_dir_dirty; |
7c673cae FG |
375 | elist<CDentry*>::item item_stray; |
376 | ||
377 | // lock | |
378 | static LockType lock_type; | |
379 | static LockType versionlock_type; | |
380 | ||
94b18763 | 381 | SimpleLock lock; // FIXME referenced containers not in mempool |
f67539c2 | 382 | LocalLockC versionlock; // FIXME referenced containers not in mempool |
7c673cae | 383 | |
94b18763 | 384 | mempool::mds_co::map<client_t,ClientLease*> client_lease_map; |
9f95a23c | 385 | std::map<int, std::unique_ptr<BatchOp>> batch_ops; |
7c673cae FG |
386 | |
387 | ||
388 | protected: | |
389 | friend class Migrator; | |
390 | friend class Locker; | |
391 | friend class MDCache; | |
392 | friend class StrayManager; | |
393 | friend class CInode; | |
394 | friend class C_MDC_XlockRequest; | |
395 | ||
94b18763 | 396 | CDir *dir = nullptr; // containing dirfrag |
f67539c2 | 397 | linkage_t linkage; /* durable */ |
94b18763 FG |
398 | mempool::mds_co::list<linkage_t> projected; |
399 | ||
400 | version_t version = 0; // dir version when last touched. | |
401 | version_t projected_version = 0; // what it will be when i unlock/commit. | |
7c673cae | 402 | |
94b18763 FG |
403 | private: |
404 | mempool::mds_co::string name; | |
f67539c2 | 405 | mempool::mds_co::string alternate_name; |
7c673cae FG |
406 | }; |
407 | ||
f67539c2 | 408 | std::ostream& operator<<(std::ostream& out, const CDentry& dn); |
7c673cae FG |
409 | |
410 | ||
411 | #endif |