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