// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include "librbd/ConfigWatcher.h" #include "common/config_obs.h" #include "common/dout.h" #include "common/errno.h" #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" #include "librbd/api/Config.h" #include #include #include #include #define dout_subsys ceph_subsys_rbd #undef dout_prefix #define dout_prefix *_dout << "librbd::ConfigWatcher: " \ << __func__ << ": " namespace librbd { template struct ConfigWatcher::Observer : public md_config_obs_t { ConfigWatcher* m_config_watcher; std::deque m_config_key_strs; mutable std::vector m_config_keys; Observer(CephContext* cct, ConfigWatcher* config_watcher) : m_config_watcher(config_watcher) { const std::string rbd_key_prefix("rbd_"); auto& schema = cct->_conf.get_schema(); for (auto& pair : schema) { // watch all "rbd_" keys for simplicity if (!boost::starts_with(pair.first, rbd_key_prefix)) { continue; } m_config_key_strs.emplace_back(pair.first); } m_config_keys.reserve(m_config_key_strs.size()); for (auto& key : m_config_key_strs) { m_config_keys.emplace_back(key.c_str()); } m_config_keys.emplace_back(nullptr); } const char** get_tracked_conf_keys() const override { ceph_assert(!m_config_keys.empty()); return &m_config_keys[0]; } void handle_conf_change(const ConfigProxy& conf, const std::set &changed) override { m_config_watcher->handle_global_config_change(changed); } }; template ConfigWatcher::ConfigWatcher(I& image_ctx) : m_image_ctx(image_ctx) { } template ConfigWatcher::~ConfigWatcher() { ceph_assert(m_observer == nullptr); } template void ConfigWatcher::init() { auto cct = m_image_ctx.cct; ldout(cct, 10) << dendl; m_observer = new Observer(cct, this); cct->_conf.add_observer(m_observer); } template void ConfigWatcher::shut_down() { auto cct = m_image_ctx.cct; ldout(cct, 10) << dendl; ceph_assert(m_observer != nullptr); cct->_conf.remove_observer(m_observer); delete m_observer; m_observer = nullptr; } template void ConfigWatcher::handle_global_config_change( std::set changed_keys) { { // ignore any global changes that are being overridden std::shared_lock image_locker{m_image_ctx.image_lock}; for (auto& key : m_image_ctx.config_overrides) { changed_keys.erase(key); } } if (changed_keys.empty()) { return; } auto cct = m_image_ctx.cct; ldout(cct, 10) << "changed_keys=" << changed_keys << dendl; // refresh the image to pick up any global config overrides m_image_ctx.state->handle_update_notification(); } } // namespace librbd template class librbd::ConfigWatcher;