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