]>
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 | ||
169 | for (set<int64_t>::const_iterator p = mds->mdsmap->get_data_pools().begin(); | |
170 | p != mds->mdsmap->get_data_pools().end(); | |
171 | ++p) { | |
172 | need_to_purge[*p].insert(sn); | |
173 | need_to_purge[*p].insert(seq); | |
174 | } | |
175 | ||
176 | pending_destroy.erase(tid); | |
177 | } | |
178 | else if (pending_noop.count(tid)) { | |
179 | dout(7) << "commit " << tid << " noop" << dendl; | |
180 | pending_noop.erase(tid); | |
181 | } | |
182 | else | |
183 | ceph_abort(); | |
184 | ||
185 | // bump version. | |
186 | version++; | |
187 | //dump(); | |
188 | return true; | |
189 | } | |
190 | ||
191 | void SnapServer::_rollback(version_t tid) | |
192 | { | |
193 | if (pending_update.count(tid)) { | |
194 | SnapInfo &info = pending_update[tid]; | |
195 | string opname; | |
196 | if (info.long_name.empty()) | |
197 | opname = "create"; | |
198 | else | |
199 | opname.swap(info.long_name); | |
200 | dout(7) << "rollback " << tid << " " << opname << " " << info << dendl; | |
201 | pending_update.erase(tid); | |
202 | } | |
203 | ||
204 | else if (pending_destroy.count(tid)) { | |
205 | dout(7) << "rollback " << tid << " destroy " << pending_destroy[tid] << dendl; | |
206 | pending_destroy.erase(tid); | |
207 | } | |
208 | ||
209 | else if (pending_noop.count(tid)) { | |
210 | dout(7) << "rollback " << tid << " noop" << dendl; | |
211 | pending_noop.erase(tid); | |
212 | } | |
213 | ||
214 | else | |
215 | ceph_abort(); | |
216 | ||
217 | // bump version. | |
218 | version++; | |
219 | //dump(); | |
220 | } | |
221 | ||
222 | void SnapServer::_server_update(bufferlist& bl) | |
223 | { | |
224 | bufferlist::iterator p = bl.begin(); | |
225 | map<int, vector<snapid_t> > purge; | |
226 | ::decode(purge, p); | |
227 | ||
228 | dout(7) << "_server_update purged " << purge << dendl; | |
229 | for (map<int, vector<snapid_t> >::iterator p = purge.begin(); | |
230 | p != purge.end(); | |
231 | ++p) { | |
232 | for (vector<snapid_t>::iterator q = p->second.begin(); | |
233 | q != p->second.end(); | |
234 | ++q) | |
235 | need_to_purge[p->first].erase(*q); | |
236 | if (need_to_purge[p->first].empty()) | |
237 | need_to_purge.erase(p->first); | |
238 | } | |
239 | ||
240 | version++; | |
241 | } | |
242 | ||
243 | void SnapServer::handle_query(MMDSTableRequest *req) | |
244 | { | |
245 | req->put(); | |
246 | } | |
247 | ||
248 | ||
249 | ||
250 | void SnapServer::check_osd_map(bool force) | |
251 | { | |
252 | if (!force && version == last_checked_osdmap) { | |
253 | dout(10) << "check_osd_map - version unchanged" << dendl; | |
254 | return; | |
255 | } | |
256 | dout(10) << "check_osd_map need_to_purge=" << need_to_purge << dendl; | |
257 | ||
258 | map<int, vector<snapid_t> > all_purge; | |
259 | map<int, vector<snapid_t> > all_purged; | |
260 | ||
261 | mds->objecter->with_osdmap( | |
262 | [this, &all_purged, &all_purge](const OSDMap& osdmap) { | |
263 | for (const auto& p : need_to_purge) { | |
264 | int id = p.first; | |
265 | const pg_pool_t *pi = osdmap.get_pg_pool(id); | |
266 | if (pi == NULL) { | |
267 | // The pool is gone. So are the snapshots. | |
268 | all_purged[id] = std::vector<snapid_t>(p.second.begin(), | |
269 | p.second.end()); | |
270 | continue; | |
271 | } | |
272 | ||
273 | for (const auto& q : p.second) { | |
274 | if (pi->is_removed_snap(q)) { | |
275 | dout(10) << " osdmap marks " << q << " as removed" << dendl; | |
276 | all_purged[id].push_back(q); | |
277 | } else { | |
278 | all_purge[id].push_back(q); | |
279 | } | |
280 | } | |
281 | } | |
282 | }); | |
283 | ||
284 | if (!all_purged.empty()) { | |
285 | // prepare to remove from need_to_purge list | |
286 | bufferlist bl; | |
287 | ::encode(all_purged, bl); | |
288 | do_server_update(bl); | |
289 | } | |
290 | ||
291 | if (!all_purge.empty()) { | |
292 | dout(10) << "requesting removal of " << all_purge << dendl; | |
293 | MRemoveSnaps *m = new MRemoveSnaps(all_purge); | |
294 | mon_client->send_mon_message(m); | |
295 | } | |
296 | ||
297 | last_checked_osdmap = version; | |
298 | } | |
299 | ||
300 | ||
301 | void SnapServer::dump(Formatter *f) const | |
302 | { | |
303 | f->open_object_section("snapserver"); | |
304 | ||
305 | f->dump_int("last_snap", last_snap.val); | |
306 | ||
307 | f->open_array_section("pending_noop"); | |
308 | for(set<version_t>::const_iterator i = pending_noop.begin(); i != pending_noop.end(); ++i) { | |
309 | f->dump_unsigned("version", *i); | |
310 | } | |
311 | f->close_section(); | |
312 | ||
313 | f->open_array_section("snaps"); | |
314 | for (map<snapid_t, SnapInfo>::const_iterator i = snaps.begin(); i != snaps.end(); ++i) { | |
315 | f->open_object_section("snap"); | |
316 | i->second.dump(f); | |
317 | f->close_section(); | |
318 | } | |
319 | f->close_section(); | |
320 | ||
321 | f->open_object_section("need_to_purge"); | |
322 | for (map<int, set<snapid_t> >::const_iterator i = need_to_purge.begin(); i != need_to_purge.end(); ++i) { | |
323 | stringstream pool_id; | |
324 | pool_id << i->first; | |
325 | f->open_array_section(pool_id.str().c_str()); | |
326 | for (set<snapid_t>::const_iterator s = i->second.begin(); s != i->second.end(); ++s) { | |
327 | f->dump_unsigned("snapid", s->val); | |
328 | } | |
329 | f->close_section(); | |
330 | } | |
331 | f->close_section(); | |
332 | ||
333 | f->open_array_section("pending_update"); | |
334 | for(map<version_t, SnapInfo>::const_iterator i = pending_update.begin(); i != pending_update.end(); ++i) { | |
335 | f->open_object_section("snap"); | |
336 | f->dump_unsigned("version", i->first); | |
337 | f->open_object_section("snapinfo"); | |
338 | i->second.dump(f); | |
339 | f->close_section(); | |
340 | f->close_section(); | |
341 | } | |
342 | f->close_section(); | |
343 | ||
344 | f->open_array_section("pending_destroy"); | |
345 | for(map<version_t, pair<snapid_t, snapid_t> >::const_iterator i = pending_destroy.begin(); i != pending_destroy.end(); ++i) { | |
346 | f->open_object_section("snap"); | |
347 | f->dump_unsigned("version", i->first); | |
348 | f->dump_unsigned("removed_snap", i->second.first); | |
349 | f->dump_unsigned("seq", i->second.second); | |
350 | f->close_section(); | |
351 | } | |
352 | f->close_section(); | |
353 | ||
354 | f->close_section(); | |
355 | } | |
356 | ||
357 | void SnapServer::generate_test_instances(list<SnapServer*>& ls) | |
358 | { | |
359 | list<SnapInfo*> snapinfo_instances; | |
360 | SnapInfo::generate_test_instances(snapinfo_instances); | |
361 | SnapInfo populated_snapinfo = *(snapinfo_instances.back()); | |
362 | for (list<SnapInfo*>::iterator i = snapinfo_instances.begin(); i != snapinfo_instances.end(); ++i) { | |
363 | delete *i; | |
364 | } | |
365 | ||
366 | SnapServer *blank = new SnapServer(); | |
367 | ls.push_back(blank); | |
368 | SnapServer *populated = new SnapServer(); | |
369 | populated->last_snap = 123; | |
370 | populated->snaps[456] = populated_snapinfo; | |
371 | populated->need_to_purge[2].insert(012); | |
372 | populated->pending_update[234] = populated_snapinfo; | |
373 | populated->pending_destroy[345].first = 567; | |
374 | populated->pending_destroy[345].second = 768; | |
375 | populated->pending_noop.insert(890); | |
376 | ||
377 | ls.push_back(populated); | |
378 | ||
379 | } |