]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/ceph_context.cc
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / common / ceph_context.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 * Copyright (C) 2017 OVH
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
11fdf7f2
TL
16#include "common/ceph_context.h"
17
18#include <mutex>
19#include <iostream>
20
21#include <pthread.h>
22
7c673cae
FG
23#include <boost/algorithm/string.hpp>
24
25#include "include/mempool.h"
26#include "common/admin_socket.h"
7c673cae 27#include "common/code_environment.h"
11fdf7f2
TL
28#include "common/ceph_mutex.h"
29#include "common/debug.h"
30#include "common/config.h"
7c673cae 31#include "common/ceph_crypto.h"
7c673cae
FG
32#include "common/HeartbeatMap.h"
33#include "common/errno.h"
7c673cae 34#include "common/Graylog.h"
11fdf7f2
TL
35
36#include "log/Log.h"
37
7c673cae
FG
38#include "auth/Crypto.h"
39#include "include/str_list.h"
11fdf7f2
TL
40#include "common/config.h"
41#include "common/config_obs.h"
7c673cae 42#include "common/PluginRegistry.h"
11fdf7f2
TL
43#include "common/valgrind.h"
44#include "include/spinlock.h"
7c673cae 45
31f18b77 46using ceph::bufferlist;
7c673cae
FG
47using ceph::HeartbeatMap;
48
11fdf7f2
TL
49// for CINIT_FLAGS
50#include "common/common_init.h"
51
52#include <iostream>
53#include <pthread.h>
54
55#ifdef WITH_SEASTAR
56CephContext::CephContext()
57 : _conf{ceph::common::local_conf()},
58 _perf_counters_collection{ceph::common::local_perf_coll()},
59 _crypto_random{std::make_unique<CryptoRandom>()}
60{}
61
62// define the dtor in .cc as CryptoRandom is an incomplete type in the header
63CephContext::~CephContext()
64{}
65
66uint32_t CephContext::get_module_type() const
67{
68 return CEPH_ENTITY_TYPE_OSD;
69}
70
71CryptoRandom* CephContext::random() const
72{
73 return _crypto_random.get();
74}
75
76CephContext* CephContext::get()
77{
78 ++nref;
79 return this;
80}
81
82void CephContext::put()
83{
84 if (--nref == 0) {
85 delete this;
86 }
87}
88
89PerfCountersCollectionImpl* CephContext::get_perfcounters_collection()
90{
91 return _perf_counters_collection.get_perf_collection();
92}
93
94#else // WITH_SEASTAR
7c673cae
FG
95namespace {
96
97class LockdepObs : public md_config_obs_t {
98public:
f64942e4 99 explicit LockdepObs(CephContext *cct)
11fdf7f2 100 : m_cct(cct), m_registered(false), lock(ceph::make_mutex("lock_dep_obs")) {
7c673cae
FG
101 }
102 ~LockdepObs() override {
103 if (m_registered) {
104 lockdep_unregister_ceph_context(m_cct);
105 }
106 }
107
108 const char** get_tracked_conf_keys() const override {
109 static const char *KEYS[] = {"lockdep", NULL};
110 return KEYS;
111 }
112
11fdf7f2 113 void handle_conf_change(const ConfigProxy& conf,
7c673cae 114 const std::set <std::string> &changed) override {
11fdf7f2 115 std::unique_lock locker(lock);
7c673cae
FG
116 if (conf->lockdep && !m_registered) {
117 lockdep_register_ceph_context(m_cct);
118 m_registered = true;
119 } else if (!conf->lockdep && m_registered) {
120 lockdep_unregister_ceph_context(m_cct);
121 m_registered = false;
122 }
123 }
124private:
125 CephContext *m_cct;
126 bool m_registered;
11fdf7f2 127 ceph::mutex lock;
7c673cae
FG
128};
129
130class MempoolObs : public md_config_obs_t,
131 public AdminSocketHook {
132 CephContext *cct;
11fdf7f2 133 ceph::mutex lock;
7c673cae
FG
134
135public:
f64942e4 136 explicit MempoolObs(CephContext *cct)
11fdf7f2
TL
137 : cct(cct), lock(ceph::make_mutex("mem_pool_obs")) {
138 cct->_conf.add_observer(this);
7c673cae
FG
139 int r = cct->get_admin_socket()->register_command(
140 "dump_mempools",
141 "dump_mempools",
142 this,
143 "get mempool stats");
11fdf7f2 144 ceph_assert(r == 0);
7c673cae
FG
145 }
146 ~MempoolObs() override {
11fdf7f2 147 cct->_conf.remove_observer(this);
7c673cae
FG
148 cct->get_admin_socket()->unregister_command("dump_mempools");
149 }
150
151 // md_config_obs_t
152 const char** get_tracked_conf_keys() const override {
153 static const char *KEYS[] = {
154 "mempool_debug",
155 NULL
156 };
157 return KEYS;
158 }
159
11fdf7f2 160 void handle_conf_change(const ConfigProxy& conf,
7c673cae 161 const std::set <std::string> &changed) override {
11fdf7f2 162 std::unique_lock locker(lock);
7c673cae
FG
163 if (changed.count("mempool_debug")) {
164 mempool::set_debug_mode(cct->_conf->mempool_debug);
165 }
166 }
167
168 // AdminSocketHook
11fdf7f2
TL
169 bool call(std::string_view command, const cmdmap_t& cmdmap,
170 std::string_view format, bufferlist& out) override {
7c673cae
FG
171 if (command == "dump_mempools") {
172 std::unique_ptr<Formatter> f(Formatter::create(format));
173 f->open_object_section("mempools");
174 mempool::dump(f.get());
175 f->close_section();
176 f->flush(out);
177 return true;
178 }
179 return false;
180 }
181};
182
183} // anonymous namespace
184
185class CephContextServiceThread : public Thread
186{
187public:
188 explicit CephContextServiceThread(CephContext *cct)
11fdf7f2 189 : _reopen_logs(false), _exit_thread(false), _cct(cct)
7c673cae
FG
190 {
191 }
192
193 ~CephContextServiceThread() override {}
194
195 void *entry() override
196 {
197 while (1) {
11fdf7f2 198 std::unique_lock l(_lock);
eafe8130
TL
199 if (_exit_thread) {
200 break;
201 }
7c673cae
FG
202
203 if (_cct->_conf->heartbeat_interval) {
11fdf7f2
TL
204 auto interval = ceph::make_timespan(_cct->_conf->heartbeat_interval);
205 _cond.wait_for(l, interval);
7c673cae 206 } else
11fdf7f2 207 _cond.wait(l);
7c673cae
FG
208
209 if (_exit_thread) {
210 break;
211 }
212
213 if (_reopen_logs) {
214 _cct->_log->reopen_log_file();
215 _reopen_logs = false;
216 }
217 _cct->_heartbeat_map->check_touch_file();
218
219 // refresh the perf coutners
11fdf7f2 220 _cct->_refresh_perf_values();
7c673cae
FG
221 }
222 return NULL;
223 }
224
225 void reopen_logs()
226 {
11fdf7f2 227 std::lock_guard l(_lock);
7c673cae 228 _reopen_logs = true;
11fdf7f2 229 _cond.notify_all();
7c673cae
FG
230 }
231
232 void exit_thread()
233 {
11fdf7f2 234 std::lock_guard l(_lock);
7c673cae 235 _exit_thread = true;
11fdf7f2 236 _cond.notify_all();
7c673cae
FG
237 }
238
239private:
11fdf7f2
TL
240 ceph::mutex _lock = ceph::make_mutex("CephContextServiceThread::_lock");
241 ceph::condition_variable _cond;
7c673cae
FG
242 bool _reopen_logs;
243 bool _exit_thread;
244 CephContext *_cct;
245};
246
247
248/**
249 * observe logging config changes
250 *
251 * The logging subsystem sits below most of the ceph code, including
252 * the config subsystem, to keep it simple and self-contained. Feed
253 * logging-related config changes to the log.
254 */
255class LogObs : public md_config_obs_t {
256 ceph::logging::Log *log;
11fdf7f2 257 ceph::mutex lock;
7c673cae
FG
258
259public:
f64942e4 260 explicit LogObs(ceph::logging::Log *l)
11fdf7f2 261 : log(l), lock(ceph::make_mutex("log_obs")) {
f64942e4 262 }
7c673cae
FG
263
264 const char** get_tracked_conf_keys() const override {
265 static const char *KEYS[] = {
266 "log_file",
267 "log_max_new",
268 "log_max_recent",
11fdf7f2 269 "log_to_file",
7c673cae
FG
270 "log_to_syslog",
271 "err_to_syslog",
b32b8144 272 "log_stderr_prefix",
7c673cae
FG
273 "log_to_stderr",
274 "err_to_stderr",
275 "log_to_graylog",
276 "err_to_graylog",
277 "log_graylog_host",
278 "log_graylog_port",
11fdf7f2 279 "log_coarse_timestamps",
7c673cae
FG
280 "fsid",
281 "host",
282 NULL
283 };
284 return KEYS;
285 }
286
11fdf7f2 287 void handle_conf_change(const ConfigProxy& conf,
7c673cae 288 const std::set <std::string> &changed) override {
11fdf7f2 289 std::unique_lock locker(lock);
7c673cae
FG
290 // stderr
291 if (changed.count("log_to_stderr") || changed.count("err_to_stderr")) {
292 int l = conf->log_to_stderr ? 99 : (conf->err_to_stderr ? -1 : -2);
293 log->set_stderr_level(l, l);
294 }
295
296 // syslog
297 if (changed.count("log_to_syslog")) {
298 int l = conf->log_to_syslog ? 99 : (conf->err_to_syslog ? -1 : -2);
299 log->set_syslog_level(l, l);
300 }
301
302 // file
11fdf7f2
TL
303 if (changed.count("log_file") ||
304 changed.count("log_to_file")) {
305 if (conf->log_to_file) {
306 log->set_log_file(conf->log_file);
307 } else {
308 log->set_log_file({});
309 }
7c673cae
FG
310 log->reopen_log_file();
311 }
312
b32b8144 313 if (changed.count("log_stderr_prefix")) {
11fdf7f2 314 log->set_log_stderr_prefix(conf.get_val<string>("log_stderr_prefix"));
b32b8144
FG
315 }
316
7c673cae
FG
317 if (changed.count("log_max_new")) {
318
319 log->set_max_new(conf->log_max_new);
320 }
321
322 if (changed.count("log_max_recent")) {
323 log->set_max_recent(conf->log_max_recent);
324 }
325
326 // graylog
327 if (changed.count("log_to_graylog") || changed.count("err_to_graylog")) {
328 int l = conf->log_to_graylog ? 99 : (conf->err_to_graylog ? -1 : -2);
329 log->set_graylog_level(l, l);
330
331 if (conf->log_to_graylog || conf->err_to_graylog) {
332 log->start_graylog();
333 } else if (! (conf->log_to_graylog && conf->err_to_graylog)) {
334 log->stop_graylog();
335 }
336 }
337
338 if (log->graylog() && (changed.count("log_graylog_host") || changed.count("log_graylog_port"))) {
339 log->graylog()->set_destination(conf->log_graylog_host, conf->log_graylog_port);
340 }
341
11fdf7f2
TL
342 if (changed.find("log_coarse_timestamps") != changed.end()) {
343 log->set_coarse_timestamps(conf.get_val<bool>("log_coarse_timestamps"));
344 }
345
7c673cae
FG
346 // metadata
347 if (log->graylog() && changed.count("host")) {
348 log->graylog()->set_hostname(conf->host);
349 }
350
351 if (log->graylog() && changed.count("fsid")) {
11fdf7f2 352 log->graylog()->set_fsid(conf.get_val<uuid_d>("fsid"));
7c673cae
FG
353 }
354 }
355};
356
357
358// cct config watcher
359class CephContextObs : public md_config_obs_t {
360 CephContext *cct;
361
362public:
363 explicit CephContextObs(CephContext *cct) : cct(cct) {}
364
365 const char** get_tracked_conf_keys() const override {
366 static const char *KEYS[] = {
367 "enable_experimental_unrecoverable_data_corrupting_features",
368 "crush_location",
369 NULL
370 };
371 return KEYS;
372 }
373
11fdf7f2 374 void handle_conf_change(const ConfigProxy& conf,
7c673cae
FG
375 const std::set <std::string> &changed) override {
376 if (changed.count(
377 "enable_experimental_unrecoverable_data_corrupting_features")) {
11fdf7f2 378 std::lock_guard lg(cct->_feature_lock);
7c673cae
FG
379 get_str_set(
380 conf->enable_experimental_unrecoverable_data_corrupting_features,
381 cct->_experimental_features);
7c673cae
FG
382 if (getenv("CEPH_DEV") == NULL) {
383 if (!cct->_experimental_features.empty()) {
384 if (cct->_experimental_features.count("*")) {
385 lderr(cct) << "WARNING: all dangerous and experimental features are enabled." << dendl;
386 } else {
387 lderr(cct) << "WARNING: the following dangerous and experimental features are enabled: "
388 << cct->_experimental_features << dendl;
389 }
390 }
391 }
392
393 }
394 if (changed.count("crush_location")) {
395 cct->crush_location.update_from_conf();
396 }
397 }
398};
399
400bool CephContext::check_experimental_feature_enabled(const std::string& feat)
401{
402 stringstream message;
403 bool enabled = check_experimental_feature_enabled(feat, &message);
404 lderr(this) << message.str() << dendl;
405 return enabled;
406}
407
408bool CephContext::check_experimental_feature_enabled(const std::string& feat,
409 std::ostream *message)
410{
11fdf7f2
TL
411 std::unique_lock<ceph::spinlock> lg(_feature_lock);
412
7c673cae
FG
413 bool enabled = (_experimental_features.count(feat) ||
414 _experimental_features.count("*"));
7c673cae
FG
415
416 if (enabled) {
417 (*message) << "WARNING: experimental feature '" << feat << "' is enabled\n";
418 (*message) << "Please be aware that this feature is experimental, untested,\n";
419 (*message) << "unsupported, and may result in data corruption, data loss,\n";
420 (*message) << "and/or irreparable damage to your cluster. Do not use\n";
421 (*message) << "feature with important data.\n";
422 } else {
423 (*message) << "*** experimental feature '" << feat << "' is not enabled ***\n";
424 (*message) << "This feature is marked as experimental, which means it\n";
425 (*message) << " - is untested\n";
426 (*message) << " - is unsupported\n";
427 (*message) << " - may corrupt your data\n";
428 (*message) << " - may break your cluster is an unrecoverable fashion\n";
429 (*message) << "To enable this feature, add this to your ceph.conf:\n";
430 (*message) << " enable experimental unrecoverable data corrupting features = " << feat << "\n";
431 }
432 return enabled;
433}
434
435// perfcounter hooks
436
437class CephContextHook : public AdminSocketHook {
438 CephContext *m_cct;
439
440public:
441 explicit CephContextHook(CephContext *cct) : m_cct(cct) {}
442
11fdf7f2
TL
443 bool call(std::string_view command, const cmdmap_t& cmdmap,
444 std::string_view format, bufferlist& out) override {
445 try {
446 m_cct->do_command(command, cmdmap, format, &out);
447 } catch (const bad_cmd_get& e) {
448 return false;
449 }
7c673cae
FG
450 return true;
451 }
452};
453
11fdf7f2
TL
454void CephContext::do_command(std::string_view command, const cmdmap_t& cmdmap,
455 std::string_view format, bufferlist *out)
7c673cae
FG
456{
457 Formatter *f = Formatter::create(format, "json-pretty", "json-pretty");
458 stringstream ss;
11fdf7f2 459 for (auto it = cmdmap.begin(); it != cmdmap.end(); ++it) {
7c673cae
FG
460 if (it->first != "prefix") {
461 ss << it->first << ":" << cmd_vartype_stringify(it->second) << " ";
462 }
463 }
464 lgeneric_dout(this, 1) << "do_command '" << command << "' '"
465 << ss.str() << dendl;
11fdf7f2
TL
466 ceph_assert_always(!(command == "assert" && _conf->debug_asok_assert_abort));
467 if (command == "abort" && _conf->debug_asok_assert_abort) {
468 ceph_abort();
469 }
7c673cae
FG
470 if (command == "perfcounters_dump" || command == "1" ||
471 command == "perf dump") {
472 std::string logger;
473 std::string counter;
474 cmd_getval(this, cmdmap, "logger", logger);
475 cmd_getval(this, cmdmap, "counter", counter);
476 _perf_counters_collection->dump_formatted(f, false, logger, counter);
477 }
478 else if (command == "perfcounters_schema" || command == "2" ||
479 command == "perf schema") {
480 _perf_counters_collection->dump_formatted(f, true);
481 }
482 else if (command == "perf histogram dump") {
483 std::string logger;
484 std::string counter;
485 cmd_getval(this, cmdmap, "logger", logger);
486 cmd_getval(this, cmdmap, "counter", counter);
487 _perf_counters_collection->dump_formatted_histograms(f, false, logger,
488 counter);
489 }
490 else if (command == "perf histogram schema") {
491 _perf_counters_collection->dump_formatted_histograms(f, true);
492 }
493 else if (command == "perf reset") {
494 std::string var;
11fdf7f2 495 std::string section(command);
7c673cae
FG
496 f->open_object_section(section.c_str());
497 if (!cmd_getval(this, cmdmap, "var", var)) {
498 f->dump_string("error", "syntax error: 'perf reset <var>'");
499 } else {
500 if(!_perf_counters_collection->reset(var))
501 f->dump_stream("error") << "Not find: " << var;
502 else
11fdf7f2 503 f->dump_string("success", std::string(command) + ' ' + var);
7c673cae
FG
504 }
505 f->close_section();
506 }
507 else {
11fdf7f2 508 std::string section(command);
7c673cae
FG
509 boost::replace_all(section, " ", "_");
510 f->open_object_section(section.c_str());
511 if (command == "config show") {
11fdf7f2
TL
512 _conf.show_config(f);
513 }
514 else if (command == "config unset") {
515 std::string var;
516 if (!(cmd_getval(this, cmdmap, "var", var))) {
517 f->dump_string("error", "syntax error: 'config unset <var>'");
518 } else {
519 int r = _conf.rm_val(var.c_str());
520 if (r < 0 && r != -ENOENT) {
521 f->dump_stream("error") << "error unsetting '" << var << "': "
522 << cpp_strerror(r);
523 } else {
524 ostringstream ss;
525 _conf.apply_changes(&ss);
526 f->dump_string("success", ss.str());
527 }
528 }
529
7c673cae
FG
530 }
531 else if (command == "config set") {
532 std::string var;
533 std::vector<std::string> val;
534
535 if (!(cmd_getval(this, cmdmap, "var", var)) ||
536 !(cmd_getval(this, cmdmap, "val", val))) {
537 f->dump_string("error", "syntax error: 'config set <var> <value>'");
538 } else {
539 // val may be multiple words
540 string valstr = str_join(val, " ");
11fdf7f2 541 int r = _conf.set_val(var.c_str(), valstr.c_str());
7c673cae
FG
542 if (r < 0) {
543 f->dump_stream("error") << "error setting '" << var << "' to '" << valstr << "': " << cpp_strerror(r);
544 } else {
545 ostringstream ss;
11fdf7f2 546 _conf.apply_changes(&ss);
7c673cae
FG
547 f->dump_string("success", ss.str());
548 }
549 }
550 } else if (command == "config get") {
551 std::string var;
552 if (!cmd_getval(this, cmdmap, "var", var)) {
553 f->dump_string("error", "syntax error: 'config get <var>'");
554 } else {
555 char buf[4096];
92f5a8d4 556 // FIPS zeroization audit 20191115: this memset is not security related.
7c673cae
FG
557 memset(buf, 0, sizeof(buf));
558 char *tmp = buf;
11fdf7f2 559 int r = _conf.get_val(var.c_str(), &tmp, sizeof(buf));
7c673cae
FG
560 if (r < 0) {
561 f->dump_stream("error") << "error getting '" << var << "': " << cpp_strerror(r);
562 } else {
563 f->dump_string(var.c_str(), buf);
564 }
565 }
c07f9fc5
FG
566 } else if (command == "config help") {
567 std::string var;
568 if (cmd_getval(this, cmdmap, "var", var)) {
569 // Output a single one
570 std::string key = ConfFile::normalize_key_name(var);
11fdf7f2
TL
571 auto schema = _conf.get_schema(key);
572 if (!schema) {
c07f9fc5
FG
573 std::ostringstream msg;
574 msg << "Setting not found: '" << key << "'";
575 f->dump_string("error", msg.str());
576 } else {
11fdf7f2 577 f->dump_object("option", *schema);
c07f9fc5
FG
578 }
579 } else {
580 // Output all
581 f->open_array_section("options");
582 for (const auto &option : ceph_options) {
11fdf7f2 583 f->dump_object("option", option);
c07f9fc5
FG
584 }
585 f->close_section();
586 }
7c673cae 587 } else if (command == "config diff") {
7c673cae 588 f->open_object_section("diff");
11fdf7f2 589 _conf.diff(f);
7c673cae 590 f->close_section(); // unknown
31f18b77
FG
591 } else if (command == "config diff get") {
592 std::string setting;
11fdf7f2
TL
593 f->open_object_section("diff");
594 _conf.diff(f, setting);
595 f->close_section(); // unknown
7c673cae
FG
596 } else if (command == "log flush") {
597 _log->flush();
598 }
599 else if (command == "log dump") {
600 _log->dump_recent();
601 }
602 else if (command == "log reopen") {
603 _log->reopen_log_file();
604 }
605 else {
11fdf7f2 606 ceph_abort_msg("registered under wrong command?");
7c673cae
FG
607 }
608 f->close_section();
609 }
610 f->flush(*out);
611 delete f;
612 lgeneric_dout(this, 1) << "do_command '" << command << "' '" << ss.str()
613 << "result is " << out->length() << " bytes" << dendl;
614}
615
c07f9fc5
FG
616CephContext::CephContext(uint32_t module_type_,
617 enum code_environment_t code_env,
618 int init_flags_)
7c673cae 619 : nref(1),
11fdf7f2 620 _conf{code_env == CODE_ENVIRONMENT_DAEMON},
7c673cae
FG
621 _log(NULL),
622 _module_type(module_type_),
623 _init_flags(init_flags_),
624 _set_uid(0),
625 _set_gid(0),
626 _set_uid_string(),
627 _set_gid_string(),
11fdf7f2 628 _crypto_inited(0),
7c673cae
FG
629 _service_thread(NULL),
630 _log_obs(NULL),
631 _admin_socket(NULL),
632 _perf_counters_collection(NULL),
633 _perf_counters_conf_obs(NULL),
634 _heartbeat_map(NULL),
635 _crypto_none(NULL),
636 _crypto_aes(NULL),
637 _plugin_registry(NULL),
638 _lockdep_obs(NULL),
11fdf7f2 639 crush_location(this)
7c673cae 640{
7c673cae 641 _log = new ceph::logging::Log(&_conf->subsys);
7c673cae
FG
642
643 _log_obs = new LogObs(_log);
11fdf7f2 644 _conf.add_observer(_log_obs);
7c673cae
FG
645
646 _cct_obs = new CephContextObs(this);
11fdf7f2 647 _conf.add_observer(_cct_obs);
7c673cae
FG
648
649 _lockdep_obs = new LockdepObs(this);
11fdf7f2 650 _conf.add_observer(_lockdep_obs);
7c673cae
FG
651
652 _perf_counters_collection = new PerfCountersCollection(this);
653
654 _admin_socket = new AdminSocket(this);
655 _heartbeat_map = new HeartbeatMap(this);
656
657 _plugin_registry = new PluginRegistry(this);
658
659 _admin_hook = new CephContextHook(this);
11fdf7f2
TL
660 _admin_socket->register_command("assert", "assert", _admin_hook, "");
661 _admin_socket->register_command("abort", "abort", _admin_hook, "");
7c673cae
FG
662 _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, "");
663 _admin_socket->register_command("1", "1", _admin_hook, "");
664 _admin_socket->register_command("perf dump", "perf dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perfcounters value");
665 _admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, "");
666 _admin_socket->register_command("perf histogram dump", "perf histogram dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perf histogram values");
667 _admin_socket->register_command("2", "2", _admin_hook, "");
668 _admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema");
669 _admin_socket->register_command("perf histogram schema", "perf histogram schema", _admin_hook, "dump perf histogram schema");
670 _admin_socket->register_command("perf reset", "perf reset name=var,type=CephString", _admin_hook, "perf reset <name>: perf reset all or one perfcounter name");
671 _admin_socket->register_command("config show", "config show", _admin_hook, "dump current config settings");
c07f9fc5 672 _admin_socket->register_command("config help", "config help name=var,type=CephString,req=false", _admin_hook, "get config setting schema and descriptions");
7c673cae 673 _admin_socket->register_command("config set", "config set name=var,type=CephString name=val,type=CephString,n=N", _admin_hook, "config set <field> <val> [<val> ...]: set a config variable");
11fdf7f2 674 _admin_socket->register_command("config unset", "config unset name=var,type=CephString", _admin_hook, "config unset <field>: unset a config variable");
7c673cae
FG
675 _admin_socket->register_command("config get", "config get name=var,type=CephString", _admin_hook, "config get <field>: get the config value");
676 _admin_socket->register_command("config diff",
677 "config diff", _admin_hook,
678 "dump diff of current config and default config");
31f18b77
FG
679 _admin_socket->register_command("config diff get",
680 "config diff get name=var,type=CephString", _admin_hook,
681 "dump diff get <field>: dump diff of current and default config setting <field>");
7c673cae
FG
682 _admin_socket->register_command("log flush", "log flush", _admin_hook, "flush log entries to log file");
683 _admin_socket->register_command("log dump", "log dump", _admin_hook, "dump recent log entries to log file");
684 _admin_socket->register_command("log reopen", "log reopen", _admin_hook, "reopen log file");
685
686 _crypto_none = CryptoHandler::create(CEPH_CRYPTO_NONE);
687 _crypto_aes = CryptoHandler::create(CEPH_CRYPTO_AES);
11fdf7f2 688 _crypto_random.reset(new CryptoRandom());
7c673cae 689
11fdf7f2 690 lookup_or_create_singleton_object<MempoolObs>("mempool_obs", false, this);
7c673cae
FG
691}
692
693CephContext::~CephContext()
694{
11fdf7f2 695 associated_objs.clear();
7c673cae
FG
696 join_service_thread();
697
7c673cae
FG
698 if (_cct_perf) {
699 _perf_counters_collection->remove(_cct_perf);
700 delete _cct_perf;
701 _cct_perf = NULL;
702 }
703
704 delete _plugin_registry;
705
11fdf7f2 706 _admin_socket->unregister_commands(_admin_hook);
7c673cae
FG
707 delete _admin_hook;
708 delete _admin_socket;
709
710 delete _heartbeat_map;
711
712 delete _perf_counters_collection;
713 _perf_counters_collection = NULL;
714
715 delete _perf_counters_conf_obs;
716 _perf_counters_conf_obs = NULL;
717
11fdf7f2 718 _conf.remove_observer(_log_obs);
7c673cae
FG
719 delete _log_obs;
720 _log_obs = NULL;
721
11fdf7f2 722 _conf.remove_observer(_cct_obs);
7c673cae
FG
723 delete _cct_obs;
724 _cct_obs = NULL;
725
11fdf7f2 726 _conf.remove_observer(_lockdep_obs);
7c673cae
FG
727 delete _lockdep_obs;
728 _lockdep_obs = NULL;
729
730 _log->stop();
731 delete _log;
732 _log = NULL;
733
7c673cae
FG
734 delete _crypto_none;
735 delete _crypto_aes;
11fdf7f2
TL
736 if (_crypto_inited > 0) {
737 ceph_assert(_crypto_inited == 1); // or else someone explicitly did
738 // init but not shutdown
739 shutdown_crypto();
740 }
7c673cae
FG
741}
742
743void CephContext::put() {
31f18b77 744 if (--nref == 0) {
7c673cae
FG
745 ANNOTATE_HAPPENS_AFTER(&nref);
746 ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref);
747 delete this;
748 } else {
749 ANNOTATE_HAPPENS_BEFORE(&nref);
750 }
751}
752
753void CephContext::init_crypto()
754{
11fdf7f2 755 if (_crypto_inited++ == 0) {
7c673cae 756 ceph::crypto::init(this);
11fdf7f2
TL
757 }
758}
759
760void CephContext::shutdown_crypto()
761{
762 if (--_crypto_inited == 0) {
763 ceph::crypto::shutdown(g_code_env == CODE_ENVIRONMENT_LIBRARY);
7c673cae
FG
764 }
765}
766
767void CephContext::start_service_thread()
768{
11fdf7f2
TL
769 {
770 std::lock_guard lg(_service_thread_lock);
771 if (_service_thread) {
772 return;
773 }
774 _service_thread = new CephContextServiceThread(this);
775 _service_thread->create("service");
7c673cae 776 }
11fdf7f2
TL
777
778 if (!(get_init_flags() & CINIT_FLAG_NO_CCT_PERF_COUNTERS))
779 _enable_perf_counter();
7c673cae
FG
780
781 // make logs flush on_exit()
782 if (_conf->log_flush_on_exit)
783 _log->set_flush_on_exit();
784
785 // Trigger callbacks on any config observers that were waiting for
786 // it to become safe to start threads.
11fdf7f2
TL
787 _conf.set_safe_to_start_threads();
788 _conf.call_all_observers();
7c673cae
FG
789
790 // start admin socket
791 if (_conf->admin_socket.length())
792 _admin_socket->init(_conf->admin_socket);
793}
794
795void CephContext::reopen_logs()
796{
11fdf7f2 797 std::lock_guard lg(_service_thread_lock);
7c673cae
FG
798 if (_service_thread)
799 _service_thread->reopen_logs();
7c673cae
FG
800}
801
802void CephContext::join_service_thread()
803{
11fdf7f2
TL
804 std::unique_lock<ceph::spinlock> lg(_service_thread_lock);
805
7c673cae
FG
806 CephContextServiceThread *thread = _service_thread;
807 if (!thread) {
7c673cae
FG
808 return;
809 }
810 _service_thread = NULL;
11fdf7f2
TL
811
812 lg.unlock();
7c673cae
FG
813
814 thread->exit_thread();
815 thread->join();
816 delete thread;
11fdf7f2
TL
817
818 if (!(get_init_flags() & CINIT_FLAG_NO_CCT_PERF_COUNTERS))
819 _disable_perf_counter();
7c673cae
FG
820}
821
822uint32_t CephContext::get_module_type() const
823{
824 return _module_type;
825}
826
827void CephContext::set_init_flags(int flags)
828{
829 _init_flags = flags;
830}
831
832int CephContext::get_init_flags() const
833{
834 return _init_flags;
835}
836
837PerfCountersCollection *CephContext::get_perfcounters_collection()
838{
839 return _perf_counters_collection;
840}
841
11fdf7f2 842void CephContext::_enable_perf_counter()
7c673cae 843{
11fdf7f2 844 assert(!_cct_perf);
7c673cae
FG
845 PerfCountersBuilder plb(this, "cct", l_cct_first, l_cct_last);
846 plb.add_u64(l_cct_total_workers, "total_workers", "Total workers");
847 plb.add_u64(l_cct_unhealthy_workers, "unhealthy_workers", "Unhealthy workers");
11fdf7f2 848 _cct_perf = plb.create_perf_counters();
7c673cae 849 _perf_counters_collection->add(_cct_perf);
11fdf7f2
TL
850
851 assert(_mempool_perf_names.empty());
852 assert(_mempool_perf_descriptions.empty());
853 _mempool_perf_names.reserve(mempool::num_pools * 2);
854 _mempool_perf_descriptions.reserve(mempool::num_pools * 2);
855 for (unsigned i = 0; i < mempool::num_pools; ++i) {
856 string n = mempool::get_pool_name(mempool::pool_index_t(i));
857 _mempool_perf_names.push_back(n + "_bytes");
858 _mempool_perf_descriptions.push_back(
859 string("mempool ") + n + " total bytes");
860 _mempool_perf_names.push_back(n + "_items");
861 _mempool_perf_descriptions.push_back(
862 string("mempool ") + n + " total items");
863 }
864
865 PerfCountersBuilder plb2(this, "mempool", l_mempool_first,
866 l_mempool_first + 1 + 2*mempool::num_pools);
867 unsigned l = l_mempool_first + 1;
868 for (unsigned i = 0; i < mempool::num_pools; ++i) {
869 plb2.add_u64(l++, _mempool_perf_names[i*2].c_str(),
870 _mempool_perf_descriptions[i*2].c_str());
871 plb2.add_u64(l++, _mempool_perf_names[i*2+1].c_str(),
872 _mempool_perf_descriptions[i*2+1].c_str());
873 }
874 _mempool_perf = plb2.create_perf_counters();
875 _perf_counters_collection->add(_mempool_perf);
7c673cae
FG
876}
877
11fdf7f2 878void CephContext::_disable_perf_counter()
7c673cae 879{
11fdf7f2
TL
880 if (!_cct_perf) {
881 return;
882 }
7c673cae 883 _perf_counters_collection->remove(_cct_perf);
7c673cae 884 delete _cct_perf;
11fdf7f2
TL
885 _cct_perf = nullptr;
886
887 _perf_counters_collection->remove(_mempool_perf);
888 delete _mempool_perf;
889 _mempool_perf = nullptr;
890 _mempool_perf_names.clear();
891 _mempool_perf_descriptions.clear();
7c673cae
FG
892}
893
11fdf7f2 894void CephContext::_refresh_perf_values()
7c673cae 895{
7c673cae
FG
896 if (_cct_perf) {
897 _cct_perf->set(l_cct_total_workers, _heartbeat_map->get_total_workers());
898 _cct_perf->set(l_cct_unhealthy_workers, _heartbeat_map->get_unhealthy_workers());
899 }
11fdf7f2
TL
900 unsigned l = l_mempool_first + 1;
901 for (unsigned i = 0; i < mempool::num_pools; ++i) {
902 mempool::pool_t& p = mempool::get_pool(mempool::pool_index_t(i));
903 _mempool_perf->set(l++, p.allocated_bytes());
904 _mempool_perf->set(l++, p.allocated_items());
905 }
7c673cae
FG
906}
907
908AdminSocket *CephContext::get_admin_socket()
909{
910 return _admin_socket;
911}
912
913CryptoHandler *CephContext::get_crypto_handler(int type)
914{
915 switch (type) {
916 case CEPH_CRYPTO_NONE:
917 return _crypto_none;
918 case CEPH_CRYPTO_AES:
919 return _crypto_aes;
920 default:
921 return NULL;
922 }
923}
11fdf7f2
TL
924
925void CephContext::notify_pre_fork()
926{
927 {
928 std::lock_guard lg(_fork_watchers_lock);
929 for (auto &&t : _fork_watchers) {
930 t->handle_pre_fork();
931 }
932 }
933 {
934 // note: we don't hold a lock here, but we assume we are idle at
935 // fork time, which happens during process init and startup.
936 auto i = associated_objs.begin();
937 while (i != associated_objs.end()) {
938 if (associated_objs_drop_on_fork.count(i->first.first)) {
939 i = associated_objs.erase(i);
940 } else {
941 ++i;
942 }
943 }
944 associated_objs_drop_on_fork.clear();
945 }
946}
947
948void CephContext::notify_post_fork()
949{
950 ceph::spin_unlock(&_fork_watchers_lock);
951 for (auto &&t : _fork_watchers)
952 t->handle_post_fork();
953}
954#endif // WITH_SEASTAR