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