Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 (const auto p : mds->mdsmap->get_data_pools()) {
170       need_to_purge[p].insert(sn);
171       need_to_purge[p].insert(seq);
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 }