]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/Migrator.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / mds / Migrator.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.
12 *
13 * Handles the import and export of mds authorities and actual cache data.
14 * See src/doc/exports.txt for a description.
15 */
16
17#ifndef CEPH_MDS_MIGRATOR_H
18#define CEPH_MDS_MIGRATOR_H
19
20#include "include/types.h"
21
22#include <map>
23#include <list>
24#include <set>
25using std::map;
26using std::list;
27using std::set;
28
29
30class MDSRank;
31class CDir;
32class CInode;
33class CDentry;
34
35class MExportDirDiscover;
36class MExportDirDiscoverAck;
37class MExportDirCancel;
38class MExportDirPrep;
39class MExportDirPrepAck;
40class MExportDir;
41class MExportDirAck;
42class MExportDirNotify;
43class MExportDirNotifyAck;
44class MExportDirFinish;
45
46class MExportCaps;
47class MExportCapsAck;
48class MGatherCaps;
49
50class EImportStart;
51
52class Migrator {
53public:
54 // export stages. used to clean up intelligently if there's a failure.
55 const static int EXPORT_CANCELLED = 0; // cancelled
56 const static int EXPORT_CANCELLING = 1; // waiting for cancel notifyacks
57 const static int EXPORT_LOCKING = 2; // acquiring locks
58 const static int EXPORT_DISCOVERING = 3; // dest is disovering export dir
59 const static int EXPORT_FREEZING = 4; // we're freezing the dir tree
60 const static int EXPORT_PREPPING = 5; // sending dest spanning tree to export bounds
61 const static int EXPORT_WARNING = 6; // warning bystanders of dir_auth_pending
62 const static int EXPORT_EXPORTING = 7; // sent actual export, waiting for ack
63 const static int EXPORT_LOGGINGFINISH = 8; // logging EExportFinish
64 const static int EXPORT_NOTIFYING = 9; // waiting for notifyacks
65 static const char *get_export_statename(int s) {
66 switch (s) {
67 case EXPORT_CANCELLING: return "cancelling";
68 case EXPORT_LOCKING: return "locking";
69 case EXPORT_DISCOVERING: return "discovering";
70 case EXPORT_FREEZING: return "freezing";
71 case EXPORT_PREPPING: return "prepping";
72 case EXPORT_WARNING: return "warning";
73 case EXPORT_EXPORTING: return "exporting";
74 case EXPORT_LOGGINGFINISH: return "loggingfinish";
75 case EXPORT_NOTIFYING: return "notifying";
76 default: ceph_abort(); return 0;
77 }
78 }
79
80 // -- imports --
81 const static int IMPORT_DISCOVERING = 1; // waiting for prep
82 const static int IMPORT_DISCOVERED = 2; // waiting for prep
83 const static int IMPORT_PREPPING = 3; // opening dirs on bounds
84 const static int IMPORT_PREPPED = 4; // opened bounds, waiting for import
85 const static int IMPORT_LOGGINGSTART = 5; // got import, logging EImportStart
86 const static int IMPORT_ACKING = 6; // logged EImportStart, sent ack, waiting for finish
87 const static int IMPORT_FINISHING = 7; // sent cap imports, waiting for finish
88 const static int IMPORT_ABORTING = 8; // notifying bystanders of an abort before unfreezing
89 static const char *get_import_statename(int s) {
90 switch (s) {
91 case IMPORT_DISCOVERING: return "discovering";
92 case IMPORT_DISCOVERED: return "discovered";
93 case IMPORT_PREPPING: return "prepping";
94 case IMPORT_PREPPED: return "prepped";
95 case IMPORT_LOGGINGSTART: return "loggingstart";
96 case IMPORT_ACKING: return "acking";
97 case IMPORT_FINISHING: return "finishing";
98 case IMPORT_ABORTING: return "aborting";
99 default: ceph_abort(); return 0;
100 }
101 }
102
103 // -- cons --
104 Migrator(MDSRank *m, MDCache *c) : mds(m), cache(c) {}
105
106
107
108protected:
109 // export fun
110 struct export_state_t {
111 int state;
112 mds_rank_t peer;
113 uint64_t tid;
114 set<mds_rank_t> warning_ack_waiting;
115 set<mds_rank_t> notify_ack_waiting;
116 map<inodeno_t,map<client_t,Capability::Import> > peer_imported;
117 MutationRef mut;
118 // for freeze tree deadlock detection
119 utime_t last_cum_auth_pins_change;
120 int last_cum_auth_pins;
121 int num_remote_waiters; // number of remote authpin waiters
122 export_state_t() : state(0), peer(0), tid(0), mut(),
123 last_cum_auth_pins(0), num_remote_waiters(0) {}
124 };
125
126 map<CDir*, export_state_t> export_state;
127
128 list<pair<dirfrag_t,mds_rank_t> > export_queue;
129
130 // import fun
131 struct import_state_t {
132 int state;
133 mds_rank_t peer;
134 uint64_t tid;
135 set<mds_rank_t> bystanders;
136 list<dirfrag_t> bound_ls;
137 list<ScatterLock*> updated_scatterlocks;
138 map<client_t,entity_inst_t> client_map;
139 map<CInode*, map<client_t,Capability::Export> > peer_exports;
140 MutationRef mut;
141 import_state_t() : state(0), peer(0), tid(0), mut() {}
142 };
143
144 map<dirfrag_t, import_state_t> import_state;
145
146 void handle_export_discover_ack(MExportDirDiscoverAck *m);
147 void export_frozen(CDir *dir, uint64_t tid);
148 void handle_export_prep_ack(MExportDirPrepAck *m);
149 void export_sessions_flushed(CDir *dir, uint64_t tid);
150 void export_go(CDir *dir);
151 void export_go_synced(CDir *dir, uint64_t tid);
152 void export_try_cancel(CDir *dir, bool notify_peer=true);
153 void export_cancel_finish(CDir *dir);
154 void export_reverse(CDir *dir);
155 void export_notify_abort(CDir *dir, set<CDir*>& bounds);
156 void handle_export_ack(MExportDirAck *m);
157 void export_logged_finish(CDir *dir);
158 void handle_export_notify_ack(MExportDirNotifyAck *m);
159 void export_finish(CDir *dir);
160
161 void handle_gather_caps(MGatherCaps *m);
162
163 friend class C_MDC_ExportFreeze;
164 friend class C_MDS_ExportFinishLogged;
165 friend class C_M_ExportGo;
166 friend class C_M_ExportSessionsFlushed;
167 friend class MigratorContext;
168 friend class MigratorLogContext;
169
170 // importer
171 void handle_export_discover(MExportDirDiscover *m);
172 void handle_export_cancel(MExportDirCancel *m);
173 void handle_export_prep(MExportDirPrep *m);
174 void handle_export_dir(MExportDir *m);
175
176 void import_reverse_discovering(dirfrag_t df);
177 void import_reverse_discovered(dirfrag_t df, CInode *diri);
178 void import_reverse_prepping(CDir *dir);
179 void import_remove_pins(CDir *dir, set<CDir*>& bounds);
180 void import_reverse_unfreeze(CDir *dir);
181 void import_reverse_final(CDir *dir);
182 void import_notify_abort(CDir *dir, set<CDir*>& bounds);
183 void import_notify_finish(CDir *dir, set<CDir*>& bounds);
184 void import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from,
185 map<client_t,entity_inst_t> &imported_client_map,
186 map<client_t,uint64_t>& sseqmap);
187 void handle_export_finish(MExportDirFinish *m);
188
189 void handle_export_caps(MExportCaps *m);
190 void logged_import_caps(CInode *in,
191 mds_rank_t from,
192 map<CInode*, map<client_t,Capability::Export> >& cap_imports,
193 map<client_t,entity_inst_t>& client_map,
194 map<client_t,uint64_t>& sseqmap);
195
196
197 friend class C_MDS_ImportDirLoggedStart;
198 friend class C_MDS_ImportDirLoggedFinish;
199 friend class C_M_LoggedImportCaps;
200
201 // bystander
202 void handle_export_notify(MExportDirNotify *m);
203
204
205public:
206
207 void dispatch(Message*);
208
209 void show_importing();
210 void show_exporting();
211
212 int get_num_exporting() const { return export_state.size(); }
213 int get_export_queue_size() const { return export_queue.size(); }
214
215 // -- status --
216 int is_exporting(CDir *dir) const {
217 map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
218 if (it != export_state.end()) return it->second.state;
219 return 0;
220 }
221 bool is_exporting() const { return !export_state.empty(); }
222 int is_importing(dirfrag_t df) const {
223 map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
224 if (it != import_state.end()) return it->second.state;
225 return 0;
226 }
227 bool is_importing() const { return !import_state.empty(); }
228
229 bool is_ambiguous_import(dirfrag_t df) const {
230 map<dirfrag_t, import_state_t>::const_iterator p = import_state.find(df);
231 if (p == import_state.end())
232 return false;
233 if (p->second.state >= IMPORT_LOGGINGSTART &&
234 p->second.state < IMPORT_ABORTING)
235 return true;
236 return false;
237 }
238
239 int get_import_state(dirfrag_t df) const {
240 map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
241 assert(it != import_state.end());
242 return it->second.state;
243 }
244 int get_import_peer(dirfrag_t df) const {
245 map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
246 assert(it != import_state.end());
247 return it->second.peer;
248 }
249
250 int get_export_state(CDir *dir) const {
251 map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
252 assert(it != export_state.end());
253 return it->second.state;
254 }
255 // this returns true if we are export @dir,
256 // and are not waiting for @who to be
257 // be warned of ambiguous auth.
258 // only returns meaningful results during EXPORT_WARNING state.
259 bool export_has_warned(CDir *dir, mds_rank_t who) {
260 map<CDir*, export_state_t>::iterator it = export_state.find(dir);
261 assert(it != export_state.end());
262 assert(it->second.state == EXPORT_WARNING);
263 return (it->second.warning_ack_waiting.count(who) == 0);
264 }
265
266 bool export_has_notified(CDir *dir, mds_rank_t who) const {
267 map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
268 assert(it != export_state.end());
269 assert(it->second.state == EXPORT_NOTIFYING);
270 return (it->second.notify_ack_waiting.count(who) == 0);
271 }
272
273 void export_freeze_inc_num_waiters(CDir *dir) {
274 map<CDir*, export_state_t>::iterator it = export_state.find(dir);
275 assert(it != export_state.end());
276 it->second.num_remote_waiters++;
277 }
278 void find_stale_export_freeze();
279
280 // -- misc --
281 void handle_mds_failure_or_stop(mds_rank_t who);
282
283 void audit();
284
285 // -- import/export --
286 // exporter
287 void dispatch_export_dir(MDRequestRef& mdr, int count);
288 void export_dir(CDir *dir, mds_rank_t dest);
289 void export_empty_import(CDir *dir);
290
291 void export_dir_nicely(CDir *dir, mds_rank_t dest);
292 void maybe_do_queued_export();
293 void clear_export_queue() {
294 export_queue.clear();
295 }
296
297 void get_export_lock_set(CDir *dir, set<SimpleLock*>& locks);
298 void get_export_client_set(CDir *dir, set<client_t> &client_set);
299 void get_export_client_set(CInode *in, set<client_t> &client_set);
300
301 void encode_export_inode(CInode *in, bufferlist& bl,
302 map<client_t,entity_inst_t>& exported_client_map);
303 void encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl,
304 map<client_t,entity_inst_t>& exported_client_map);
305 void finish_export_inode(CInode *in, utime_t now, mds_rank_t target,
306 map<client_t,Capability::Import>& peer_imported,
307 list<MDSInternalContextBase*>& finished);
308 void finish_export_inode_caps(CInode *in, mds_rank_t target,
309 map<client_t,Capability::Import>& peer_imported);
310
311
312 uint64_t encode_export_dir(bufferlist& exportbl,
313 CDir *dir,
314 map<client_t,entity_inst_t>& exported_client_map,
315 utime_t now);
316 void finish_export_dir(CDir *dir, utime_t now, mds_rank_t target,
317 map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
318 list<MDSInternalContextBase*>& finished, int *num_dentries);
319
320 void clear_export_proxy_pins(CDir *dir);
321
322 void export_caps(CInode *in);
323
324 void decode_import_inode(CDentry *dn, bufferlist::iterator& blp,
325 mds_rank_t oldauth, LogSegment *ls,
326 map<CInode*, map<client_t,Capability::Export> >& cap_imports,
327 list<ScatterLock*>& updated_scatterlocks);
328 void decode_import_inode_caps(CInode *in, bool auth_cap, bufferlist::iterator &blp,
329 map<CInode*, map<client_t,Capability::Export> >& cap_imports);
330 void finish_import_inode_caps(CInode *in, mds_rank_t from, bool auth_cap,
331 map<client_t,Capability::Export> &export_map,
332 map<client_t,Capability::Import> &import_map);
333 int decode_import_dir(bufferlist::iterator& blp,
334 mds_rank_t oldauth,
335 CDir *import_root,
336 EImportStart *le,
337 LogSegment *ls,
338 map<CInode*, map<client_t,Capability::Export> >& cap_imports,
339 list<ScatterLock*>& updated_scatterlocks, utime_t now);
340
341 void import_reverse(CDir *dir);
342
343 void import_finish(CDir *dir, bool notify, bool last=true);
344
345private:
346 MDSRank *mds;
347 MDCache *cache;
348};
349
350#endif