]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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, uint32_t ops, 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 | ||
31f18b77 FG |
122 | void _eval_stray_remote(CDentry *stray_dn, CDentry *remote_dn); |
123 | ||
7c673cae FG |
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 | /** | |
31f18b77 FG |
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). | |
7c673cae FG |
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 | */ | |
31f18b77 | 161 | void eval_remote(CDentry *remote_dn); |
7c673cae FG |
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 |