]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/SnapRealm.cc
update dh_systemd restart patch for pacific
[ceph.git] / ceph / src / mds / SnapRealm.cc
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 */
14
15#include "SnapRealm.h"
16#include "MDCache.h"
17#include "MDSRank.h"
11fdf7f2 18#include "SnapClient.h"
7c673cae 19
11fdf7f2 20#include <string_view>
7c673cae
FG
21
22
23/*
24 * SnapRealm
25 */
26
27#define dout_context g_ceph_context
28#define dout_subsys ceph_subsys_mds
29#undef dout_prefix
30#define dout_prefix _prefix(_dout, mdcache->mds->get_nodeid(), inode, srnode.seq, this)
31static ostream& _prefix(std::ostream *_dout, int whoami, const CInode *inode,
32 uint64_t seq, const SnapRealm *realm) {
33 return *_dout << " mds." << whoami
34 << ".cache.snaprealm(" << inode->ino()
35 << " seq " << seq << " " << realm << ") ";
36}
37
38ostream& operator<<(ostream& out, const SnapRealm& realm)
39{
40 out << "snaprealm(" << realm.inode->ino()
41 << " seq " << realm.srnode.seq
42 << " lc " << realm.srnode.last_created
43 << " cr " << realm.srnode.created;
44 if (realm.srnode.created != realm.srnode.current_parent_since)
45 out << " cps " << realm.srnode.current_parent_since;
46 out << " snaps=" << realm.srnode.snaps;
11fdf7f2
TL
47 out << " past_parent_snaps=" << realm.srnode.past_parent_snaps;
48
11fdf7f2
TL
49 if (realm.srnode.is_parent_global())
50 out << " global ";
7c673cae
FG
51 out << " " << &realm << ")";
52 return out;
53}
54
11fdf7f2 55SnapRealm::SnapRealm(MDCache *c, CInode *in) :
f67539c2 56 mdcache(c), inode(in), inodes_with_caps(member_offset(CInode, item_caps))
11fdf7f2
TL
57{
58 global = (inode->ino() == MDS_INO_GLOBAL_SNAPREALM);
59}
7c673cae 60
7c673cae
FG
61/*
62 * get list of snaps for this realm. we must include parents' snaps
63 * for the intervals during which they were our parent.
64 */
11fdf7f2 65void SnapRealm::build_snap_set() const
7c673cae 66{
11fdf7f2 67 dout(10) << "build_snap_set on " << *this << dendl;
7c673cae 68
11fdf7f2 69 cached_snaps.clear();
7c673cae 70
11fdf7f2
TL
71 if (global) {
72 mdcache->mds->snapclient->get_snaps(cached_snaps);
73 return;
74 }
7c673cae 75
11fdf7f2
TL
76 // include my snaps
77 for (const auto& p : srnode.snaps)
78 cached_snaps.insert(p.first);
79
80 if (!srnode.past_parent_snaps.empty()) {
81 set<snapid_t> snaps = mdcache->mds->snapclient->filter(srnode.past_parent_snaps);
82 if (!snaps.empty()) {
83 snapid_t last = *snaps.rbegin();
84 cached_seq = std::max(cached_seq, last);
85 cached_last_created = std::max(cached_last_created, last);
86 }
87 cached_snaps.insert(snaps.begin(), snaps.end());
7c673cae 88 }
7c673cae 89
11fdf7f2
TL
90 snapid_t parent_seq = parent ? parent->get_newest_seq() : snapid_t(0);
91 if (parent_seq >= srnode.current_parent_since) {
92 auto& snaps = parent->get_snaps();
93 auto p = snaps.lower_bound(srnode.current_parent_since);
94 cached_snaps.insert(p, snaps.end());
95 cached_seq = std::max(cached_seq, parent_seq);
96 cached_last_created = std::max(cached_last_created, parent->get_last_created());
97 }
98}
7c673cae
FG
99
100void SnapRealm::check_cache() const
101{
11fdf7f2
TL
102 snapid_t seq;
103 snapid_t last_created;
104 snapid_t last_destroyed = mdcache->mds->snapclient->get_last_destroyed();
105 if (global || srnode.is_parent_global()) {
106 last_created = mdcache->mds->snapclient->get_last_created();
107 seq = std::max(last_created, last_destroyed);
108 } else {
109 last_created = srnode.last_created;
110 seq = srnode.seq;
111 }
112 if (cached_seq >= seq &&
113 cached_last_destroyed == last_destroyed)
7c673cae
FG
114 return;
115
7c673cae
FG
116 cached_snap_context.clear();
117
11fdf7f2
TL
118 cached_seq = seq;
119 cached_last_created = last_created;
120 cached_last_destroyed = last_destroyed;
adb31ebb
TL
121
122 cached_subvolume_ino = 0;
123 if (parent)
124 cached_subvolume_ino = parent->get_subvolume_ino();
125 if (!cached_subvolume_ino && srnode.is_subvolume())
126 cached_subvolume_ino = inode->ino();
127
11fdf7f2 128 build_snap_set();
7c673cae 129
11fdf7f2 130 build_snap_trace();
7c673cae
FG
131
132 dout(10) << "check_cache rebuilt " << cached_snaps
11fdf7f2 133 << " seq " << seq
7c673cae
FG
134 << " cached_seq " << cached_seq
135 << " cached_last_created " << cached_last_created
136 << " cached_last_destroyed " << cached_last_destroyed
137 << ")" << dendl;
138}
139
140const set<snapid_t>& SnapRealm::get_snaps() const
141{
142 check_cache();
143 dout(10) << "get_snaps " << cached_snaps
144 << " (seq " << srnode.seq << " cached_seq " << cached_seq << ")"
145 << dendl;
146 return cached_snaps;
147}
148
149/*
150 * build vector in reverse sorted order
151 */
152const SnapContext& SnapRealm::get_snap_context() const
153{
154 check_cache();
155
156 if (!cached_snap_context.seq) {
157 cached_snap_context.seq = cached_seq;
158 cached_snap_context.snaps.resize(cached_snaps.size());
159 unsigned i = 0;
160 for (set<snapid_t>::reverse_iterator p = cached_snaps.rbegin();
161 p != cached_snaps.rend();
162 ++p)
163 cached_snap_context.snaps[i++] = *p;
164 }
165
166 return cached_snap_context;
167}
168
11fdf7f2 169void SnapRealm::get_snap_info(map<snapid_t, const SnapInfo*>& infomap, snapid_t first, snapid_t last)
7c673cae
FG
170{
171 const set<snapid_t>& snaps = get_snaps();
172 dout(10) << "get_snap_info snaps " << snaps << dendl;
173
174 // include my snaps within interval [first,last]
11fdf7f2 175 for (auto p = srnode.snaps.lower_bound(first); // first element >= first
7c673cae
FG
176 p != srnode.snaps.end() && p->first <= last;
177 ++p)
178 infomap[p->first] = &p->second;
179
11fdf7f2
TL
180 if (!srnode.past_parent_snaps.empty()) {
181 set<snapid_t> snaps;
182 for (auto p = srnode.past_parent_snaps.lower_bound(first); // first element >= first
183 p != srnode.past_parent_snaps.end() && *p <= last;
184 ++p) {
185 snaps.insert(*p);
186 }
187
188 map<snapid_t, const SnapInfo*> _infomap;
189 mdcache->mds->snapclient->get_snap_infos(_infomap, snaps);
190 infomap.insert(_infomap.begin(), _infomap.end());
7c673cae 191 }
11fdf7f2 192
7c673cae 193 if (srnode.current_parent_since <= last && parent)
11fdf7f2 194 parent->get_snap_info(infomap, std::max(first, srnode.current_parent_since), last);
7c673cae
FG
195}
196
11fdf7f2 197std::string_view SnapRealm::get_snapname(snapid_t snapid, inodeno_t atino)
7c673cae
FG
198{
199 auto srnode_snaps_entry = srnode.snaps.find(snapid);
200 if (srnode_snaps_entry != srnode.snaps.end()) {
201 if (atino == inode->ino())
202 return srnode_snaps_entry->second.name;
203 else
204 return srnode_snaps_entry->second.get_long_name();
205 }
206
11fdf7f2
TL
207 if (!srnode.past_parent_snaps.empty()) {
208 if (srnode.past_parent_snaps.count(snapid)) {
209 const SnapInfo *sinfo = mdcache->mds->snapclient->get_snap_info(snapid);
210 if (sinfo) {
211 if (atino == sinfo->ino)
212 return sinfo->name;
213 else
214 return sinfo->get_long_name();
215 }
216 }
7c673cae
FG
217 }
218
11fdf7f2
TL
219 ceph_assert(srnode.current_parent_since <= snapid);
220 ceph_assert(parent);
7c673cae
FG
221 return parent->get_snapname(snapid, atino);
222}
223
11fdf7f2 224snapid_t SnapRealm::resolve_snapname(std::string_view n, inodeno_t atino, snapid_t first, snapid_t last)
7c673cae
FG
225{
226 // first try me
227 dout(10) << "resolve_snapname '" << n << "' in [" << first << "," << last << "]" << dendl;
228
7c673cae
FG
229 bool actual = (atino == inode->ino());
230 string pname;
231 inodeno_t pino;
11fdf7f2 232 if (n.length() && n[0] == '_') {
81eedcae
TL
233 size_t next_ = n.find_last_of('_');
234 if (next_ > 1 && next_ + 1 < n.length()) {
11fdf7f2
TL
235 pname = n.substr(1, next_ - 1);
236 pino = atoll(n.data() + next_ + 1);
237 dout(10) << " " << n << " parses to name '" << pname << "' dirino " << pino << dendl;
238 }
7c673cae
FG
239 }
240
11fdf7f2 241 for (auto p = srnode.snaps.lower_bound(first); // first element >= first
7c673cae
FG
242 p != srnode.snaps.end() && p->first <= last;
243 ++p) {
244 dout(15) << " ? " << p->second << dendl;
245 //if (num && p->second.snapid == num)
246 //return p->first;
247 if (actual && p->second.name == n)
248 return p->first;
249 if (!actual && p->second.name == pname && p->second.ino == pino)
250 return p->first;
251 }
252
11fdf7f2
TL
253 if (!srnode.past_parent_snaps.empty()) {
254 set<snapid_t> snaps;
255 for (auto p = srnode.past_parent_snaps.lower_bound(first); // first element >= first
256 p != srnode.past_parent_snaps.end() && *p <= last;
257 ++p)
258 snaps.insert(*p);
259
260 map<snapid_t, const SnapInfo*> _infomap;
261 mdcache->mds->snapclient->get_snap_infos(_infomap, snaps);
262
263 for (auto& it : _infomap) {
264 dout(15) << " ? " << *it.second << dendl;
265 actual = (it.second->ino == atino);
266 if (actual && it.second->name == n)
267 return it.first;
268 if (!actual && it.second->name == pname && it.second->ino == pino)
269 return it.first;
270 }
7c673cae 271 }
11fdf7f2 272
7c673cae 273 if (parent && srnode.current_parent_since <= last)
11fdf7f2 274 return parent->resolve_snapname(n, atino, std::max(first, srnode.current_parent_since), last);
7c673cae
FG
275 return 0;
276}
277
278
279void SnapRealm::adjust_parent()
280{
11fdf7f2
TL
281 SnapRealm *newparent;
282 if (srnode.is_parent_global()) {
283 newparent = mdcache->get_global_snaprealm();
284 } else {
285 CDentry *pdn = inode->get_parent_dn();
286 newparent = pdn ? pdn->get_dir()->get_inode()->find_snaprealm() : NULL;
287 }
7c673cae
FG
288 if (newparent != parent) {
289 dout(10) << "adjust_parent " << parent << " -> " << newparent << dendl;
290 if (parent)
291 parent->open_children.erase(this);
292 parent = newparent;
293 if (parent)
294 parent->open_children.insert(this);
295
296 invalidate_cached_snaps();
297 }
298}
299
300void SnapRealm::split_at(SnapRealm *child)
301{
302 dout(10) << "split_at " << *child
303 << " on " << *child->inode << dendl;
304
305 if (inode->is_mdsdir() || !child->inode->is_dir()) {
306 // it's not a dir.
307 if (child->inode->containing_realm) {
308 // - no open children.
309 // - only need to move this child's inode's caps.
310 child->inode->move_to_realm(child);
311 } else {
312 // no caps, nothing to move/split.
313 dout(20) << " split no-op, no caps to move on file " << *child->inode << dendl;
11fdf7f2 314 ceph_assert(!child->inode->is_any_caps());
7c673cae
FG
315 }
316 return;
317 }
318
319 // it's a dir.
320
321 // split open_children
322 dout(10) << " open_children are " << open_children << dendl;
323 for (set<SnapRealm*>::iterator p = open_children.begin();
324 p != open_children.end(); ) {
325 SnapRealm *realm = *p;
326 if (realm != child &&
11fdf7f2 327 child->inode->is_ancestor_of(realm->inode)) {
7c673cae
FG
328 dout(20) << " child gets child realm " << *realm << " on " << *realm->inode << dendl;
329 realm->parent = child;
330 child->open_children.insert(realm);
331 open_children.erase(p++);
332 } else {
333 dout(20) << " keeping child realm " << *realm << " on " << *realm->inode << dendl;
334 ++p;
335 }
336 }
337
338 // split inodes_with_caps
f67539c2 339 for (auto p = inodes_with_caps.begin(); !p.end(); ) {
7c673cae
FG
340 CInode *in = *p;
341 ++p;
7c673cae 342 // does inode fall within the child realm?
11fdf7f2 343 if (child->inode->is_ancestor_of(in)) {
7c673cae
FG
344 dout(20) << " child gets " << *in << dendl;
345 in->move_to_realm(child);
346 } else {
347 dout(20) << " keeping " << *in << dendl;
348 }
349 }
11fdf7f2
TL
350}
351
352void SnapRealm::merge_to(SnapRealm *newparent)
353{
354 if (!newparent)
355 newparent = parent;
356 dout(10) << "merge to " << *newparent << " on " << *newparent->inode << dendl;
357
11fdf7f2
TL
358 dout(10) << " open_children are " << open_children << dendl;
359 for (auto realm : open_children) {
360 dout(20) << " child realm " << *realm << " on " << *realm->inode << dendl;
361 newparent->open_children.insert(realm);
362 realm->parent = newparent;
363 }
364 open_children.clear();
365
f67539c2 366 for (auto p = inodes_with_caps.begin(); !p.end(); ) {
11fdf7f2
TL
367 CInode *in = *p;
368 ++p;
369 in->move_to_realm(newparent);
370 }
371 ceph_assert(inodes_with_caps.empty());
7c673cae 372
11fdf7f2
TL
373 // delete this
374 inode->close_snaprealm();
7c673cae
FG
375}
376
11fdf7f2 377const bufferlist& SnapRealm::get_snap_trace() const
7c673cae
FG
378{
379 check_cache();
380 return cached_snap_trace;
381}
382
11fdf7f2 383void SnapRealm::build_snap_trace() const
7c673cae 384{
11fdf7f2
TL
385 cached_snap_trace.clear();
386
387 if (global) {
388 SnapRealmInfo info(inode->ino(), 0, cached_seq, 0);
389 info.my_snaps.reserve(cached_snaps.size());
390 for (auto p = cached_snaps.rbegin(); p != cached_snaps.rend(); ++p)
391 info.my_snaps.push_back(*p);
7c673cae 392
11fdf7f2
TL
393 dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
394 encode(info, cached_snap_trace);
395 return;
396 }
397
398 SnapRealmInfo info(inode->ino(), srnode.created, srnode.seq, srnode.current_parent_since);
7c673cae
FG
399 if (parent) {
400 info.h.parent = parent->inode->ino();
11fdf7f2
TL
401
402 set<snapid_t> past;
403 if (!srnode.past_parent_snaps.empty()) {
404 past = mdcache->mds->snapclient->filter(srnode.past_parent_snaps);
405 if (srnode.is_parent_global()) {
406 auto p = past.lower_bound(srnode.current_parent_since);
407 past.erase(p, past.end());
408 }
11fdf7f2
TL
409 }
410
411 if (!past.empty()) {
7c673cae
FG
412 info.prior_parent_snaps.reserve(past.size());
413 for (set<snapid_t>::reverse_iterator p = past.rbegin(); p != past.rend(); ++p)
414 info.prior_parent_snaps.push_back(*p);
11fdf7f2 415 dout(10) << "build_snap_trace prior_parent_snaps from [1," << *past.rbegin() << "] "
7c673cae
FG
416 << info.prior_parent_snaps << dendl;
417 }
11fdf7f2 418 }
7c673cae
FG
419
420 info.my_snaps.reserve(srnode.snaps.size());
11fdf7f2 421 for (auto p = srnode.snaps.rbegin();
7c673cae
FG
422 p != srnode.snaps.rend();
423 ++p)
424 info.my_snaps.push_back(p->first);
425 dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
426
11fdf7f2 427 encode(info, cached_snap_trace);
7c673cae
FG
428
429 if (parent)
11fdf7f2 430 cached_snap_trace.append(parent->get_snap_trace());
7c673cae
FG
431}
432
f67539c2 433void SnapRealm::prune_past_parent_snaps()
7c673cae 434{
f67539c2 435 dout(10) << __func__ << dendl;
7c673cae 436 check_cache();
11fdf7f2 437
11fdf7f2
TL
438 for (auto p = srnode.past_parent_snaps.begin();
439 p != srnode.past_parent_snaps.end(); ) {
440 auto q = cached_snaps.find(*p);
441 if (q == cached_snaps.end()) {
f67539c2 442 dout(10) << __func__ << " pruning " << *p << dendl;
11fdf7f2 443 srnode.past_parent_snaps.erase(p++);
7c673cae 444 } else {
f67539c2 445 dout(10) << __func__ << " keeping " << *p << dendl;
7c673cae
FG
446 ++p;
447 }
448 }
449}
450