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