]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/SnapServer.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / mds / SnapServer.cc
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 }