]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/deep_copy/SnapshotCreateRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / deep_copy / SnapshotCreateRequest.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 "SetHeadRequest.h"
5 #include "SnapshotCreateRequest.h"
6 #include "common/errno.h"
7 #include "cls/rbd/cls_rbd_client.h"
8 #include "cls/rbd/cls_rbd_types.h"
9 #include "librbd/ExclusiveLock.h"
10 #include "librbd/ObjectMap.h"
11 #include "librbd/Operations.h"
12 #include "librbd/Utils.h"
13 #include "osdc/Striper.h"
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::deep_copy::SnapshotCreateRequest: " \
18 << this << " " << __func__ << ": "
19
20 namespace librbd {
21 namespace deep_copy {
22
23 using librbd::util::create_context_callback;
24 using librbd::util::create_rados_callback;
25
26 template <typename I>
27 SnapshotCreateRequest<I>::SnapshotCreateRequest(
28 I *dst_image_ctx, const std::string &snap_name,
29 const cls::rbd::SnapshotNamespace &snap_namespace,
30 uint64_t size, const cls::rbd::ParentImageSpec &spec,
31 uint64_t parent_overlap, Context *on_finish)
32 : m_dst_image_ctx(dst_image_ctx), m_snap_name(snap_name),
33 m_snap_namespace(snap_namespace), m_size(size),
34 m_parent_spec(spec), m_parent_overlap(parent_overlap),
35 m_on_finish(on_finish), m_cct(dst_image_ctx->cct) {
36 }
37
38 template <typename I>
39 void SnapshotCreateRequest<I>::send() {
40 send_set_head();
41 }
42
43 template <typename I>
44 void SnapshotCreateRequest<I>::send_set_head() {
45 ldout(m_cct, 20) << dendl;
46
47 auto ctx = create_context_callback<
48 SnapshotCreateRequest<I>, &SnapshotCreateRequest<I>::handle_set_head>(this);
49 auto req = SetHeadRequest<I>::create(m_dst_image_ctx, m_size, m_parent_spec,
50 m_parent_overlap, ctx);
51 req->send();
52 }
53
54 template <typename I>
55 void SnapshotCreateRequest<I>::handle_set_head(int r) {
56 ldout(m_cct, 20) << "r=" << r << dendl;
57
58 if (r < 0) {
59 lderr(m_cct) << "failed to set head: " << cpp_strerror(r) << dendl;
60 finish(r);
61 return;
62 }
63
64 send_create_snap();
65 }
66
67 template <typename I>
68 void SnapshotCreateRequest<I>::send_create_snap() {
69 ldout(m_cct, 20) << "snap_name=" << m_snap_name << dendl;
70
71 int r;
72 auto finish_op_ctx = start_lock_op(&r);
73 if (finish_op_ctx == nullptr) {
74 lderr(m_cct) << "lost exclusive lock" << dendl;
75 finish(r);
76 return;
77 }
78
79 auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
80 handle_create_snap(r);
81 finish_op_ctx->complete(0);
82 });
83 std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
84 m_dst_image_ctx->operations->execute_snap_create(m_snap_namespace,
85 m_snap_name.c_str(),
86 ctx,
87 0U, true);
88 }
89
90 template <typename I>
91 void SnapshotCreateRequest<I>::handle_create_snap(int r) {
92 ldout(m_cct, 20) << "r=" << r << dendl;
93
94 if (r < 0) {
95 lderr(m_cct) << "failed to create snapshot '" << m_snap_name << "': "
96 << cpp_strerror(r) << dendl;
97 finish(r);
98 return;
99 }
100
101 send_create_object_map();
102 }
103 template <typename I>
104 void SnapshotCreateRequest<I>::send_create_object_map() {
105
106 if (!m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
107 finish(0);
108 return;
109 }
110
111 m_dst_image_ctx->image_lock.lock_shared();
112 auto snap_it = m_dst_image_ctx->snap_ids.find(
113 {cls::rbd::UserSnapshotNamespace(), m_snap_name});
114 if (snap_it == m_dst_image_ctx->snap_ids.end()) {
115 lderr(m_cct) << "failed to locate snap: " << m_snap_name << dendl;
116 m_dst_image_ctx->image_lock.unlock_shared();
117 finish(-ENOENT);
118 return;
119 }
120 librados::snap_t local_snap_id = snap_it->second;
121 m_dst_image_ctx->image_lock.unlock_shared();
122
123 std::string object_map_oid(librbd::ObjectMap<>::object_map_name(
124 m_dst_image_ctx->id, local_snap_id));
125 uint64_t object_count = Striper::get_num_objects(m_dst_image_ctx->layout,
126 m_size);
127 ldout(m_cct, 20) << "object_map_oid=" << object_map_oid << ", "
128 << "object_count=" << object_count << dendl;
129
130 // initialize an empty object map of the correct size (object sync
131 // will populate the object map)
132 librados::ObjectWriteOperation op;
133 librbd::cls_client::object_map_resize(&op, object_count, OBJECT_NONEXISTENT);
134
135 int r;
136 auto finish_op_ctx = start_lock_op(&r);
137 if (finish_op_ctx == nullptr) {
138 lderr(m_cct) << "lost exclusive lock" << dendl;
139 finish(r);
140 return;
141 }
142
143 auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
144 handle_create_object_map(r);
145 finish_op_ctx->complete(0);
146 });
147 librados::AioCompletion *comp = create_rados_callback(ctx);
148 r = m_dst_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op);
149 ceph_assert(r == 0);
150 comp->release();
151 }
152
153 template <typename I>
154 void SnapshotCreateRequest<I>::handle_create_object_map(int r) {
155 ldout(m_cct, 20) << "r=" << r << dendl;
156
157 if (r < 0) {
158 lderr(m_cct) << "failed to create object map: " << cpp_strerror(r)
159 << dendl;
160 finish(r);
161 return;
162 }
163
164 finish(0);
165 }
166
167 template <typename I>
168 Context *SnapshotCreateRequest<I>::start_lock_op(int* r) {
169 std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
170 if (m_dst_image_ctx->exclusive_lock == nullptr) {
171 return new LambdaContext([](int r) {});
172 }
173 return m_dst_image_ctx->exclusive_lock->start_op(r);
174 }
175
176 template <typename I>
177 void SnapshotCreateRequest<I>::finish(int r) {
178 ldout(m_cct, 20) << "r=" << r << dendl;
179
180 m_on_finish->complete(r);
181 delete this;
182 }
183
184 } // namespace deep_copy
185 } // namespace librbd
186
187 template class librbd::deep_copy::SnapshotCreateRequest<librbd::ImageCtx>;