Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / StrayManager.h
1 // vim: ts=8 sw=2 smarttab
2 /*
3  * Ceph - scalable distributed file system
4  *
5  * Copyright (C) 2015 Red Hat
6  *
7  * This is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License version 2.1, as published by the Free Software 
10  * Foundation.  See file COPYING.
11  * 
12  */
13
14 #ifndef STRAY_MANAGER_H
15 #define STRAY_MANAGER_H
16
17 #include "include/elist.h"
18 #include <list>
19 #include "mds/PurgeQueue.h"
20
21 class MDSRank;
22 class PerfCounters;
23 class CInode;
24 class CDentry;
25
26 class StrayManager
27 {
28   protected:
29   // Has passed through eval_stray and still has refs
30   elist<CDentry*> delayed_eval_stray;
31
32   // strays that have been trimmed from cache
33   std::set<std::string> trimmed_strays;
34
35   // Global references for doing I/O
36   MDSRank *mds;
37   PerfCounters *logger;
38
39   bool started;
40
41   // Stray dentries for this rank (including those not in cache)
42   uint64_t num_strays;
43
44   // Stray dentries
45   uint64_t num_strays_delayed;
46
47   // Entries that have entered enqueue() but not been persistently
48   // recorded by PurgeQueue yet
49   uint64_t num_strays_enqueuing;
50
51   PurgeQueue &purge_queue;
52
53   void truncate(CDentry *dn);
54
55   /**
56    * Purge a dentry from a stray directory.  This function
57    * is called once eval_stray is satisfied and StrayManager
58    * throttling is also satisfied.  There is no going back
59    * at this stage!
60    */
61   void purge(CDentry *dn);
62
63   /**
64    * Completion handler for a Filer::purge on a stray inode.
65    */
66   void _purge_stray_purged(CDentry *dn, bool only_head);
67
68   void _purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls);
69
70   /**
71    * Callback: we have logged the update to an inode's metadata
72    * reflecting it's newly-zeroed length.
73    */
74   void _truncate_stray_logged(CDentry *dn, LogSegment *ls);
75
76   friend class StrayManagerIOContext;
77   friend class StrayManagerLogContext;
78   friend class StrayManagerContext;
79
80   friend class C_StraysFetched;
81   friend class C_OpenSnapParents;
82   friend class C_PurgeStrayLogged;
83   friend class C_TruncateStrayLogged;
84   friend class C_IO_PurgeStrayPurged;
85
86
87   // Call this on a dentry that has been identified as
88   // elegible for purging.  It will be passed on to PurgeQueue.
89   void enqueue(CDentry *dn, bool trunc);
90
91   // Final part of enqueue() which we may have to retry
92   // after opening snap parents.
93   void _enqueue(CDentry *dn, bool trunc);
94
95
96   /**
97    * When hard links exist to an inode whose primary dentry
98    * is unlinked, the inode gets a stray primary dentry.
99    *
100    * We may later "reintegrate" the inode into a remaining
101    * non-stray dentry (one of what was previously a remote
102    * dentry) by issuing a rename from the stray to the other
103    * dentry.
104    */
105   void reintegrate_stray(CDentry *dn, CDentry *rlink);
106
107   /**
108    * Evaluate a stray dentry for purging or reintegration.
109    *
110    * purging: If the inode has no linkage, and no more references, then
111    *          we may decide to purge it.
112    *
113    * reintegration: If the inode still has linkage, then it means someone else
114    *                (a hard link) is still referring to it, and we should
115    *                think about reintegrating that inode into the remote dentry.
116    *
117    * @returns true if the dentry will be purged (caller should never
118    *          take more refs after this happens), else false.
119    */
120   bool _eval_stray(CDentry *dn, bool delay=false);
121
122   void _eval_stray_remote(CDentry *stray_dn, CDentry *remote_dn);
123
124   // My public interface is for consumption by MDCache
125   public:
126   explicit StrayManager(MDSRank *mds, PurgeQueue &purge_queue_);
127   void set_logger(PerfCounters *l) {logger = l;}
128   void activate();
129
130   bool eval_stray(CDentry *dn, bool delay=false);
131
132   void set_num_strays(uint64_t num);
133   uint64_t get_num_strays() const { return num_strays; }
134
135   /**
136    * Where eval_stray was previously invoked with delay=true, call
137    * eval_stray again for any dentries that were put on the
138    * delayed_eval_stray list as a result of the original call.
139    *
140    * Used so that various places can call eval_stray(delay=true) during
141    * an operation to identify dentries of interest, and then call
142    * this function later during trim in order to do the final
143    * evaluation (and resulting actions) while not in the middle of another
144    * metadata operation.
145    */
146   void advance_delayed();
147
148   /**
149    * Remote dentry potentially points to a stray. When it is touched,
150    * call in here to evaluate it for migration (move a stray residing
151    * on another MDS to this MDS) or reintegration (move a stray dentry's
152    * inode into a non-stray hardlink dentry and clean up the stray).
153    *
154    * @param stray_dn a stray dentry whose inode has been referenced
155    *                 by a remote dentry
156    * @param remote_dn (optional) which remote dentry was touched
157    *                  in an operation that led us here: this is used
158    *                  as a hint for which remote to reintegrate into
159    *                  if there are multiple remotes.
160    */
161   void eval_remote(CDentry *remote_dn);
162
163   /**
164    * Given a dentry within one of my stray directories,
165    * send it off to a stray directory in another MDS.
166    *
167    * This is for use:
168    *  * Case A: when shutting down a rank, we migrate strays
169    *    away from ourselves rather than waiting for purge
170    *  * Case B: when a client request has a trace that refers to
171    *    a stray inode on another MDS, we migrate that inode from
172    *    there to here, in order that we can later re-integrate it
173    *    here.
174    *
175    * In case B, the receiver should be calling into eval_stray
176    * on completion of mv (i.e. inode put), resulting in a subsequent
177    * reintegration.
178    */
179   void migrate_stray(CDentry *dn, mds_rank_t dest);
180
181   /**
182    * Update stats to reflect a newly created stray dentry.  Needed
183    * because stats on strays live here, but creation happens
184    * in Server or MDCache.  For our purposes "creation" includes
185    * loading a stray from a dirfrag and migrating a stray from
186    * another MDS, in addition to creations per-se.
187    */
188   void notify_stray_created();
189
190   /**
191    * Update stats to reflect a removed stray dentry.  Needed because
192    * stats on strays live here, but removal happens in Server or
193    * MDCache.  Also includes migration (rename) of strays from
194    * this MDS to another MDS.
195    */
196   void notify_stray_removed();
197 };
198
199 #endif  // STRAY_MANAGER_H