]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | namespace librbd { | |
17 | namespace mirror { | |
18 | namespace snapshot { | |
19 | namespace util { | |
20 | ||
21 | namespace { | |
22 | ||
23 | const std::string IMAGE_STATE_OBJECT_PREFIX = "rbd_mirror_snapshot."; | |
24 | ||
25 | bool 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 | ||
51 | std::string get_image_meta_key(const std::string& mirror_uuid) { | |
52 | return ".rbd_mirror." + mirror_uuid; | |
53 | } | |
54 | ||
55 | template <typename I> | |
56 | bool 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 | ||
128 | template <typename I> | |
129 | bool 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 | ||
166 | template <typename I> | |
167 | std::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 | ||
178 | template 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 | ||
182 | template bool librbd::mirror::snapshot::util::can_create_non_primary_snapshot( | |
183 | librbd::ImageCtx *image_ctx); | |
184 | ||
185 | template std::string librbd::mirror::snapshot::util::image_state_object_name( | |
186 | librbd::ImageCtx *image_ctx, uint64_t snap_id, uint64_t index); |