]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/api/Snapshot.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / librbd / api / Snapshot.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/api/Snapshot.h"
5 #include "cls/rbd/cls_rbd_types.h"
6 #include "common/errno.h"
7 #include "librbd/ImageCtx.h"
8 #include "librbd/ImageState.h"
9 #include "librbd/Operations.h"
10 #include "librbd/Utils.h"
11 #include <boost/variant.hpp>
12 #include "include/Context.h"
13 #include "common/Cond.h"
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::api::Snapshot: " << __func__ << ": "
18
19 namespace librbd {
20 namespace api {
21
22 namespace {
23
24 class GetGroupVisitor : public boost::static_visitor<int> {
25 public:
26 CephContext* cct;
27 librados::IoCtx *image_ioctx;
28 snap_group_namespace_t *group_snap;
29
30 explicit GetGroupVisitor(CephContext* cct, librados::IoCtx *_image_ioctx,
31 snap_group_namespace_t *group_snap)
32 : cct(cct), image_ioctx(_image_ioctx), group_snap(group_snap) {};
33
34 template <typename T>
35 inline int operator()(const T&) const {
36 // ignore other than GroupSnapshotNamespace types.
37 return -EINVAL;
38 }
39
40 inline int operator()(
41 const cls::rbd::GroupSnapshotNamespace& snap_namespace) {
42 IoCtx group_ioctx;
43 int r = util::create_ioctx(*image_ioctx, "group", snap_namespace.group_pool,
44 {}, &group_ioctx);
45 if (r < 0) {
46 return r;
47 }
48
49 cls::rbd::GroupSnapshot group_snapshot;
50
51 std::string group_name;
52 r = cls_client::dir_get_name(&group_ioctx, RBD_GROUP_DIRECTORY,
53 snap_namespace.group_id, &group_name);
54 if (r < 0) {
55 lderr(cct) << "failed to retrieve group name: " << cpp_strerror(r)
56 << dendl;
57 return r;
58 }
59
60 string group_header_oid = util::group_header_name(snap_namespace.group_id);
61 r = cls_client::group_snap_get_by_id(&group_ioctx,
62 group_header_oid,
63 snap_namespace.group_snapshot_id,
64 &group_snapshot);
65 if (r < 0) {
66 lderr(cct) << "failed to retrieve group snapshot: " << cpp_strerror(r)
67 << dendl;
68 return r;
69 }
70
71 group_snap->group_pool = group_ioctx.get_id();
72 group_snap->group_name = group_name;
73 group_snap->group_snap_name = group_snapshot.name;
74 return 0;
75 }
76 };
77
78 class GetTrashVisitor : public boost::static_visitor<int> {
79 public:
80 std::string* original_name;
81
82 explicit GetTrashVisitor(std::string* original_name)
83 : original_name(original_name) {
84 }
85
86 template <typename T>
87 inline int operator()(const T&) const {
88 return -EINVAL;
89 }
90
91 inline int operator()(
92 const cls::rbd::TrashSnapshotNamespace& snap_namespace) {
93 *original_name = snap_namespace.original_name;
94 return 0;
95 }
96 };
97
98 } // anonymous namespace
99
100 template <typename I>
101 int Snapshot<I>::get_group_namespace(I *ictx, uint64_t snap_id,
102 snap_group_namespace_t *group_snap) {
103 int r = ictx->state->refresh_if_required();
104 if (r < 0) {
105 return r;
106 }
107
108 RWLock::RLocker snap_locker(ictx->snap_lock);
109 auto snap_info = ictx->get_snap_info(snap_id);
110 if (snap_info == nullptr) {
111 return -ENOENT;
112 }
113
114 GetGroupVisitor ggv = GetGroupVisitor(ictx->cct, &ictx->data_ctx, group_snap);
115 r = boost::apply_visitor(ggv, snap_info->snap_namespace);
116 if (r < 0) {
117 return r;
118 }
119
120 return 0;
121 }
122
123 template <typename I>
124 int Snapshot<I>::get_trash_namespace(I *ictx, uint64_t snap_id,
125 std::string* original_name) {
126 int r = ictx->state->refresh_if_required();
127 if (r < 0) {
128 return r;
129 }
130
131 RWLock::RLocker snap_locker(ictx->snap_lock);
132 auto snap_info = ictx->get_snap_info(snap_id);
133 if (snap_info == nullptr) {
134 return -ENOENT;
135 }
136
137 auto visitor = GetTrashVisitor(original_name);
138 r = boost::apply_visitor(visitor, snap_info->snap_namespace);
139 if (r < 0) {
140 return r;
141 }
142
143 return 0;
144 }
145
146 template <typename I>
147 int Snapshot<I>::get_namespace_type(I *ictx, uint64_t snap_id,
148 snap_namespace_type_t *namespace_type) {
149 int r = ictx->state->refresh_if_required();
150 if (r < 0) {
151 return r;
152 }
153
154 RWLock::RLocker l(ictx->snap_lock);
155 auto snap_info = ictx->get_snap_info(snap_id);
156 if (snap_info == nullptr) {
157 return -ENOENT;
158 }
159
160 *namespace_type = static_cast<snap_namespace_type_t>(
161 cls::rbd::get_snap_namespace_type(snap_info->snap_namespace));
162 return 0;
163 }
164
165 template <typename I>
166 int Snapshot<I>::remove(I *ictx, uint64_t snap_id) {
167 ldout(ictx->cct, 20) << "snap_remove " << ictx << " " << snap_id << dendl;
168
169 int r = ictx->state->refresh_if_required();
170 if (r < 0) {
171 return r;
172 }
173
174 cls::rbd::SnapshotNamespace snapshot_namespace;
175 std::string snapshot_name;
176 {
177 RWLock::RLocker snap_locker(ictx->snap_lock);
178 auto it = ictx->snap_info.find(snap_id);
179 if (it == ictx->snap_info.end()) {
180 return -ENOENT;
181 }
182
183 snapshot_namespace = it->second.snap_namespace;
184 snapshot_name = it->second.name;
185 }
186
187 C_SaferCond ctx;
188 ictx->operations->snap_remove(snapshot_namespace, snapshot_name, &ctx);
189 r = ctx.wait();
190 return r;
191 }
192
193 } // namespace api
194 } // namespace librbd
195
196 template class librbd::api::Snapshot<librbd::ImageCtx>;