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