]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/mirror/snapshot/Utils.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / librbd / mirror / snapshot / Utils.cc
CommitLineData
9f95a23c
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "common/dout.h"
5#include "common/errno.h"
6#include "include/stringify.h"
7#include "librbd/ImageCtx.h"
8#include "librbd/mirror/snapshot/Utils.h"
9
10#define dout_subsys ceph_subsys_rbd
11
12#undef dout_prefix
13#define dout_prefix *_dout << "librbd::mirror::snapshot::util: " \
14 << " " << __func__ << ": "
15
16namespace librbd {
17namespace mirror {
18namespace snapshot {
19namespace util {
20
21namespace {
22
23const std::string IMAGE_STATE_OBJECT_PREFIX = "rbd_mirror_snapshot.";
24
25bool get_rollback_snap_id(
26 std::map<librados::snap_t, SnapInfo>::reverse_iterator it,
27 std::map<librados::snap_t, SnapInfo>::reverse_iterator end,
28 uint64_t *rollback_snap_id) {
29
30 for (; it != end; it++) {
1e59de90
TL
31 auto mirror_ns = std::get<cls::rbd::MirrorSnapshotNamespace>(
32 it->second.snap_namespace);
33 if (mirror_ns.state != cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) {
9f95a23c
TL
34 break;
35 }
1e59de90 36 if (mirror_ns.complete) {
9f95a23c
TL
37 break;
38 }
39 }
40
41 if (it != end) {
42 *rollback_snap_id = it->first;
43 return true;
44 }
45
46 return false;
47}
48
49} // anonymous namespace
50
51std::string get_image_meta_key(const std::string& mirror_uuid) {
52 return ".rbd_mirror." + mirror_uuid;
53}
54
55template <typename I>
56bool can_create_primary_snapshot(I *image_ctx, bool demoted, bool force,
57 bool* requires_orphan,
58 uint64_t *rollback_snap_id) {
59 CephContext *cct = image_ctx->cct;
60
61 if (requires_orphan != nullptr) {
62 *requires_orphan = false;
63 }
64 if (rollback_snap_id) {
65 *rollback_snap_id = CEPH_NOSNAP;
66 }
67
68 std::shared_lock image_locker{image_ctx->image_lock};
69
70 for (auto it = image_ctx->snap_info.rbegin();
71 it != image_ctx->snap_info.rend(); it++) {
1e59de90 72 auto mirror_ns = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
9f95a23c
TL
73 &it->second.snap_namespace);
74 if (mirror_ns == nullptr) {
75 continue;
76 }
77 ldout(cct, 20) << "previous snapshot snap_id=" << it->first << " "
78 << *mirror_ns << dendl;
79 if (mirror_ns->is_demoted() && !force) {
80 lderr(cct) << "trying to create primary snapshot without force "
81 << "when previous primary snapshot is demoted"
82 << dendl;
83 return false;
84 }
85
86 if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) {
87 if (!force) {
88 lderr(cct) << "trying to create primary snapshot without force "
89 << "when previous snapshot is non-primary"
90 << dendl;
91 return false;
92 }
93 if (demoted) {
94 lderr(cct) << "trying to create primary demoted snapshot "
95 << "when previous snapshot is non-primary"
96 << dendl;
97 return false;
98 }
99
100 if (requires_orphan != nullptr) {
101 *requires_orphan = !mirror_ns->is_demoted();
102 }
103 if (!mirror_ns->complete) {
104 ldout(cct, 20) << "needs rollback" << dendl;
105 if (!rollback_snap_id) {
106 lderr(cct) << "trying to create primary snapshot "
107 << "when previous non-primary snapshot is not copied yet"
108 << dendl;
109 return false;
110 }
111 if (!get_rollback_snap_id(++it, image_ctx->snap_info.rend(),
112 rollback_snap_id)) {
113 lderr(cct) << "cannot rollback" << dendl;
114 return false;
115 }
116 ldout(cct, 20) << "rollback_snap_id=" << *rollback_snap_id << dendl;
117 }
118 return true;
119 }
120
121 return true;
122 }
123
124 ldout(cct, 20) << "no previous mirror snapshots found" << dendl;
125 return true;
126}
127
128template <typename I>
129bool can_create_non_primary_snapshot(I *image_ctx) {
130 CephContext *cct = image_ctx->cct;
131
132 std::shared_lock image_locker{image_ctx->image_lock};
133
134 for (auto it = image_ctx->snap_info.rbegin();
135 it != image_ctx->snap_info.rend(); it++) {
1e59de90 136 auto mirror_ns = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
9f95a23c
TL
137 &it->second.snap_namespace);
138 if (mirror_ns != nullptr) {
139 ldout(cct, 20) << "previous mirror snapshot snap_id=" << it->first << " "
140 << *mirror_ns << dendl;
141
142 if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) {
143 if (!mirror_ns->complete) {
144 lderr(cct) << "trying to create non-primary snapshot "
145 << "when previous non-primary snapshot is not copied yet"
146 << dendl;
147 return false;
148 }
149 return true;
150 }
151
152 if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
153 lderr(cct) << "trying to create non-primary snapshot "
154 << "when previous primary snapshot is not in demoted state"
155 << dendl;
156 return false;
157 }
158 return true;
159 }
160 }
161
162 ldout(cct, 20) << "no previous mirror snapshots found" << dendl;
163 return true;
164}
165
166template <typename I>
167std::string image_state_object_name(I *image_ctx, uint64_t snap_id,
168 uint64_t index) {
169 return IMAGE_STATE_OBJECT_PREFIX + image_ctx->id + "." +
170 stringify(snap_id) + "." + stringify(index);
171}
172
173} // namespace util
174} // namespace snapshot
175} // namespace mirror
176} // namespace librbd
177
178template bool librbd::mirror::snapshot::util::can_create_primary_snapshot(
179 librbd::ImageCtx *image_ctx, bool demoted, bool force,
180 bool* requires_orphan, uint64_t *rollback_snap_id);
181
182template bool librbd::mirror::snapshot::util::can_create_non_primary_snapshot(
183 librbd::ImageCtx *image_ctx);
184
185template std::string librbd::mirror::snapshot::util::image_state_object_name(
186 librbd::ImageCtx *image_ctx, uint64_t snap_id, uint64_t index);