]>
Commit | Line | Data |
---|---|---|
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 | */ | |
14 | ||
15 | #include "SnapServer.h" | |
16 | #include "MDSRank.h" | |
17 | #include "osd/OSDMap.h" | |
18 | #include "osdc/Objecter.h" | |
19 | #include "mon/MonClient.h" | |
20 | ||
21 | #include "include/types.h" | |
22 | #include "messages/MMDSTableRequest.h" | |
23 | #include "messages/MRemoveSnaps.h" | |
24 | ||
25 | #include "msg/Messenger.h" | |
26 | ||
27 | #include "common/config.h" | |
28 | #include "include/assert.h" | |
29 | ||
30 | #define dout_context g_ceph_context | |
31 | #define dout_subsys ceph_subsys_mds | |
32 | #undef dout_prefix | |
33 | #define dout_prefix *_dout << "mds." << rank << ".snap " | |
34 | ||
35 | ||
36 | void SnapServer::reset_state() | |
37 | { | |
38 | last_snap = 1; /* snapid 1 reserved for initial root snaprealm */ | |
39 | snaps.clear(); | |
40 | need_to_purge.clear(); | |
41 | ||
42 | // find any removed snapshot in data pools | |
43 | if (mds) { // only if I'm running in a live MDS | |
44 | snapid_t first_free = 0; | |
45 | mds->objecter->with_osdmap([&](const OSDMap& o) { | |
46 | for (const auto p : mds->mdsmap->get_data_pools()) { | |
47 | const pg_pool_t *pi = o.get_pg_pool(p); | |
48 | if (!pi) { | |
49 | // If pool isn't in OSDMap yet then can't have any snaps | |
50 | // needing removal, skip. | |
51 | continue; | |
52 | } | |
53 | if (!pi->removed_snaps.empty() && | |
54 | pi->removed_snaps.range_end() > first_free) | |
55 | first_free = pi->removed_snaps.range_end(); | |
56 | } | |
57 | }); | |
58 | if (first_free > last_snap) | |
59 | last_snap = first_free; | |
60 | } | |
61 | } | |
62 | ||
63 | ||
64 | // SERVER | |
65 | ||
66 | void SnapServer::_prepare(bufferlist &bl, uint64_t reqid, mds_rank_t bymds) | |
67 | { | |
68 | bufferlist::iterator p = bl.begin(); | |
69 | __u32 op; | |
70 | ::decode(op, p); | |
71 | ||
72 | switch (op) { | |
73 | case TABLE_OP_CREATE: | |
74 | { | |
75 | version++; | |
76 | ||
77 | SnapInfo info; | |
78 | ::decode(info.ino, p); | |
79 | if (!p.end()) { | |
80 | ::decode(info.name, p); | |
81 | ::decode(info.stamp, p); | |
82 | info.snapid = ++last_snap; | |
83 | info.long_name = "create"; | |
84 | pending_update[version] = info; | |
85 | dout(10) << "prepare v" << version << " create " << info << dendl; | |
86 | } else { | |
87 | pending_noop.insert(version); | |
88 | dout(10) << "prepare v" << version << " noop" << dendl; | |
89 | } | |
90 | bl.clear(); | |
91 | ::encode(last_snap, bl); | |
92 | } | |
93 | break; | |
94 | ||
95 | case TABLE_OP_DESTROY: | |
96 | { | |
97 | inodeno_t ino; | |
98 | snapid_t snapid; | |
99 | ::decode(ino, p); // not used, currently. | |
100 | ::decode(snapid, p); | |
101 | version++; | |
102 | ||
103 | // bump last_snap... we use it as a version value on the snaprealm. | |
104 | ++last_snap; | |
105 | ||
106 | pending_destroy[version] = pair<snapid_t,snapid_t>(snapid, last_snap); | |
107 | dout(10) << "prepare v" << version << " destroy " << snapid << " seq " << last_snap << dendl; | |
108 | ||
109 | bl.clear(); | |
110 | ::encode(last_snap, bl); | |
111 | } | |
112 | break; | |
113 | ||
114 | case TABLE_OP_UPDATE: | |
115 | { | |
116 | SnapInfo info; | |
117 | ::decode(info.ino, p); | |
118 | ::decode(info.snapid, p); | |
119 | ::decode(info.name, p); | |
120 | ::decode(info.stamp, p); | |
121 | info.long_name = "update"; | |
122 | ||
123 | version++; | |
124 | // bump last_snap... we use it as a version value on the snaprealm. | |
125 | ++last_snap; | |
126 | pending_update[version] = info; | |
127 | dout(10) << "prepare v" << version << " update " << info << dendl; | |
128 | ||
129 | bl.clear(); | |
130 | ::encode(last_snap, bl); | |
131 | } | |
132 | break; | |
133 | ||
134 | default: | |
135 | ceph_abort(); | |
136 | } | |
137 | //dump(); | |
138 | } | |
139 | ||
140 | bool SnapServer::_is_prepared(version_t tid) const | |
141 | { | |
142 | return | |
143 | pending_update.count(tid) || | |
144 | pending_destroy.count(tid); | |
145 | } | |
146 | ||
147 | bool SnapServer::_commit(version_t tid, MMDSTableRequest *req) | |
148 | { | |
149 | if (pending_update.count(tid)) { | |
150 | SnapInfo &info = pending_update[tid]; | |
151 | string opname; | |
152 | if (info.long_name.empty()) | |
153 | opname = "create"; | |
154 | else | |
155 | opname.swap(info.long_name); | |
156 | if (info.stamp == utime_t() && snaps.count(info.snapid)) | |
157 | info.stamp = snaps[info.snapid].stamp; | |
158 | dout(7) << "commit " << tid << " " << opname << " " << info << dendl; | |
159 | snaps[info.snapid] = info; | |
160 | pending_update.erase(tid); | |
161 | } | |
162 | ||
163 | else if (pending_destroy.count(tid)) { | |
164 | snapid_t sn = pending_destroy[tid].first; | |
165 | snapid_t seq = pending_destroy[tid].second; | |
166 | dout(7) << "commit " << tid << " destroy " << sn << " seq " << seq << dendl; | |
167 | snaps.erase(sn); | |
168 | ||
31f18b77 FG |
169 | for (const auto p : mds->mdsmap->get_data_pools()) { |
170 | need_to_purge[p].insert(sn); | |
171 | need_to_purge[p].insert(seq); | |
7c673cae FG |
172 | } |
173 | ||
174 | pending_destroy.erase(tid); | |
175 | } | |
176 | else if (pending_noop.count(tid)) { | |
177 | dout(7) << "commit " << tid << " noop" << dendl; | |
178 | pending_noop.erase(tid); | |
179 | } | |
180 | else | |
181 | ceph_abort(); | |
182 | ||
183 | // bump version. | |
184 | version++; | |
185 | //dump(); | |
186 | return true; | |
187 | } | |
188 | ||
189 | void SnapServer::_rollback(version_t tid) | |
190 | { | |
191 | if (pending_update.count(tid)) { | |
192 | SnapInfo &info = pending_update[tid]; | |
193 | string opname; | |
194 | if (info.long_name.empty()) | |
195 | opname = "create"; | |
196 | else | |
197 | opname.swap(info.long_name); | |
198 | dout(7) << "rollback " << tid << " " << opname << " " << info << dendl; | |
199 | pending_update.erase(tid); | |
200 | } | |
201 | ||
202 | else if (pending_destroy.count(tid)) { | |
203 | dout(7) << "rollback " << tid << " destroy " << pending_destroy[tid] << dendl; | |
204 | pending_destroy.erase(tid); | |
205 | } | |
206 | ||
207 | else if (pending_noop.count(tid)) { | |
208 | dout(7) << "rollback " << tid << " noop" << dendl; | |
209 | pending_noop.erase(tid); | |
210 | } | |
211 | ||
212 | else | |
213 | ceph_abort(); | |
214 | ||
215 | // bump version. | |
216 | version++; | |
217 | //dump(); | |
218 | } | |
219 | ||
220 | void SnapServer::_server_update(bufferlist& bl) | |
221 | { | |
222 | bufferlist::iterator p = bl.begin(); | |
223 | map<int, vector<snapid_t> > purge; | |
224 | ::decode(purge, p); | |
225 | ||
226 | dout(7) << "_server_update purged " << purge << dendl; | |
227 | for (map<int, vector<snapid_t> >::iterator p = purge.begin(); | |
228 | p != purge.end(); | |
229 | ++p) { | |
230 | for (vector<snapid_t>::iterator q = p->second.begin(); | |
231 | q != p->second.end(); | |
232 | ++q) | |
233 | need_to_purge[p->first].erase(*q); | |
234 | if (need_to_purge[p->first].empty()) | |
235 | need_to_purge.erase(p->first); | |
236 | } | |
237 | ||
238 | version++; | |
239 | } | |
240 | ||
241 | void SnapServer::handle_query(MMDSTableRequest *req) | |
242 | { | |
243 | req->put(); | |
244 | } | |
245 | ||
246 | ||
247 | ||
248 | void SnapServer::check_osd_map(bool force) | |
249 | { | |
250 | if (!force && version == last_checked_osdmap) { | |
251 | dout(10) << "check_osd_map - version unchanged" << dendl; | |
252 | return; | |
253 | } | |
254 | dout(10) << "check_osd_map need_to_purge=" << need_to_purge << dendl; | |
255 | ||
256 | map<int, vector<snapid_t> > all_purge; | |
257 | map<int, vector<snapid_t> > all_purged; | |
258 | ||
259 | mds->objecter->with_osdmap( | |
260 | [this, &all_purged, &all_purge](const OSDMap& osdmap) { | |
261 | for (const auto& p : need_to_purge) { | |
262 | int id = p.first; | |
263 | const pg_pool_t *pi = osdmap.get_pg_pool(id); | |
264 | if (pi == NULL) { | |
265 | // The pool is gone. So are the snapshots. | |
266 | all_purged[id] = std::vector<snapid_t>(p.second.begin(), | |
267 | p.second.end()); | |
268 | continue; | |
269 | } | |
270 | ||
271 | for (const auto& q : p.second) { | |
272 | if (pi->is_removed_snap(q)) { | |
273 | dout(10) << " osdmap marks " << q << " as removed" << dendl; | |
274 | all_purged[id].push_back(q); | |
275 | } else { | |
276 | all_purge[id].push_back(q); | |
277 | } | |
278 | } | |
279 | } | |
280 | }); | |
281 | ||
282 | if (!all_purged.empty()) { | |
283 | // prepare to remove from need_to_purge list | |
284 | bufferlist bl; | |
285 | ::encode(all_purged, bl); | |
286 | do_server_update(bl); | |
287 | } | |
288 | ||
289 | if (!all_purge.empty()) { | |
290 | dout(10) << "requesting removal of " << all_purge << dendl; | |
291 | MRemoveSnaps *m = new MRemoveSnaps(all_purge); | |
292 | mon_client->send_mon_message(m); | |
293 | } | |
294 | ||
295 | last_checked_osdmap = version; | |
296 | } | |
297 | ||
298 | ||
299 | void SnapServer::dump(Formatter *f) const | |
300 | { | |
301 | f->open_object_section("snapserver"); | |
302 | ||
303 | f->dump_int("last_snap", last_snap.val); | |
304 | ||
305 | f->open_array_section("pending_noop"); | |
306 | for(set<version_t>::const_iterator i = pending_noop.begin(); i != pending_noop.end(); ++i) { | |
307 | f->dump_unsigned("version", *i); | |
308 | } | |
309 | f->close_section(); | |
310 | ||
311 | f->open_array_section("snaps"); | |
312 | for (map<snapid_t, SnapInfo>::const_iterator i = snaps.begin(); i != snaps.end(); ++i) { | |
313 | f->open_object_section("snap"); | |
314 | i->second.dump(f); | |
315 | f->close_section(); | |
316 | } | |
317 | f->close_section(); | |
318 | ||
319 | f->open_object_section("need_to_purge"); | |
320 | for (map<int, set<snapid_t> >::const_iterator i = need_to_purge.begin(); i != need_to_purge.end(); ++i) { | |
321 | stringstream pool_id; | |
322 | pool_id << i->first; | |
323 | f->open_array_section(pool_id.str().c_str()); | |
324 | for (set<snapid_t>::const_iterator s = i->second.begin(); s != i->second.end(); ++s) { | |
325 | f->dump_unsigned("snapid", s->val); | |
326 | } | |
327 | f->close_section(); | |
328 | } | |
329 | f->close_section(); | |
330 | ||
331 | f->open_array_section("pending_update"); | |
332 | for(map<version_t, SnapInfo>::const_iterator i = pending_update.begin(); i != pending_update.end(); ++i) { | |
333 | f->open_object_section("snap"); | |
334 | f->dump_unsigned("version", i->first); | |
335 | f->open_object_section("snapinfo"); | |
336 | i->second.dump(f); | |
337 | f->close_section(); | |
338 | f->close_section(); | |
339 | } | |
340 | f->close_section(); | |
341 | ||
342 | f->open_array_section("pending_destroy"); | |
343 | for(map<version_t, pair<snapid_t, snapid_t> >::const_iterator i = pending_destroy.begin(); i != pending_destroy.end(); ++i) { | |
344 | f->open_object_section("snap"); | |
345 | f->dump_unsigned("version", i->first); | |
346 | f->dump_unsigned("removed_snap", i->second.first); | |
347 | f->dump_unsigned("seq", i->second.second); | |
348 | f->close_section(); | |
349 | } | |
350 | f->close_section(); | |
351 | ||
352 | f->close_section(); | |
353 | } | |
354 | ||
355 | void SnapServer::generate_test_instances(list<SnapServer*>& ls) | |
356 | { | |
357 | list<SnapInfo*> snapinfo_instances; | |
358 | SnapInfo::generate_test_instances(snapinfo_instances); | |
359 | SnapInfo populated_snapinfo = *(snapinfo_instances.back()); | |
360 | for (list<SnapInfo*>::iterator i = snapinfo_instances.begin(); i != snapinfo_instances.end(); ++i) { | |
361 | delete *i; | |
362 | } | |
363 | ||
364 | SnapServer *blank = new SnapServer(); | |
365 | ls.push_back(blank); | |
366 | SnapServer *populated = new SnapServer(); | |
367 | populated->last_snap = 123; | |
368 | populated->snaps[456] = populated_snapinfo; | |
369 | populated->need_to_purge[2].insert(012); | |
370 | populated->pending_update[234] = populated_snapinfo; | |
371 | populated->pending_destroy[345].first = 567; | |
372 | populated->pending_destroy[345].second = 768; | |
373 | populated->pending_noop.insert(890); | |
374 | ||
375 | ls.push_back(populated); | |
376 | ||
377 | } |