]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/api/Config.cc
import 15.2.5
[ceph.git] / ceph / src / librbd / api / Config.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/Config.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "common/Cond.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/Utils.h"
10 #include "librbd/api/PoolMetadata.h"
11 #include "librbd/image/GetMetadataRequest.h"
12 #include <algorithm>
13 #include <boost/algorithm/string/predicate.hpp>
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::Config: " << __func__ << ": "
18
19 namespace librbd {
20 namespace api {
21
22 namespace {
23
24 const uint32_t MAX_KEYS = 64;
25
26 typedef std::map<std::string_view, std::pair<std::string, config_source_t>> Parent;
27
28 static std::set<std::string_view> EXCLUDE_OPTIONS {
29 "rbd_auto_exclusive_lock_until_manual_request",
30 "rbd_default_format",
31 "rbd_default_map_options",
32 "rbd_default_pool",
33 "rbd_discard_on_zeroed_write_same",
34 "rbd_op_thread_timeout",
35 "rbd_op_threads",
36 "rbd_tracing",
37 "rbd_validate_names",
38 "rbd_validate_pool",
39 "rbd_mirror_pool_replayers_refresh_interval",
40 "rbd_config_pool_override_update_timestamp"
41 };
42 static std::set<std::string_view> EXCLUDE_IMAGE_OPTIONS {
43 "rbd_default_clone_format",
44 "rbd_default_data_pool",
45 "rbd_default_features",
46 "rbd_default_format",
47 "rbd_default_order",
48 "rbd_default_stripe_count",
49 "rbd_default_stripe_unit",
50 "rbd_journal_order",
51 "rbd_journal_pool",
52 "rbd_journal_splay_width"
53 };
54
55 struct Options : Parent {
56 librados::IoCtx m_io_ctx;
57
58 Options(librados::IoCtx& io_ctx, bool image_apply_only_options) {
59 m_io_ctx.dup(io_ctx);
60 m_io_ctx.set_namespace("");
61
62 CephContext *cct = reinterpret_cast<CephContext *>(m_io_ctx.cct());
63
64 const std::string rbd_key_prefix("rbd_");
65 const std::string rbd_mirror_key_prefix("rbd_mirror_");
66 auto& schema = cct->_conf.get_schema();
67 for (auto& pair : schema) {
68 if (!boost::starts_with(pair.first, rbd_key_prefix)) {
69 continue;
70 } else if (EXCLUDE_OPTIONS.count(pair.first) != 0) {
71 continue;
72 } else if (image_apply_only_options &&
73 EXCLUDE_IMAGE_OPTIONS.count(pair.first) != 0) {
74 continue;
75 } else if (image_apply_only_options &&
76 boost::starts_with(pair.first, rbd_mirror_key_prefix)) {
77 continue;
78 }
79
80 insert({pair.first, {}});
81 }
82 }
83
84 int init() {
85 CephContext *cct = (CephContext *)m_io_ctx.cct();
86
87 for (auto& [k,v] : *this) {
88 int r = cct->_conf.get_val(k, &v.first);
89 ceph_assert(r == 0);
90 v.second = RBD_CONFIG_SOURCE_CONFIG;
91 }
92
93 std::string last_key = ImageCtx::METADATA_CONF_PREFIX;
94 bool more_results = true;
95
96 while (more_results) {
97 std::map<std::string, bufferlist> pairs;
98
99 int r = librbd::api::PoolMetadata<>::list(m_io_ctx, last_key, MAX_KEYS,
100 &pairs);
101 if (r < 0) {
102 return r;
103 }
104
105 if (pairs.empty()) {
106 break;
107 }
108
109 more_results = (pairs.size() == MAX_KEYS);
110 last_key = pairs.rbegin()->first;
111
112 for (auto kv : pairs) {
113 std::string key;
114 if (!util::is_metadata_config_override(kv.first, &key)) {
115 more_results = false;
116 break;
117 }
118 auto it = find(key);
119 if (it != end()) {
120 it->second = {{kv.second.c_str(), kv.second.length()},
121 RBD_CONFIG_SOURCE_POOL};
122 }
123 }
124 }
125 return 0;
126 }
127 };
128
129 } // anonymous namespace
130
131 template <typename I>
132 bool Config<I>::is_option_name(librados::IoCtx& io_ctx,
133 const std::string &name) {
134 Options opts(io_ctx, false);
135
136 return (opts.find(name) != opts.end());
137 }
138
139 template <typename I>
140 int Config<I>::list(librados::IoCtx& io_ctx,
141 std::vector<config_option_t> *options) {
142 Options opts(io_ctx, false);
143
144 int r = opts.init();
145 if (r < 0) {
146 return r;
147 }
148
149 for (auto& [k,v] : opts) {
150 options->push_back({std::string{k}, v.first, v.second});
151 }
152
153 return 0;
154 }
155
156 template <typename I>
157 bool Config<I>::is_option_name(I *image_ctx, const std::string &name) {
158 Options opts(image_ctx->md_ctx, true);
159
160 return (opts.find(name) != opts.end());
161 }
162
163 template <typename I>
164 int Config<I>::list(I *image_ctx, std::vector<config_option_t> *options) {
165 CephContext *cct = image_ctx->cct;
166 Options opts(image_ctx->md_ctx, true);
167
168 int r = opts.init();
169 if (r < 0) {
170 return r;
171 }
172
173 std::map<std::string, bufferlist> pairs;
174 C_SaferCond ctx;
175 auto req = image::GetMetadataRequest<I>::create(
176 image_ctx->md_ctx, image_ctx->header_oid, true,
177 ImageCtx::METADATA_CONF_PREFIX, ImageCtx::METADATA_CONF_PREFIX, 0U, &pairs,
178 &ctx);
179 req->send();
180
181 r = ctx.wait();
182 if (r < 0) {
183 lderr(cct) << "failed reading image metadata: " << cpp_strerror(r)
184 << dendl;
185 return r;
186 }
187
188 for (auto kv : pairs) {
189 std::string key;
190 if (!util::is_metadata_config_override(kv.first, &key)) {
191 break;
192 }
193 auto it = opts.find(key);
194 if (it != opts.end()) {
195 it->second = {{kv.second.c_str(), kv.second.length()},
196 RBD_CONFIG_SOURCE_IMAGE};
197 }
198 }
199
200 for (auto& [k,v] : opts) {
201 options->push_back({std::string{k}, v.first, v.second});
202 }
203
204 return 0;
205 }
206
207 template <typename I>
208 void Config<I>::apply_pool_overrides(librados::IoCtx& io_ctx,
209 ConfigProxy* config) {
210 CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
211
212 Options opts(io_ctx, false);
213 int r = opts.init();
214 if (r < 0) {
215 lderr(cct) << "failed to read pool config overrides: " << cpp_strerror(r)
216 << dendl;
217 return;
218 }
219
220 for (auto& [k,v] : opts) {
221 if (v.second == RBD_CONFIG_SOURCE_POOL) {
222 r = config->set_val(k, v.first);
223 if (r < 0) {
224 lderr(cct) << "failed to override pool config " << k << "="
225 << v.first << ": " << cpp_strerror(r) << dendl;
226 }
227 }
228 }
229 }
230
231 } // namespace api
232 } // namespace librbd
233
234 template class librbd::api::Config<librbd::ImageCtx>;