]> git.proxmox.com Git - ceph.git/blame - ceph/src/global/global_init.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / global / global_init.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
f67539c2 15#include <filesystem>
f67539c2 16#include "common/async/context_pool.h"
7c673cae
FG
17#include "common/ceph_argparse.h"
18#include "common/code_environment.h"
19#include "common/config.h"
20#include "common/debug.h"
21#include "common/errno.h"
22#include "common/signal.h"
23#include "common/version.h"
24#include "erasure-code/ErasureCodePlugin.h"
25#include "global/global_context.h"
26#include "global/global_init.h"
27#include "global/pidfile.h"
28#include "global/signal_handler.h"
29#include "include/compat.h"
30#include "include/str_list.h"
11fdf7f2 31#include "mon/MonClient.h"
7c673cae 32
f67539c2 33#ifndef _WIN32
7c673cae
FG
34#include <pwd.h>
35#include <grp.h>
f67539c2 36#endif
7c673cae
FG
37#include <errno.h>
38
39#ifdef HAVE_SYS_PRCTL_H
40#include <sys/prctl.h>
41#endif
42
43#define dout_context g_ceph_context
44#define dout_subsys ceph_subsys_
f67539c2 45
20effc67
TL
46namespace fs = std::filesystem;
47
f67539c2
TL
48using std::cerr;
49using std::string;
50
7c673cae
FG
51static void global_init_set_globals(CephContext *cct)
52{
53 g_ceph_context = cct;
11fdf7f2 54 get_process_name(g_process_name, sizeof(g_process_name));
7c673cae
FG
55}
56
57static void output_ceph_version()
58{
59 char buf[1024];
60 snprintf(buf, sizeof(buf), "%s, process %s, pid %d",
61 pretty_version_to_str().c_str(),
62 get_process_name_cpp().c_str(), getpid());
63 generic_dout(0) << buf << dendl;
64}
65
66static const char* c_str_or_null(const std::string &str)
67{
68 if (str.empty())
69 return NULL;
70 return str.c_str();
71}
72
73static int chown_path(const std::string &pathname, const uid_t owner, const gid_t group,
74 const std::string &uid_str, const std::string &gid_str)
75{
f67539c2
TL
76 #ifdef _WIN32
77 return 0;
78 #else
79
7c673cae
FG
80 const char *pathname_cstr = c_str_or_null(pathname);
81
82 if (!pathname_cstr) {
83 return 0;
84 }
85
86 int r = ::chown(pathname_cstr, owner, group);
87
88 if (r < 0) {
89 r = -errno;
90 cerr << "warning: unable to chown() " << pathname << " as "
91 << uid_str << ":" << gid_str << ": " << cpp_strerror(r) << std::endl;
92 }
93
94 return r;
f67539c2 95 #endif
7c673cae
FG
96}
97
11fdf7f2
TL
98void global_pre_init(
99 const std::map<std::string,std::string> *defaults,
100 std::vector < const char* >& args,
101 uint32_t module_type, code_environment_t code_env,
102 int flags)
7c673cae
FG
103{
104 std::string conf_file_list;
105 std::string cluster = "";
11fdf7f2 106
9f95a23c
TL
107 // ensure environment arguments are included in early processing
108 env_to_vec(args);
109
11fdf7f2
TL
110 CephInitParameters iparams = ceph_argparse_early_args(
111 args, module_type,
112 &cluster, &conf_file_list);
113
b32b8144 114 CephContext *cct = common_preinit(iparams, code_env, flags);
7c673cae
FG
115 cct->_conf->cluster = cluster;
116 global_init_set_globals(cct);
11fdf7f2 117 auto& conf = cct->_conf;
7c673cae 118
11fdf7f2
TL
119 if (flags & (CINIT_FLAG_NO_DEFAULT_CONFIG_FILE|
120 CINIT_FLAG_NO_MON_CONFIG)) {
121 conf->no_mon_config = true;
122 }
123
124 // alternate defaults
125 if (defaults) {
126 for (auto& i : *defaults) {
127 conf.set_val_default(i.first, i.second);
128 }
129 }
7c673cae 130
9f95a23c
TL
131 if (conf.get_val<bool>("no_config_file")) {
132 flags |= CINIT_FLAG_NO_DEFAULT_CONFIG_FILE;
133 }
134
11fdf7f2
TL
135 int ret = conf.parse_config_files(c_str_or_null(conf_file_list),
136 &cerr, flags);
7c673cae 137 if (ret == -EDOM) {
11fdf7f2
TL
138 cct->_log->flush();
139 cerr << "global_init: error parsing config file." << std::endl;
7c673cae
FG
140 _exit(1);
141 }
142 else if (ret == -ENOENT) {
143 if (!(flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)) {
144 if (conf_file_list.length()) {
11fdf7f2
TL
145 cct->_log->flush();
146 cerr << "global_init: unable to open config file from search list "
147 << conf_file_list << std::endl;
7c673cae
FG
148 _exit(1);
149 } else {
9f95a23c
TL
150 cerr << "did not load config file, using default settings."
151 << std::endl;
7c673cae
FG
152 }
153 }
154 }
155 else if (ret) {
11fdf7f2 156 cct->_log->flush();
f67539c2
TL
157 cerr << "global_init: error reading config file. "
158 << conf.get_parse_error() << std::endl;
7c673cae
FG
159 _exit(1);
160 }
161
11fdf7f2
TL
162 // environment variables override (CEPH_ARGS, CEPH_KEYRING)
163 conf.parse_env(cct->get_module_type());
164
165 // command line (as passed by caller)
166 conf.parse_argv(args);
7c673cae 167
11fdf7f2
TL
168 if (!cct->_log->is_started()) {
169 cct->_log->start();
170 }
171
172 // do the --show-config[-val], if present in argv
173 conf.do_argv_commands();
7c673cae
FG
174
175 // Now we're ready to complain about config file parse errors
9f95a23c 176 g_conf().complain_about_parse_error(g_ceph_context);
7c673cae
FG
177}
178
179boost::intrusive_ptr<CephContext>
11fdf7f2 180global_init(const std::map<std::string,std::string> *defaults,
7c673cae
FG
181 std::vector < const char* >& args,
182 uint32_t module_type, code_environment_t code_env,
f67539c2 183 int flags, bool run_pre_init)
7c673cae
FG
184{
185 // Ensure we're not calling the global init functions multiple times.
186 static bool first_run = true;
187 if (run_pre_init) {
188 // We will run pre_init from here (default).
11fdf7f2
TL
189 ceph_assert(!g_ceph_context && first_run);
190 global_pre_init(defaults, args, module_type, code_env, flags);
7c673cae
FG
191 } else {
192 // Caller should have invoked pre_init manually.
11fdf7f2 193 ceph_assert(g_ceph_context && first_run);
7c673cae
FG
194 }
195 first_run = false;
196
197 // Verify flags have not changed if global_pre_init() has been called
198 // manually. If they have, update them.
199 if (g_ceph_context->get_init_flags() != flags) {
200 g_ceph_context->set_init_flags(flags);
201 }
202
f67539c2 203 #ifndef _WIN32
7c673cae
FG
204 // signal stuff
205 int siglist[] = { SIGPIPE, 0 };
206 block_signals(siglist, NULL);
f67539c2 207 #endif
7c673cae 208
11fdf7f2 209 if (g_conf()->fatal_signal_handlers) {
7c673cae 210 install_standard_sighandlers();
11fdf7f2 211 }
f67539c2 212 ceph::register_assert_context(g_ceph_context);
7c673cae 213
11fdf7f2 214 if (g_conf()->log_flush_on_exit)
7c673cae
FG
215 g_ceph_context->_log->set_flush_on_exit();
216
217 // drop privileges?
20effc67 218 std::ostringstream priv_ss;
f67539c2
TL
219
220 #ifndef _WIN32
7c673cae
FG
221 // consider --setuser root a no-op, even if we're not root
222 if (getuid() != 0) {
11fdf7f2
TL
223 if (g_conf()->setuser.length()) {
224 cerr << "ignoring --setuser " << g_conf()->setuser << " since I am not root"
7c673cae
FG
225 << std::endl;
226 }
11fdf7f2
TL
227 if (g_conf()->setgroup.length()) {
228 cerr << "ignoring --setgroup " << g_conf()->setgroup
7c673cae
FG
229 << " since I am not root" << std::endl;
230 }
11fdf7f2
TL
231 } else if (g_conf()->setgroup.length() ||
232 g_conf()->setuser.length()) {
7c673cae
FG
233 uid_t uid = 0; // zero means no change; we can only drop privs here.
234 gid_t gid = 0;
235 std::string uid_string;
236 std::string gid_string;
eafe8130 237 std::string home_directory;
11fdf7f2 238 if (g_conf()->setuser.length()) {
eafe8130
TL
239 char buf[4096];
240 struct passwd pa;
241 struct passwd *p = 0;
242
11fdf7f2 243 uid = atoi(g_conf()->setuser.c_str());
eafe8130
TL
244 if (uid) {
245 getpwuid_r(uid, &pa, buf, sizeof(buf), &p);
246 } else {
11fdf7f2 247 getpwnam_r(g_conf()->setuser.c_str(), &pa, buf, sizeof(buf), &p);
eafe8130 248 if (!p) {
11fdf7f2 249 cerr << "unable to look up user '" << g_conf()->setuser << "'"
7c673cae
FG
250 << std::endl;
251 exit(1);
eafe8130
TL
252 }
253
254 uid = p->pw_uid;
255 gid = p->pw_gid;
256 uid_string = g_conf()->setuser;
257 }
258
259 if (p && p->pw_dir != nullptr) {
260 home_directory = std::string(p->pw_dir);
7c673cae
FG
261 }
262 }
11fdf7f2
TL
263 if (g_conf()->setgroup.length() > 0) {
264 gid = atoi(g_conf()->setgroup.c_str());
7c673cae
FG
265 if (!gid) {
266 char buf[4096];
267 struct group gr;
268 struct group *g = 0;
11fdf7f2 269 getgrnam_r(g_conf()->setgroup.c_str(), &gr, buf, sizeof(buf), &g);
7c673cae 270 if (!g) {
11fdf7f2 271 cerr << "unable to look up group '" << g_conf()->setgroup << "'"
7c673cae
FG
272 << ": " << cpp_strerror(errno) << std::endl;
273 exit(1);
274 }
275 gid = g->gr_gid;
11fdf7f2 276 gid_string = g_conf()->setgroup;
7c673cae
FG
277 }
278 }
279 if ((uid || gid) &&
11fdf7f2 280 g_conf()->setuser_match_path.length()) {
7c673cae 281 // induce early expansion of setuser_match_path config option
11fdf7f2
TL
282 string match_path = g_conf()->setuser_match_path;
283 g_conf().early_expand_meta(match_path, &cerr);
7c673cae
FG
284 struct stat st;
285 int r = ::stat(match_path.c_str(), &st);
286 if (r < 0) {
287 cerr << "unable to stat setuser_match_path "
11fdf7f2 288 << g_conf()->setuser_match_path
7c673cae
FG
289 << ": " << cpp_strerror(errno) << std::endl;
290 exit(1);
291 }
292 if ((uid && uid != st.st_uid) ||
293 (gid && gid != st.st_gid)) {
294 cerr << "WARNING: will not setuid/gid: " << match_path
295 << " owned by " << st.st_uid << ":" << st.st_gid
296 << " and not requested " << uid << ":" << gid
297 << std::endl;
298 uid = 0;
299 gid = 0;
300 uid_string.erase();
301 gid_string.erase();
302 } else {
303 priv_ss << "setuser_match_path "
304 << match_path << " owned by "
305 << st.st_uid << ":" << st.st_gid << ". ";
306 }
307 }
308 g_ceph_context->set_uid_gid(uid, gid);
309 g_ceph_context->set_uid_gid_strings(uid_string, gid_string);
310 if ((flags & CINIT_FLAG_DEFER_DROP_PRIVILEGES) == 0) {
311 if (setgid(gid) != 0) {
312 cerr << "unable to setgid " << gid << ": " << cpp_strerror(errno)
313 << std::endl;
314 exit(1);
315 }
316 if (setuid(uid) != 0) {
317 cerr << "unable to setuid " << uid << ": " << cpp_strerror(errno)
318 << std::endl;
319 exit(1);
320 }
eafe8130
TL
321 if (setenv("HOME", home_directory.c_str(), 1) != 0) {
322 cerr << "warning: unable to set HOME to " << home_directory << ": "
323 << cpp_strerror(errno) << std::endl;
324 }
7c673cae
FG
325 priv_ss << "set uid:gid to " << uid << ":" << gid << " (" << uid_string << ":" << gid_string << ")";
326 } else {
327 priv_ss << "deferred set uid:gid to " << uid << ":" << gid << " (" << uid_string << ":" << gid_string << ")";
328 }
329 }
f67539c2 330 #endif /* _WIN32 */
7c673cae
FG
331
332#if defined(HAVE_SYS_PRCTL_H)
333 if (prctl(PR_SET_DUMPABLE, 1) == -1) {
334 cerr << "warning: unable to set dumpable flag: " << cpp_strerror(errno) << std::endl;
335 }
92f5a8d4
TL
336# if defined(PR_SET_THP_DISABLE)
337 if (!g_conf().get_val<bool>("thp") && prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0) == -1) {
338 cerr << "warning: unable to disable THP: " << cpp_strerror(errno) << std::endl;
339 }
340# endif
7c673cae
FG
341#endif
342
9f95a23c
TL
343 //
344 // Utterly important to run first network connection after setuid().
345 // In case of rdma transport uverbs kernel module starts returning
346 // -EACCESS on each operation if credentials has been changed, see
347 // callers of ib_safe_file_access() for details.
348 //
349 // fork() syscall also matters, so daemonization won't work in case
350 // of rdma.
351 //
352 if (!g_conf()->no_mon_config) {
353 // make sure our mini-session gets legacy values
354 g_conf().apply_changes(nullptr);
355
f67539c2
TL
356 ceph::async::io_context_pool cp(1);
357 MonClient mc_bootstrap(g_ceph_context, cp);
9f95a23c 358 if (mc_bootstrap.get_monmap_and_config() < 0) {
f67539c2 359 cp.stop();
9f95a23c
TL
360 g_ceph_context->_log->flush();
361 cerr << "failed to fetch mon config (--no-mon-config to skip)"
362 << std::endl;
363 _exit(1);
364 }
f67539c2 365 cp.stop();
9f95a23c
TL
366 }
367
7c673cae 368 // Expand metavariables. Invoke configuration observers. Open log file.
11fdf7f2 369 g_conf().apply_changes(nullptr);
7c673cae 370
11fdf7f2 371 if (g_conf()->run_dir.length() &&
7c673cae
FG
372 code_env == CODE_ENVIRONMENT_DAEMON &&
373 !(flags & CINIT_FLAG_NO_DAEMON_ACTIONS)) {
f67539c2
TL
374
375 if (!fs::exists(g_conf()->run_dir.c_str())) {
376 std::error_code ec;
377 if (!fs::create_directory(g_conf()->run_dir, ec)) {
378 cerr << "warning: unable to create " << g_conf()->run_dir
379 << ec.message() << std::endl;
380 }
381 fs::permissions(
382 g_conf()->run_dir.c_str(),
383 fs::perms::owner_all |
384 fs::perms::group_read | fs::perms::group_exec |
385 fs::perms::others_read | fs::perms::others_exec);
7c673cae
FG
386 }
387 }
388
7c673cae
FG
389 // call all observers now. this has the side-effect of configuring
390 // and opening the log file immediately.
11fdf7f2 391 g_conf().call_all_observers();
7c673cae
FG
392
393 if (priv_ss.str().length()) {
394 dout(0) << priv_ss.str() << dendl;
395 }
396
397 if ((flags & CINIT_FLAG_DEFER_DROP_PRIVILEGES) &&
398 (g_ceph_context->get_set_uid() || g_ceph_context->get_set_gid())) {
399 // Fix ownership on log files and run directories if needed.
400 // Admin socket files are chown()'d during the common init path _after_
401 // the service thread has been started. This is sadly a bit of a hack :(
11fdf7f2 402 chown_path(g_conf()->run_dir,
7c673cae
FG
403 g_ceph_context->get_set_uid(),
404 g_ceph_context->get_set_gid(),
405 g_ceph_context->get_set_uid_string(),
406 g_ceph_context->get_set_gid_string());
407 g_ceph_context->_log->chown_log_file(
408 g_ceph_context->get_set_uid(),
409 g_ceph_context->get_set_gid());
410 }
411
412 // Now we're ready to complain about config file parse errors
9f95a23c 413 g_conf().complain_about_parse_error(g_ceph_context);
7c673cae
FG
414
415 // test leak checking
11fdf7f2 416 if (g_conf()->debug_deliberately_leak_memory) {
7c673cae
FG
417 derr << "deliberately leaking some memory" << dendl;
418 char *s = new char[1234567];
419 (void)s;
420 // cppcheck-suppress memleak
421 }
422
423 if (code_env == CODE_ENVIRONMENT_DAEMON && !(flags & CINIT_FLAG_NO_DAEMON_ACTIONS))
424 output_ceph_version();
425
426 if (g_ceph_context->crush_location.init_on_startup()) {
427 cerr << " failed to init_on_startup : " << cpp_strerror(errno) << std::endl;
428 exit(1);
429 }
430
431 return boost::intrusive_ptr<CephContext>{g_ceph_context, false};
432}
7c673cae 433
7c673cae
FG
434void global_print_banner(void)
435{
436 output_ceph_version();
437}
438
439int global_init_prefork(CephContext *cct)
440{
441 if (g_code_env != CODE_ENVIRONMENT_DAEMON)
442 return -1;
443
11fdf7f2 444 const auto& conf = cct->_conf;
7c673cae
FG
445 if (!conf->daemonize) {
446
9f95a23c 447 if (pidfile_write(conf->pid_file) < 0)
7c673cae
FG
448 exit(1);
449
450 if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) &&
451 (cct->get_set_uid() || cct->get_set_gid())) {
452 chown_path(conf->pid_file, cct->get_set_uid(), cct->get_set_gid(),
453 cct->get_set_uid_string(), cct->get_set_gid_string());
454 }
455
456 return -1;
457 }
458
459 cct->notify_pre_fork();
460 // stop log thread
461 cct->_log->flush();
462 cct->_log->stop();
463 return 0;
464}
465
466void global_init_daemonize(CephContext *cct)
467{
468 if (global_init_prefork(cct) < 0)
469 return;
470
f67539c2 471#if !defined(_AIX) && !defined(_WIN32)
7c673cae
FG
472 int ret = daemon(1, 1);
473 if (ret) {
474 ret = errno;
475 derr << "global_init_daemonize: BUG: daemon error: "
476 << cpp_strerror(ret) << dendl;
477 exit(1);
478 }
479
480 global_init_postfork_start(cct);
481 global_init_postfork_finish(cct);
482#else
483# warning daemon not supported on aix
484#endif
485}
486
1adf2230
AA
487int reopen_as_null(CephContext *cct, int fd)
488{
f67539c2 489 int newfd = open(DEV_NULL, O_RDONLY | O_CLOEXEC);
1adf2230
AA
490 if (newfd < 0) {
491 int err = errno;
492 lderr(cct) << __func__ << " failed to open /dev/null: " << cpp_strerror(err)
493 << dendl;
494 return -1;
495 }
496 // atomically dup newfd to target fd. target fd is implicitly closed if
497 // open and atomically replaced; see man dup2
498 int r = dup2(newfd, fd);
499 if (r < 0) {
500 int err = errno;
501 lderr(cct) << __func__ << " failed to dup2 " << fd << ": "
502 << cpp_strerror(err) << dendl;
503 return -1;
504 }
505 // close newfd (we cloned it to target fd)
506 VOID_TEMP_FAILURE_RETRY(close(newfd));
91327a77 507 // N.B. FD_CLOEXEC is cleared on fd (see dup2(2))
1adf2230
AA
508 return 0;
509}
510
7c673cae
FG
511void global_init_postfork_start(CephContext *cct)
512{
adb31ebb
TL
513 // reexpand the meta in child process
514 cct->_conf.finalize_reexpand_meta();
515
7c673cae
FG
516 // restart log thread
517 cct->_log->start();
518 cct->notify_post_fork();
519
520 /* This is the old trick where we make file descriptors 0, 1, and possibly 2
521 * point to /dev/null.
522 *
523 * We have to do this because otherwise some arbitrary call to open() later
524 * in the program might get back one of these file descriptors. It's hard to
525 * guarantee that nobody ever writes to stdout, even though they're not
526 * supposed to.
527 */
1adf2230 528 reopen_as_null(cct, STDIN_FILENO);
7c673cae 529
11fdf7f2 530 const auto& conf = cct->_conf;
9f95a23c 531 if (pidfile_write(conf->pid_file) < 0)
7c673cae
FG
532 exit(1);
533
534 if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) &&
535 (cct->get_set_uid() || cct->get_set_gid())) {
536 chown_path(conf->pid_file, cct->get_set_uid(), cct->get_set_gid(),
537 cct->get_set_uid_string(), cct->get_set_gid_string());
538 }
539}
540
541void global_init_postfork_finish(CephContext *cct)
542{
28e407b8
AA
543 /* We only close stdout+stderr once the caller decides the daemonization
544 * process is finished. This way we can allow error or other messages to be
7c673cae
FG
545 * propagated in a manner that the user is able to see.
546 */
547 if (!(cct->get_init_flags() & CINIT_FLAG_NO_CLOSE_STDERR)) {
548 int ret = global_init_shutdown_stderr(cct);
549 if (ret) {
550 derr << "global_init_daemonize: global_init_shutdown_stderr failed with "
551 << "error code " << ret << dendl;
552 exit(1);
553 }
554 }
28e407b8 555
1adf2230 556 reopen_as_null(cct, STDOUT_FILENO);
28e407b8 557
7c673cae
FG
558 ldout(cct, 1) << "finished global_init_daemonize" << dendl;
559}
560
561
562void global_init_chdir(const CephContext *cct)
563{
11fdf7f2 564 const auto& conf = cct->_conf;
7c673cae
FG
565 if (conf->chdir.empty())
566 return;
567 if (::chdir(conf->chdir.c_str())) {
568 int err = errno;
569 derr << "global_init_chdir: failed to chdir to directory: '"
570 << conf->chdir << "': " << cpp_strerror(err) << dendl;
571 }
572}
573
574/* Map stderr to /dev/null. This isn't really re-entrant; we rely on the old unix
575 * behavior that the file descriptor that gets assigned is the lowest
576 * available one.
577 */
578int global_init_shutdown_stderr(CephContext *cct)
579{
1adf2230 580 reopen_as_null(cct, STDERR_FILENO);
11fdf7f2
TL
581 int l = cct->_conf->err_to_stderr ? -1 : -2;
582 cct->_log->set_stderr_level(l, l);
7c673cae
FG
583 return 0;
584}
585
586int global_init_preload_erasure_code(const CephContext *cct)
587{
11fdf7f2 588 const auto& conf = cct->_conf;
7c673cae
FG
589 string plugins = conf->osd_erasure_code_plugins;
590
591 // validate that this is a not a legacy plugin
f67539c2 592 std::list<string> plugins_list;
7c673cae 593 get_str_list(plugins, plugins_list);
f67539c2 594 for (auto i = plugins_list.begin(); i != plugins_list.end(); ++i) {
7c673cae
FG
595 string plugin_name = *i;
596 string replacement = "";
597
598 if (plugin_name == "jerasure_generic" ||
599 plugin_name == "jerasure_sse3" ||
600 plugin_name == "jerasure_sse4" ||
601 plugin_name == "jerasure_neon") {
602 replacement = "jerasure";
603 }
604 else if (plugin_name == "shec_generic" ||
605 plugin_name == "shec_sse3" ||
606 plugin_name == "shec_sse4" ||
607 plugin_name == "shec_neon") {
608 replacement = "shec";
609 }
610
611 if (replacement != "") {
612 dout(0) << "WARNING: osd_erasure_code_plugins contains plugin "
613 << plugin_name << " that is now deprecated. Please modify the value "
614 << "for osd_erasure_code_plugins to use " << replacement << " instead." << dendl;
615 }
616 }
617
f67539c2
TL
618 std::stringstream ss;
619 int r = ceph::ErasureCodePluginRegistry::instance().preload(
7c673cae 620 plugins,
11fdf7f2 621 conf.get_val<std::string>("erasure_code_dir"),
7c673cae
FG
622 &ss);
623 if (r)
624 derr << ss.str() << dendl;
625 else
626 dout(0) << ss.str() << dendl;
627 return r;
628}