]> git.proxmox.com Git - ceph.git/blame - ceph/src/librados/snap_set_diff.cc
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / librados / snap_set_diff.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#include <vector>
5
6#include "snap_set_diff.h"
7#include "common/ceph_context.h"
8#include "include/rados/librados.hpp"
9#include "include/interval_set.h"
10#include "common/debug.h"
11
12#define dout_subsys ceph_subsys_rados
13
20effc67 14using namespace std;
7c673cae
FG
15/**
16 * calculate intervals/extents that vary between two snapshots
17 */
18void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set,
19 librados::snap_t start, librados::snap_t end,
20 interval_set<uint64_t> *diff, uint64_t *end_size,
94b18763
FG
21 bool *end_exists, librados::snap_t *clone_end_snap_id,
22 bool *whole_object)
7c673cae
FG
23{
24 ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end
25 << ", snap_set seq " << snap_set.seq << dendl;
26 bool saw_start = false;
27 uint64_t start_size = 0;
28 diff->clear();
29 *end_size = 0;
30 *end_exists = false;
31 *clone_end_snap_id = 0;
94b18763 32 *whole_object = false;
7c673cae 33
f38dd50b
TL
34 auto r = snap_set.clones.begin();
35 while (r != snap_set.clones.end()) {
7c673cae
FG
36 // make an interval, and hide the fact that the HEAD doesn't
37 // include itself in the snaps list
38 librados::snap_t a, b;
39 if (r->cloneid == librados::SNAP_HEAD) {
40 // head is valid starting from right after the last seen seq
41 a = snap_set.seq + 1;
42 b = librados::SNAP_HEAD;
94b18763
FG
43 } else if (r->snaps.empty()) {
44 ldout(cct, 1) << "clone " << r->cloneid
45 << ": empty snaps, return whole object" << dendl;
11fdf7f2 46 diff->clear();
94b18763
FG
47 *whole_object = true;
48 return;
7c673cae
FG
49 } else {
50 a = r->snaps[0];
51 // note: b might be < r->cloneid if a snap has been trimmed.
52 b = r->snaps[r->snaps.size()-1];
53 }
54 ldout(cct, 20) << " clone " << r->cloneid << " snaps " << r->snaps
55 << " -> [" << a << "," << b << "]"
56 << " size " << r->size << " overlap to next " << r->overlap << dendl;
57
58 if (b < start) {
59 // this is before start
60 ++r;
61 continue;
62 }
63
64 if (!saw_start) {
65 if (start < a) {
66 ldout(cct, 20) << " start, after " << start << dendl;
67 // this means the object didn't exist at start
68 if (r->size)
69 diff->insert(0, r->size);
70 start_size = 0;
71 } else {
72 ldout(cct, 20) << " start" << dendl;
73 start_size = r->size;
74 }
75 saw_start = true;
76 }
77
7c673cae 78 if (end < a) {
7c673cae
FG
79 break;
80 }
81 if (end <= b) {
82 ldout(cct, 20) << " end" << dendl;
f38dd50b 83 *end_size = r->size;
7c673cae
FG
84 *end_exists = true;
85 *clone_end_snap_id = b;
f38dd50b 86 return;
7c673cae
FG
87 }
88
f38dd50b
TL
89 // start with the largest possible diff to next, and subtract off
90 // any overlap
7c673cae
FG
91 const vector<pair<uint64_t, uint64_t> > *overlap = &r->overlap;
92 interval_set<uint64_t> diff_to_next;
f38dd50b
TL
93 uint64_t diff_boundary;
94 uint64_t prev_size = r->size;
7c673cae
FG
95 ++r;
96 if (r != snap_set.clones.end()) {
f38dd50b
TL
97 if (r->size >= prev_size) {
98 diff_boundary = r->size;
99 } else if (prev_size <= start_size) {
100 // truncated range below size at start
101 diff_boundary = prev_size;
102 } else {
103 // truncated range (partially) above size at start -- drop that
104 // part from the running diff
105 diff_boundary = std::max(r->size, start_size);
106 ldout(cct, 20) << " no more diff beyond " << diff_boundary << dendl;
107 diff->erase(diff_boundary, prev_size - diff_boundary);
108 }
109 if (diff_boundary) {
110 diff_to_next.insert(0, diff_boundary);
111 }
112 for (auto p = overlap->begin(); p != overlap->end(); ++p) {
113 diff_to_next.erase(p->first, p->second);
114 }
115 ldout(cct, 20) << " diff_to_next " << diff_to_next << dendl;
116 diff->union_of(diff_to_next);
117 ldout(cct, 20) << " diff now " << *diff << dendl;
7c673cae 118 }
f38dd50b
TL
119 }
120
121 if (r != snap_set.clones.end()) {
122 ldout(cct, 20) << " past end " << end
123 << ", end object does not exist" << dendl;
124 } else {
125 ldout(cct, 20) << " ran out of clones before reaching end " << end
126 << ", end object does not exist" << dendl;
127 }
128 diff->clear();
129 if (start_size) {
130 diff->insert(0, start_size);
7c673cae
FG
131 }
132}