From 017d8308484c4d3f07ffe3e63515a8f34961a1ac Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 6 Apr 2016 16:08:15 -0400 Subject: [PATCH] rbd-mirror: workaround for intermingled lockdep singletons If librados constructs the CephContext, lockdep will be initialized in both the librados shared address space and also within the app address space. This breaks lockdep's functionality and results in a crash upon shutdown. Signed-off-by: Jason Dillaman --- src/tools/rbd_mirror/Replayer.cc | 56 +++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/tools/rbd_mirror/Replayer.cc b/src/tools/rbd_mirror/Replayer.cc index ce76f99a57ee9..d73bc103048de 100644 --- a/src/tools/rbd_mirror/Replayer.cc +++ b/src/tools/rbd_mirror/Replayer.cc @@ -5,6 +5,9 @@ #include "common/Formatter.h" #include "common/admin_socket.h" +#include "common/ceph_argparse.h" +#include "common/code_environment.h" +#include "common/common_init.h" #include "common/debug.h" #include "common/errno.h" #include "include/stringify.h" @@ -143,37 +146,60 @@ int Replayer::init() { dout(20) << "replaying for " << m_peer << dendl; - int r = m_remote->init2(m_peer.client_name.c_str(), - m_peer.cluster_name.c_str(), 0); - if (r < 0) { - derr << "error initializing remote cluster handle for " << m_peer - << " : " << cpp_strerror(r) << dendl; - return r; + // NOTE: manually bootstrap a CephContext here instead of via + // the librados API to avoid mixing global singletons between + // the librados shared library and the daemon + // TODO: eliminate intermingling of global singletons within Ceph APIs + CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT); + if (m_peer.client_name.empty() || + !iparams.name.from_str(m_peer.client_name)) { + derr << "error initializing remote cluster handle for " << m_peer << dendl; + return -EINVAL; } - r = m_remote->conf_read_file(nullptr); + CephContext *cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, + CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS); + cct->_conf->cluster = m_peer.cluster_name; + + // librados::Rados::conf_read_file + int r = cct->_conf->parse_config_files(nullptr, nullptr, 0); if (r < 0) { - derr << "could not read ceph conf for " << m_peer - << " : " << cpp_strerror(r) << dendl; + derr << "could not read ceph conf for " << m_peer << ": " + << cpp_strerror(r) << dendl; + cct->put(); return r; } + cct->_conf->parse_env(); - r = m_remote->conf_parse_env(nullptr); + // librados::Rados::conf_parse_env + std::vector args; + env_to_vec(args, nullptr); + r = cct->_conf->parse_argv(args); if (r < 0) { - derr << "could not parse environment for " << m_peer - << " : " << cpp_strerror(r) << dendl; + derr << "could not parse environment for " << m_peer << ":" + << cpp_strerror(r) << dendl; + cct->put(); return r; } if (!m_args.empty()) { - r = m_remote->conf_parse_argv(m_args.size(), &m_args[0]); + // librados::Rados::conf_parse_argv + r = cct->_conf->parse_argv(m_args); if (r < 0) { - derr << "could not parse command line args for " << m_peer - << " : " << cpp_strerror(r) << dendl; + derr << "could not parse command line args for " << m_peer << ": " + << cpp_strerror(r) << dendl; + cct->put(); return r; } } + cct->_conf->apply_changes(nullptr); + cct->_conf->complain_about_parse_errors(cct); + + r = m_remote->init_with_context(cct); + assert(r == 0); + cct->put(); + r = m_remote->connect(); if (r < 0) { derr << "error connecting to remote cluster " << m_peer -- 2.39.5