]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/CDentry.h
dff250bcac332f2309492a4fae84f43c36dac842
[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 const CDir *get_dir() const { return dir; }
157 CDir *get_dir() { return dir; }
158 std::string_view get_name() const { return std::string_view(name); }
159 std::string_view get_alternate_name() const {
160 return std::string_view(alternate_name);
161 }
162 void set_alternate_name(mempool::mds_co::string altn) {
163 alternate_name = std::move(altn);
164 }
165 void set_alternate_name(std::string_view altn) {
166 alternate_name = mempool::mds_co::string(altn);
167 }
168
169 __u32 get_hash() const { return hash; }
170
171 // linkage
172 const linkage_t *get_linkage() const { return &linkage; }
173 linkage_t *get_linkage() { return &linkage; }
174
175 linkage_t *_project_linkage() {
176 projected.push_back(linkage_t());
177 return &projected.back();
178 }
179 void push_projected_linkage();
180 void push_projected_linkage(inodeno_t ino, char d_type) {
181 linkage_t *p = _project_linkage();
182 p->remote_ino = ino;
183 p->remote_d_type = d_type;
184 }
185 void push_projected_linkage(CInode *inode);
186 linkage_t *pop_projected_linkage();
187
188 bool is_projected() const { return !projected.empty(); }
189
190 linkage_t *get_projected_linkage() {
191 if (!projected.empty())
192 return &projected.back();
193 return &linkage;
194 }
195
196 const linkage_t *get_projected_linkage() const {
197 if (!projected.empty())
198 return &projected.back();
199 return &linkage;
200 }
201
202 CInode *get_projected_inode() {
203 return get_projected_linkage()->inode;
204 }
205
206 bool use_projected(client_t client, const MutationRef& mut) const {
207 return lock.can_read_projected(client) ||
208 lock.get_xlock_by() == mut;
209 }
210 linkage_t *get_linkage(client_t client, const MutationRef& mut) {
211 return use_projected(client, mut) ? get_projected_linkage() : get_linkage();
212 }
213
214 // ref counts: pin ourselves in the LRU when we're pinned.
215 void first_get() override {
216 lru_pin();
217 }
218 void last_put() override {
219 lru_unpin();
220 }
221 void _put() override;
222
223 // auth pins
224 bool can_auth_pin(int *err_ret=nullptr) const override;
225 void auth_pin(void *by) override;
226 void auth_unpin(void *by) override;
227 void adjust_nested_auth_pins(int diradj, void *by);
228 bool is_frozen() const override;
229 bool is_freezing() const override;
230 int get_num_dir_auth_pins() const;
231
232 // remote links
233 void link_remote(linkage_t *dnl, CInode *in);
234 void unlink_remote(linkage_t *dnl);
235
236 // copy cons
237 CDentry(const CDentry& m);
238 const CDentry& operator= (const CDentry& right);
239
240 // misc
241 void make_path_string(std::string& s, bool projected=false) const;
242 void make_path(filepath& fp, bool projected=false) const;
243
244 // -- version --
245 version_t get_version() const { return version; }
246 void set_version(version_t v) { projected_version = version = v; }
247 version_t get_projected_version() const { return projected_version; }
248 void set_projected_version(version_t v) { projected_version = v; }
249
250 mds_authority_t authority() const override;
251
252 version_t pre_dirty(version_t min=0);
253 void _mark_dirty(LogSegment *ls);
254 void mark_dirty(version_t pv, LogSegment *ls);
255 void mark_clean();
256
257 void mark_new();
258 bool is_new() const { return state_test(STATE_NEW); }
259 void clear_new() { state_clear(STATE_NEW); }
260
261 // -- exporting
262 // note: this assumes the dentry already exists.
263 // i.e., the name is already extracted... so we just need the other state.
264 void encode_export(ceph::buffer::list& bl) {
265 ENCODE_START(1, 1, bl);
266 encode(first, bl);
267 encode(state, bl);
268 encode(version, bl);
269 encode(projected_version, bl);
270 encode(lock, bl);
271 encode(get_replicas(), bl);
272 get(PIN_TEMPEXPORTING);
273 ENCODE_FINISH(bl);
274 }
275 void finish_export() {
276 // twiddle
277 clear_replica_map();
278 replica_nonce = EXPORT_NONCE;
279 state_clear(CDentry::STATE_AUTH);
280 if (is_dirty())
281 mark_clean();
282 put(PIN_TEMPEXPORTING);
283 }
284 void abort_export() {
285 put(PIN_TEMPEXPORTING);
286 }
287 void decode_import(ceph::buffer::list::const_iterator& blp, LogSegment *ls) {
288 DECODE_START(1, blp);
289 decode(first, blp);
290 __u32 nstate;
291 decode(nstate, blp);
292 decode(version, blp);
293 decode(projected_version, blp);
294 decode(lock, blp);
295 decode(get_replicas(), blp);
296
297 // twiddle
298 state &= MASK_STATE_IMPORT_KEPT;
299 state_set(CDentry::STATE_AUTH);
300 if (nstate & STATE_DIRTY)
301 _mark_dirty(ls);
302 if (is_replicated())
303 get(PIN_REPLICATED);
304 replica_nonce = 0;
305 DECODE_FINISH(blp);
306 }
307
308 // -- locking --
309 SimpleLock* get_lock(int type) override {
310 ceph_assert(type == CEPH_LOCK_DN);
311 return &lock;
312 }
313 void set_object_info(MDSCacheObjectInfo &info) override;
314 void encode_lock_state(int type, ceph::buffer::list& bl) override;
315 void decode_lock_state(int type, const ceph::buffer::list& bl) override;
316
317 // ---------------------------------------------
318 // replicas (on clients)
319
320 bool is_any_leases() const {
321 return !client_lease_map.empty();
322 }
323 const ClientLease *get_client_lease(client_t c) const {
324 if (client_lease_map.count(c))
325 return client_lease_map.find(c)->second;
326 return 0;
327 }
328 ClientLease *get_client_lease(client_t c) {
329 if (client_lease_map.count(c))
330 return client_lease_map.find(c)->second;
331 return 0;
332 }
333 bool have_client_lease(client_t c) const {
334 const ClientLease *l = get_client_lease(c);
335 if (l)
336 return true;
337 else
338 return false;
339 }
340
341 ClientLease *add_client_lease(client_t c, Session *session);
342 void remove_client_lease(ClientLease *r, Locker *locker); // returns remaining mask (if any), and kicks locker eval_gathers
343 void remove_client_leases(Locker *locker);
344
345 std::ostream& print_db_line_prefix(std::ostream& out) override;
346 void print(std::ostream& out) override;
347 void dump(ceph::Formatter *f) const;
348
349 static void encode_remote(inodeno_t& ino, unsigned char d_type,
350 std::string_view alternate_name,
351 bufferlist &bl);
352 static void decode_remote(char icode, inodeno_t& ino, unsigned char& d_type,
353 mempool::mds_co::string& alternate_name,
354 ceph::buffer::list::const_iterator& bl);
355
356 __u32 hash;
357 snapid_t first, last;
358
359 elist<CDentry*>::item item_dirty, item_dir_dirty;
360 elist<CDentry*>::item item_stray;
361
362 // lock
363 static LockType lock_type;
364 static LockType versionlock_type;
365
366 SimpleLock lock; // FIXME referenced containers not in mempool
367 LocalLockC versionlock; // FIXME referenced containers not in mempool
368
369 mempool::mds_co::map<client_t,ClientLease*> client_lease_map;
370 std::map<int, std::unique_ptr<BatchOp>> batch_ops;
371
372
373 protected:
374 friend class Migrator;
375 friend class Locker;
376 friend class MDCache;
377 friend class StrayManager;
378 friend class CInode;
379 friend class C_MDC_XlockRequest;
380
381 CDir *dir = nullptr; // containing dirfrag
382 linkage_t linkage; /* durable */
383 mempool::mds_co::list<linkage_t> projected;
384
385 version_t version = 0; // dir version when last touched.
386 version_t projected_version = 0; // what it will be when i unlock/commit.
387
388 private:
389 mempool::mds_co::string name;
390 mempool::mds_co::string alternate_name;
391 };
392
393 std::ostream& operator<<(std::ostream& out, const CDentry& dn);
394
395
396 #endif