diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.git_version | 4 | ||||
-rw-r--r-- | src/client/Client.cc | 8 | ||||
-rw-r--r-- | src/client/Client.h | 2 | ||||
-rw-r--r-- | src/common/ceph_strings.cc | 6 | ||||
-rw-r--r-- | src/common/options/mds-client.yaml.in | 8 | ||||
-rw-r--r-- | src/mds/Beacon.cc | 24 | ||||
-rw-r--r-- | src/mds/MDSAuthCaps.h | 17 | ||||
-rw-r--r-- | src/mds/Server.cc | 23 | ||||
-rw-r--r-- | src/mds/SessionMap.cc | 1 | ||||
-rw-r--r-- | src/mds/SessionMap.h | 12 | ||||
-rw-r--r-- | src/mds/mdstypes.cc | 26 | ||||
-rw-r--r-- | src/mds/mdstypes.h | 3 | ||||
-rw-r--r-- | src/messages/MMDSBeacon.h | 5 | ||||
-rw-r--r-- | src/mon/MDSMonitor.cc | 1 | ||||
-rw-r--r-- | src/osd/OSDMap.cc | 8 | ||||
-rw-r--r-- | src/pybind/mgr/k8sevents/module.py | 18 | ||||
-rw-r--r-- | src/pybind/mgr/requirements.txt | 2 |
17 files changed, 133 insertions, 35 deletions
diff --git a/src/.git_version b/src/.git_version index 32a4fa347..1c10e47ef 100644 --- a/src/.git_version +++ b/src/.git_version @@ -1,2 +1,2 @@ -76424b2fe1bb19c32c52140f39764599abf5e035 -18.2.3 +e7ad5345525c7aa95470c26863873b581076945d +18.2.4 diff --git a/src/client/Client.cc b/src/client/Client.cc index ba41e9dd0..ec97e36fb 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -392,6 +392,12 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_) if (cct->_conf->client_acl_type == "posix_acl") acl_type = POSIX_ACL; + if (auto str = cct->_conf->client_debug_inject_features; !str.empty()) { + myfeatures = feature_bitset_t(str); + } else { + myfeatures = feature_bitset_t(CEPHFS_FEATURES_CLIENT_SUPPORTED); + } + lru.lru_set_midpoint(cct->_conf->client_cache_mid); // file handles @@ -2354,7 +2360,7 @@ MetaSessionRef Client::_open_mds_session(mds_rank_t mds) auto m = make_message<MClientSession>(CEPH_SESSION_REQUEST_OPEN); m->metadata = metadata; - m->supported_features = feature_bitset_t(CEPHFS_FEATURES_CLIENT_SUPPORTED); + m->supported_features = myfeatures; m->metric_spec = feature_bitset_t(CEPHFS_METRIC_FEATURES_ALL); session->con->send_message2(std::move(m)); return session; diff --git a/src/client/Client.h b/src/client/Client.h index beeef0803..dc9e31aa8 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1639,6 +1639,8 @@ private: uint64_t nr_write_request = 0; std::vector<MDSCapAuth> cap_auths; + + feature_bitset_t myfeatures; }; /** diff --git a/src/common/ceph_strings.cc b/src/common/ceph_strings.cc index 18dcc701b..a92311618 100644 --- a/src/common/ceph_strings.cc +++ b/src/common/ceph_strings.cc @@ -151,7 +151,11 @@ uint64_t ceph_release_features(int r) return req; req |= CEPH_FEATUREMASK_CRUSH_CHOOSE_ARGS; // and overlaps - if (r <= CEPH_RELEASE_LUMINOUS) + if (r <= CEPH_RELEASE_QUINCY) + return req; + + req |= CEPH_FEATUREMASK_SERVER_REEF; // upmap-primary + if (r <= CEPH_RELEASE_REEF) return req; return req; diff --git a/src/common/options/mds-client.yaml.in b/src/common/options/mds-client.yaml.in index 1f7600dee..28912cdb1 100644 --- a/src/common/options/mds-client.yaml.in +++ b/src/common/options/mds-client.yaml.in @@ -251,6 +251,14 @@ options: default: 0 services: - mds_client +- name: client_debug_inject_features + type: str + level: dev + services: + - mds_client + flags: + - startup + with_legacy: true - name: client_max_inline_size type: size level: dev diff --git a/src/mds/Beacon.cc b/src/mds/Beacon.cc index 5dd319a14..b67e0a31b 100644 --- a/src/mds/Beacon.cc +++ b/src/mds/Beacon.cc @@ -484,6 +484,30 @@ void Beacon::notify_health(MDSRank const *mds) health.metrics.push_back(m); } + // Report a health warning if clients have broken root_squash + if (auto c = mds->sessionmap.num_broken_root_squash_clients(); c > 0) { + std::vector<MDSHealthMetric> metrics; + + for (auto&& session : mds->sessionmap.get_broken_root_squash_clients()) { + CachedStackStringStream css; + *css << "Client " << session->get_human_name() << " has broken root_squash implementation"; + MDSHealthMetric m(MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH, HEALTH_ERR, css->strv()); + m.metadata["client_id"] = stringify(session->get_client()); + metrics.emplace_back(std::move(m)); + } + + if (metrics.size() <= (size_t)g_conf()->mds_health_summarize_threshold) { + health.metrics.insert(std::end(health.metrics), std::make_move_iterator(std::begin(metrics)), std::make_move_iterator(std::end(metrics))); + } else { + CachedStackStringStream css; + *css << "There are " << c << " clients with broken root_squash implementations"; + dout(20) << css->strv() << dendl; + MDSHealthMetric m(MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH, HEALTH_ERR, css->strv()); + m.metadata["client_count"] = stringify(c); + health.metrics.push_back(std::move(m)); + } + } + // Report if we have significantly exceeded our cache size limit if (mds->mdcache->cache_overfull()) { CachedStackStringStream css; diff --git a/src/mds/MDSAuthCaps.h b/src/mds/MDSAuthCaps.h index bbb2589b3..f77fd965a 100644 --- a/src/mds/MDSAuthCaps.h +++ b/src/mds/MDSAuthCaps.h @@ -146,6 +146,10 @@ struct MDSCapMatch { */ bool match_path(std::string_view target_path) const; + bool match_fs(std::string_view target_fs) const { + return fs_name == target_fs || fs_name.empty() || fs_name == "*"; + } + void encode(ceph::buffer::list& bl) const { ENCODE_START(1, 1, bl); encode(uid, bl); @@ -261,8 +265,7 @@ public: } for (const MDSCapGrant &g : grants) { - if (g.match.fs_name == fs_name || g.match.fs_name.empty() || - g.match.fs_name == "*") { + if (g.match.match_fs(fs_name)) { if (mask & MAY_READ && g.spec.allow_read()) { return true; } @@ -285,10 +288,12 @@ public: } } - bool root_squash_in_caps() const { - for (const MDSCapGrant &g : grants) { - if (g.match.root_squash) { - return true; + bool root_squash_in_caps(std::string_view fs_name) const { + for (const MDSCapGrant& g : grants) { + if (g.match.match_fs(fs_name)) { + if (g.match.root_squash) { + return true; + } } } return false; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 48e7b03ae..2f8b376ce 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -717,16 +717,10 @@ void Server::handle_client_session(const cref_t<MClientSession> &m) break; } - if (session->auth_caps.root_squash_in_caps() && !client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK)) { - CachedStackStringStream css; - *css << "client lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK needed to enforce 'root_squash' MDS auth caps"; - send_reject_message(css->strv()); - mds->clog->warn() << "client session (" << session->info.inst - << ") lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK " - << " needed to enforce 'root_squash' MDS auth caps"; - session->clear(); - break; - + std::string_view fs_name = mds->mdsmap->get_fs_name(); + bool client_caps_check = client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK); + if (session->auth_caps.root_squash_in_caps(fs_name) && !client_caps_check) { + mds->sessionmap.add_to_broken_root_squash_clients(session); } // Special case for the 'root' metadata path; validate that the claimed // root is actually within the caps of the session @@ -1573,11 +1567,10 @@ void Server::handle_client_reconnect(const cref_t<MClientReconnect> &m) *css << "missing required features '" << missing_features << "'"; error_str = css->strv(); } - if (session->auth_caps.root_squash_in_caps() && - !session->info.client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK)) { - CachedStackStringStream css; - *css << "client lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK needed to enforce 'root_squash' MDS auth caps"; - error_str = css->strv(); + std::string_view fs_name = mds->mdsmap->get_fs_name(); + bool client_caps_check = session->info.client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK); + if (session->auth_caps.root_squash_in_caps(fs_name) && !client_caps_check) { + mds->sessionmap.add_to_broken_root_squash_clients(session); } } diff --git a/src/mds/SessionMap.cc b/src/mds/SessionMap.cc index 9cc2b0138..9bec67c24 100644 --- a/src/mds/SessionMap.cc +++ b/src/mds/SessionMap.cc @@ -705,6 +705,7 @@ void SessionMap::remove_session(Session *s) s->trim_completed_requests(0); s->item_session_list.remove_myself(); + broken_root_squash_clients.erase(s); session_map.erase(s->info.inst.name); dirty_sessions.erase(s->info.inst.name); null_sessions.insert(s->info.inst.name); diff --git a/src/mds/SessionMap.h b/src/mds/SessionMap.h index 360dd66a2..623f20a0e 100644 --- a/src/mds/SessionMap.h +++ b/src/mds/SessionMap.h @@ -682,6 +682,16 @@ public: void remove_session(Session *s); void touch_session(Session *session); + void add_to_broken_root_squash_clients(Session* s) { + broken_root_squash_clients.insert(s); + } + uint64_t num_broken_root_squash_clients() const { + return broken_root_squash_clients.size(); + } + auto const& get_broken_root_squash_clients() const { + return broken_root_squash_clients; + } + Session *get_oldest_session(int state) { auto by_state_entry = by_state.find(state); if (by_state_entry == by_state.end() || by_state_entry->second->empty()) @@ -849,6 +859,8 @@ private: bool validate_and_encode_session(MDSRank *mds, Session *session, bufferlist& bl); void apply_blocklist(const std::set<entity_name_t>& victims); + + std::set<Session*> broken_root_squash_clients; }; std::ostream& operator<<(std::ostream &out, const Session &s); diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc index 044c33459..114ca137b 100644 --- a/src/mds/mdstypes.cc +++ b/src/mds/mdstypes.cc @@ -7,6 +7,10 @@ #include "common/Formatter.h" #include "common/StackStringStream.h" +#include <iostream> +#include <sstream> +#include <string> + const mds_gid_t MDS_GID_NONE = mds_gid_t(0); using std::list; @@ -429,7 +433,7 @@ feature_bitset_t::feature_bitset_t(unsigned long value) } } -feature_bitset_t::feature_bitset_t(const vector<size_t>& array) +void feature_bitset_t::init_array(const vector<size_t>& array) { if (!array.empty()) { size_t n = array.back(); @@ -448,6 +452,26 @@ feature_bitset_t::feature_bitset_t(const vector<size_t>& array) } } +feature_bitset_t::feature_bitset_t(std::string_view str) +{ + std::stringstream ss; + std::vector<size_t> v; + std::string atom; + + ss << str; + while (std::getline(ss, atom, ',')) { + v.push_back(std::stoul(atom)); + } + std::sort(v.begin(), v.end()); + + init_array(v); +} + +feature_bitset_t::feature_bitset_t(const vector<size_t>& array) +{ + init_array(array); +} + feature_bitset_t& feature_bitset_t::operator-=(const feature_bitset_t& other) { for (size_t i = 0; i < _vec.size(); ++i) { diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 3381d44c9..8e7b16761 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -294,6 +294,7 @@ public: feature_bitset_t(const feature_bitset_t& other) : _vec(other._vec) {} feature_bitset_t(feature_bitset_t&& other) : _vec(std::move(other._vec)) {} feature_bitset_t(unsigned long value = 0); + feature_bitset_t(std::string_view); feature_bitset_t(const std::vector<size_t>& array); feature_bitset_t& operator=(const feature_bitset_t& other) { _vec = other._vec; @@ -347,6 +348,8 @@ public: void dump(ceph::Formatter *f) const; void print(std::ostream& out) const; private: + void init_array(const std::vector<size_t>& v); + std::vector<block_type> _vec; }; WRITE_CLASS_ENCODER(feature_bitset_t) diff --git a/src/messages/MMDSBeacon.h b/src/messages/MMDSBeacon.h index d843b0e76..2323f78d8 100644 --- a/src/messages/MMDSBeacon.h +++ b/src/messages/MMDSBeacon.h @@ -46,6 +46,8 @@ enum mds_metric_t { MDS_HEALTH_CACHE_OVERSIZED, MDS_HEALTH_SLOW_METADATA_IO, MDS_HEALTH_CLIENTS_LAGGY, + MDS_HEALTH_CLIENTS_LAGGY_MANY, + MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH, MDS_HEALTH_DUMMY, // not a real health warning, for testing }; @@ -65,6 +67,7 @@ inline const char *mds_metric_name(mds_metric_t m) case MDS_HEALTH_CACHE_OVERSIZED: return "MDS_CACHE_OVERSIZED"; case MDS_HEALTH_SLOW_METADATA_IO: return "MDS_SLOW_METADATA_IO"; case MDS_HEALTH_CLIENTS_LAGGY: return "MDS_CLIENTS_LAGGY"; + case MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH: return "MDS_CLIENTS_BROKEN_ROOTSQUASH"; case MDS_HEALTH_DUMMY: return "MDS_DUMMY"; default: return "???"; @@ -101,6 +104,8 @@ inline const char *mds_metric_summary(mds_metric_t m) return "%num% MDSs report slow metadata IOs"; case MDS_HEALTH_CLIENTS_LAGGY: return "%num% client(s) laggy due to laggy OSDs"; + case MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH: + return "%num% MDS report clients with broken root_squash implementation"; default: return "???"; } diff --git a/src/mon/MDSMonitor.cc b/src/mon/MDSMonitor.cc index 0ac5060f7..88894d73f 100644 --- a/src/mon/MDSMonitor.cc +++ b/src/mon/MDSMonitor.cc @@ -275,6 +275,7 @@ void MDSMonitor::encode_pending(MonitorDBStore::TransactionRef t) } pending.get_health_checks(&new_checks); for (auto& p : new_checks.checks) { + // TODO: handle "client_count" metadata when summarizing p.second.summary = std::regex_replace( p.second.summary, std::regex("%num%"), diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc index 5fb73084d..6468e605c 100644 --- a/src/osd/OSDMap.cc +++ b/src/osd/OSDMap.cc @@ -1747,9 +1747,12 @@ uint64_t OSDMap::get_features(int entity_type, uint64_t *pmask) const } mask |= CEPH_FEATURES_CRUSH; - if (!pg_upmap.empty() || !pg_upmap_items.empty() || !pg_upmap_primaries.empty()) + if (!pg_upmap.empty() || !pg_upmap_items.empty()) features |= CEPH_FEATUREMASK_OSDMAP_PG_UPMAP; mask |= CEPH_FEATUREMASK_OSDMAP_PG_UPMAP; + if (!pg_upmap_primaries.empty()) + features |= CEPH_FEATUREMASK_SERVER_REEF; + mask |= CEPH_FEATUREMASK_SERVER_REEF; for (auto &pool: pools) { if (pool.second.has_flag(pg_pool_t::FLAG_HASHPSPOOL)) { @@ -1821,6 +1824,9 @@ ceph_release_t OSDMap::get_min_compat_client() const { uint64_t f = get_features(CEPH_ENTITY_TYPE_CLIENT, nullptr); + if (HAVE_FEATURE(f, SERVER_REEF)) { // v18.2.3 (upmap-primary; see #61948) + return ceph_release_t::reef; + } if (HAVE_FEATURE(f, OSDMAP_PG_UPMAP) || // v12.0.0-1733-g27d6f43 HAVE_FEATURE(f, CRUSH_CHOOSE_ARGS)) { // v12.0.1-2172-gef1ef28 return ceph_release_t::luminous; // v12.2.0 diff --git a/src/pybind/mgr/k8sevents/module.py b/src/pybind/mgr/k8sevents/module.py index b34029209..5855ba42e 100644 --- a/src/pybind/mgr/k8sevents/module.py +++ b/src/pybind/mgr/k8sevents/module.py @@ -67,7 +67,11 @@ else: # which causes an exception in the generator. A workaround is discussed for a similar issue # in https://github.com/kubernetes-client/python/issues/376 which has been used here # pylint: disable=no-member - from kubernetes.client.models.v1_event import V1Event + try: + from kubernetes.client.models.core_v1_event import CoreV1Event as V1Event + except ImportError: + from kubernetes.client.models.v1_event import V1Event + def local_involved_object(self, involved_object): if involved_object is None: involved_object = client.V1ObjectReference(api_version="1") @@ -409,14 +413,14 @@ class KubernetesEvent(object): event_source = client.V1EventSource(component="ceph-mgr", host=self.host) - return client.V1Event( - involved_object=obj_ref, - metadata=obj_meta, - message=self.message, - count=self.count, + return V1Event( + involved_object=obj_ref, + metadata=obj_meta, + message=self.message, + count=self.count, type=self.event_type, reason=self.event_reason, - source=event_source, + source=event_source, first_timestamp=self.first_timestamp, last_timestamp=self.last_timestamp ) diff --git a/src/pybind/mgr/requirements.txt b/src/pybind/mgr/requirements.txt index 7daee3323..044674f9b 100644 --- a/src/pybind/mgr/requirements.txt +++ b/src/pybind/mgr/requirements.txt @@ -1,5 +1,5 @@ -rrequirements-required.txt asyncssh==2.9 -kubernetes==11.0.0 +kubernetes urllib3==1.26.15 pytest==7.4.4 |