1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/mirror/snapshot/SetImageStateRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "cls/rbd/cls_rbd_client.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/Utils.h"
10 #include "librbd/image/GetMetadataRequest.h"
11 #include "librbd/mirror/snapshot/WriteImageStateRequest.h"
13 #include <boost/algorithm/string/predicate.hpp>
15 #define dout_subsys ceph_subsys_rbd
18 #define dout_prefix *_dout << "librbd::mirror_snapshot::SetImageStateRequest: " \
19 << this << " " << __func__ << ": "
25 using librbd::util::create_context_callback
;
26 using librbd::util::create_rados_callback
;
29 void SetImageStateRequest
<I
>::send() {
34 void SetImageStateRequest
<I
>::get_snap_limit() {
35 CephContext
*cct
= m_image_ctx
->cct
;
36 ldout(cct
, 20) << dendl
;
38 librados::ObjectReadOperation op
;
39 cls_client::snapshot_get_limit_start(&op
);
41 librados::AioCompletion
*comp
= create_rados_callback
<
42 SetImageStateRequest
<I
>,
43 &SetImageStateRequest
<I
>::handle_get_snap_limit
>(this);
45 int r
= m_image_ctx
->md_ctx
.aio_operate(m_image_ctx
->header_oid
, comp
, &op
,
52 void SetImageStateRequest
<I
>::handle_get_snap_limit(int r
) {
53 CephContext
*cct
= m_image_ctx
->cct
;
54 ldout(cct
, 20) << "r=" << r
<< dendl
;
57 auto it
= m_bl
.cbegin();
58 r
= cls_client::snapshot_get_limit_finish(&it
, &m_image_state
.snap_limit
);
62 lderr(cct
) << "failed to retrieve snapshot limit: " << cpp_strerror(r
)
68 ldout(cct
, 20) << "snap_limit=" << m_image_state
.snap_limit
<< dendl
;
74 void SetImageStateRequest
<I
>::get_metadata() {
75 CephContext
*cct
= m_image_ctx
->cct
;
76 ldout(cct
, 20) << dendl
;
78 auto ctx
= create_context_callback
<
79 SetImageStateRequest
<I
>,
80 &SetImageStateRequest
<I
>::handle_get_metadata
>(this);
81 auto req
= image::GetMetadataRequest
<I
>::create(
82 m_image_ctx
->md_ctx
, m_image_ctx
->header_oid
, true, "", "", 0,
83 &m_image_state
.metadata
, ctx
);
88 void SetImageStateRequest
<I
>::handle_get_metadata(int r
) {
89 CephContext
*cct
= m_image_ctx
->cct
;
90 ldout(cct
, 20) << "r=" << r
<< dendl
;
93 lderr(cct
) << "failed to retrieve metadata: " << cpp_strerror(r
)
100 std::shared_lock image_locker
{m_image_ctx
->image_lock
};
102 m_image_state
.name
= m_image_ctx
->name
;
103 m_image_state
.features
=
104 m_image_ctx
->features
& ~RBD_FEATURES_IMPLICIT_ENABLE
;
106 for (auto &[snap_id
, snap_info
] : m_image_ctx
->snap_info
) {
107 auto type
= cls::rbd::get_snap_namespace_type(snap_info
.snap_namespace
);
108 if (type
!= cls::rbd::SNAPSHOT_NAMESPACE_TYPE_USER
) {
109 // only replicate user snapshots -- trash snapshots will be
110 // replicated by an implicit delete if required
113 m_image_state
.snapshots
[snap_id
] = {snap_info
.snap_namespace
,
115 snap_info
.protection_status
};
122 template <typename I
>
123 void SetImageStateRequest
<I
>::write_image_state() {
124 CephContext
*cct
= m_image_ctx
->cct
;
125 ldout(cct
, 20) << dendl
;
127 auto ctx
= create_context_callback
<
128 SetImageStateRequest
<I
>,
129 &SetImageStateRequest
<I
>::handle_write_image_state
>(this);
131 auto req
= WriteImageStateRequest
<I
>::create(m_image_ctx
, m_snap_id
,
136 template <typename I
>
137 void SetImageStateRequest
<I
>::handle_write_image_state(int r
) {
138 CephContext
*cct
= m_image_ctx
->cct
;
139 ldout(cct
, 20) << "r=" << r
<< dendl
;
142 lderr(cct
) << "failed to write image state: " << cpp_strerror(r
)
148 update_primary_snapshot();
151 template <typename I
>
152 void SetImageStateRequest
<I
>::update_primary_snapshot() {
153 CephContext
*cct
= m_image_ctx
->cct
;
154 ldout(cct
, 20) << dendl
;
156 librados::ObjectWriteOperation op
;
157 librbd::cls_client::mirror_image_snapshot_set_copy_progress(
158 &op
, m_snap_id
, true, 0);
160 auto aio_comp
= create_rados_callback
<
161 SetImageStateRequest
<I
>,
162 &SetImageStateRequest
<I
>::handle_update_primary_snapshot
>(this);
163 int r
= m_image_ctx
->md_ctx
.aio_operate(m_image_ctx
->header_oid
, aio_comp
,
169 template <typename I
>
170 void SetImageStateRequest
<I
>::handle_update_primary_snapshot(int r
) {
171 CephContext
*cct
= m_image_ctx
->cct
;
172 ldout(cct
, 20) << "r=" << r
<< dendl
;
175 lderr(cct
) << "failed to update primary snapshot: " << cpp_strerror(r
)
184 template <typename I
>
185 void SetImageStateRequest
<I
>::finish(int r
) {
186 CephContext
*cct
= m_image_ctx
->cct
;
187 ldout(cct
, 20) << "r=" << r
<< dendl
;
189 m_on_finish
->complete(r
);
193 } // namespace snapshot
194 } // namespace mirror
195 } // namespace librbd
197 template class librbd::mirror::snapshot::SetImageStateRequest
<librbd::ImageCtx
>;