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