]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/CDentry.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / mds / CDentry.h
CommitLineData
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
37class CInode;
38class CDir;
39class Locker;
7c673cae
FG
40class CDentry;
41class LogSegment;
42
43class Session;
44
7c673cae
FG
45// define an ordering
46bool operator<(const CDentry& l, const CDentry& r);
47
48// dentry
49class CDentry : public MDSCacheObject, public LRUObject, public Counter<CDentry> {
50public:
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
388protected:
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
403private:
404 mempool::mds_co::string name;
f67539c2 405 mempool::mds_co::string alternate_name;
7c673cae
FG
406};
407
f67539c2 408std::ostream& operator<<(std::ostream& out, const CDentry& dn);
7c673cae
FG
409
410
411#endif