1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
15 #define dout_subsys ceph_subsys_rbd
17 #define dout_prefix *_dout << "librbd::api::Snapshot: " << __func__ << ": "
24 class GetGroupVisitor
: public boost::static_visitor
<int> {
27 librados::IoCtx
*image_ioctx
;
28 snap_group_namespace_t
*group_snap
;
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
) {};
35 inline int operator()(const T
&) const {
36 // ignore other than GroupSnapshotNamespace types.
40 inline int operator()(
41 const cls::rbd::GroupSnapshotNamespace
& snap_namespace
) {
43 int r
= util::create_ioctx(*image_ioctx
, "group", snap_namespace
.group_pool
,
49 cls::rbd::GroupSnapshot group_snapshot
;
51 std::string group_name
;
52 r
= cls_client::dir_get_name(&group_ioctx
, RBD_GROUP_DIRECTORY
,
53 snap_namespace
.group_id
, &group_name
);
55 lderr(cct
) << "failed to retrieve group name: " << cpp_strerror(r
)
60 string group_header_oid
= util::group_header_name(snap_namespace
.group_id
);
61 r
= cls_client::group_snap_get_by_id(&group_ioctx
,
63 snap_namespace
.group_snapshot_id
,
66 lderr(cct
) << "failed to retrieve group snapshot: " << cpp_strerror(r
)
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
;
78 class GetTrashVisitor
: public boost::static_visitor
<int> {
80 std::string
* original_name
;
82 explicit GetTrashVisitor(std::string
* original_name
)
83 : original_name(original_name
) {
87 inline int operator()(const T
&) const {
91 inline int operator()(
92 const cls::rbd::TrashSnapshotNamespace
& snap_namespace
) {
93 *original_name
= snap_namespace
.original_name
;
98 } // anonymous namespace
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();
108 RWLock::RLocker
snap_locker(ictx
->snap_lock
);
109 auto snap_info
= ictx
->get_snap_info(snap_id
);
110 if (snap_info
== nullptr) {
114 GetGroupVisitor ggv
= GetGroupVisitor(ictx
->cct
, &ictx
->data_ctx
, group_snap
);
115 r
= boost::apply_visitor(ggv
, snap_info
->snap_namespace
);
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();
131 RWLock::RLocker
snap_locker(ictx
->snap_lock
);
132 auto snap_info
= ictx
->get_snap_info(snap_id
);
133 if (snap_info
== nullptr) {
137 auto visitor
= GetTrashVisitor(original_name
);
138 r
= boost::apply_visitor(visitor
, snap_info
->snap_namespace
);
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();
154 RWLock::RLocker
l(ictx
->snap_lock
);
155 auto snap_info
= ictx
->get_snap_info(snap_id
);
156 if (snap_info
== nullptr) {
160 *namespace_type
= static_cast<snap_namespace_type_t
>(
161 cls::rbd::get_snap_namespace_type(snap_info
->snap_namespace
));
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
;
169 int r
= ictx
->state
->refresh_if_required();
174 cls::rbd::SnapshotNamespace snapshot_namespace
;
175 std::string snapshot_name
;
177 RWLock::RLocker
snap_locker(ictx
->snap_lock
);
178 auto it
= ictx
->snap_info
.find(snap_id
);
179 if (it
== ictx
->snap_info
.end()) {
183 snapshot_namespace
= it
->second
.snap_namespace
;
184 snapshot_name
= it
->second
.name
;
188 ictx
->operations
->snap_remove(snapshot_namespace
, snapshot_name
, &ctx
);
194 } // namespace librbd
196 template class librbd::api::Snapshot
<librbd::ImageCtx
>;