]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/crypto/LoadRequest.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / librbd / crypto / LoadRequest.cc
CommitLineData
f67539c2
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 "LoadRequest.h"
5
6#include "common/dout.h"
7#include "common/errno.h"
8#include "librbd/Utils.h"
9#include "librbd/ImageCtx.h"
1e59de90
TL
10#include "librbd/crypto/EncryptionFormat.h"
11#include "librbd/crypto/Types.h"
f67539c2 12#include "librbd/crypto/Utils.h"
1e59de90
TL
13#include "librbd/io/AioCompletion.h"
14#include "librbd/io/ImageDispatcherInterface.h"
15#include "librbd/io/ImageDispatchSpec.h"
16#include "librbd/io/Types.h"
f67539c2
TL
17
18#define dout_subsys ceph_subsys_rbd
19#undef dout_prefix
20#define dout_prefix *_dout << "librbd::crypto::LoadRequest: " << this \
21 << " " << __func__ << ": "
22
23namespace librbd {
24namespace crypto {
25
26using librbd::util::create_context_callback;
27
28template <typename I>
29LoadRequest<I>::LoadRequest(
1e59de90 30 I* image_ctx, std::vector<EncryptionFormat>&& formats,
f67539c2 31 Context* on_finish) : m_image_ctx(image_ctx),
1e59de90
TL
32 m_on_finish(on_finish),
33 m_format_idx(0),
34 m_is_current_format_cloned(false),
35 m_formats(std::move(formats)) {
f67539c2
TL
36}
37
38template <typename I>
39void LoadRequest<I>::send() {
1e59de90
TL
40 if (m_formats.empty()) {
41 lderr(m_image_ctx->cct) << "no encryption formats were specified" << dendl;
42 finish(-EINVAL);
43 return;
44 }
45
46 ldout(m_image_ctx->cct, 20) << "got " << m_formats.size() << " formats"
47 << dendl;
48
49 if (m_image_ctx->encryption_format.get() != nullptr) {
f67539c2
TL
50 lderr(m_image_ctx->cct) << "encryption already loaded" << dendl;
51 finish(-EEXIST);
52 return;
53 }
54
55 auto ictx = m_image_ctx;
56 while (ictx != nullptr) {
57 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
58 lderr(m_image_ctx->cct) << "cannot use encryption with journal."
59 << " image name: " << ictx->name << dendl;
60 finish(-ENOTSUP);
61 return;
62 }
63 ictx = ictx->parent;
64 }
65
1e59de90
TL
66 m_current_image_ctx = m_image_ctx;
67 flush();
68}
69
70template <typename I>
71void LoadRequest<I>::flush() {
72 auto ctx = create_context_callback<
73 LoadRequest<I>, &LoadRequest<I>::handle_flush>(this);
74 auto aio_comp = io::AioCompletion::create_and_start(
75 ctx, librbd::util::get_image_ctx(m_image_ctx), io::AIO_TYPE_FLUSH);
76 auto req = io::ImageDispatchSpec::create_flush(
77 *m_image_ctx, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
78 io::FLUSH_SOURCE_INTERNAL, {});
79 req->send();
80}
81
82template <typename I>
83void LoadRequest<I>::handle_flush(int r) {
84 ldout(m_image_ctx->cct, 20) << "r=" << r << dendl;
85
86 if (r < 0) {
87 lderr(m_image_ctx->cct) << "failed to flush image" << dendl;
88 finish(r);
89 return;
90 }
91
92 load();
93}
94
95template <typename I>
96void LoadRequest<I>::load() {
97 ldout(m_image_ctx->cct, 20) << "format_idx=" << m_format_idx << dendl;
98
99 m_detected_format_name = "";
100 auto ctx = create_context_callback<
101 LoadRequest<I>, &LoadRequest<I>::handle_load>(this);
102 m_formats[m_format_idx]->load(m_current_image_ctx, &m_detected_format_name,
103 ctx);
104}
105
106template <typename I>
107void LoadRequest<I>::handle_load(int r) {
108 ldout(m_image_ctx->cct, 20) << "r=" << r << dendl;
109
110 if (r < 0) {
111 if (m_is_current_format_cloned &&
112 m_detected_format_name == UNKNOWN_FORMAT) {
113 // encryption format was not detected, assume plaintext
114 ldout(m_image_ctx->cct, 5) << "assuming plaintext for image "
115 << m_current_image_ctx->name << dendl;
116 m_formats.pop_back();
117 invalidate_cache();
118 return;
119 }
120
121 lderr(m_image_ctx->cct) << "failed to load encryption. image name: "
122 << m_current_image_ctx->name << dendl;
123 finish(r);
124 return;
125 }
126
127 ldout(m_image_ctx->cct, 5) << "loaded format " << m_detected_format_name
128 << (m_is_current_format_cloned ? " (cloned)" : "")
129 << " for image " << m_current_image_ctx->name
130 << dendl;
131
132 m_format_idx++;
133 m_current_image_ctx = m_current_image_ctx->parent;
134 if (m_current_image_ctx != nullptr) {
135 // move on to loading parent
136 if (m_format_idx >= m_formats.size()) {
137 // try to load next ancestor using the same format
138 ldout(m_image_ctx->cct, 20) << "cloning format" << dendl;
139 m_is_current_format_cloned = true;
140 m_formats.push_back(m_formats[m_formats.size() - 1]->clone());
141 }
142
143 load();
144 } else {
145 if (m_formats.size() != m_format_idx) {
146 lderr(m_image_ctx->cct) << "got " << m_formats.size()
147 << " encryption specs to load, "
148 << "but image has " << m_format_idx - 1
149 << " ancestors" << dendl;
150 finish(-EINVAL);
151 return;
152 }
153
154 invalidate_cache();
155 }
156}
157
158template <typename I>
159void LoadRequest<I>::invalidate_cache() {
f67539c2 160 auto ctx = create_context_callback<
1e59de90
TL
161 LoadRequest<I>, &LoadRequest<I>::handle_invalidate_cache>(this);
162 m_image_ctx->io_image_dispatcher->invalidate_cache(ctx);
163}
164
165template <typename I>
166void LoadRequest<I>::handle_invalidate_cache(int r) {
167 ldout(m_image_ctx->cct, 20) << "r=" << r << dendl;
168
169 if (r < 0) {
170 lderr(m_image_ctx->cct) << "failed to invalidate image cache" << dendl;
171 }
172
173 finish(r);
f67539c2
TL
174}
175
176template <typename I>
177void LoadRequest<I>::finish(int r) {
1e59de90 178 ldout(m_image_ctx->cct, 20) << "r=" << r << dendl;
f67539c2
TL
179
180 if (r == 0) {
f67539c2 181 auto ictx = m_image_ctx;
1e59de90
TL
182 for (auto& format : m_formats) {
183 util::set_crypto(ictx, std::move(format));
f67539c2
TL
184 ictx = ictx->parent;
185 }
186 }
187
188 m_on_finish->complete(r);
189 delete this;
190}
191
192} // namespace crypto
193} // namespace librbd
194
195template class librbd::crypto::LoadRequest<librbd::ImageCtx>;