summaryrefslogtreecommitdiffstats
path: root/src/mds
diff options
context:
space:
mode:
Diffstat (limited to 'src/mds')
-rw-r--r--src/mds/Beacon.cc24
-rw-r--r--src/mds/MDSAuthCaps.h17
-rw-r--r--src/mds/Server.cc23
-rw-r--r--src/mds/SessionMap.cc1
-rw-r--r--src/mds/SessionMap.h12
-rw-r--r--src/mds/mdstypes.cc26
-rw-r--r--src/mds/mdstypes.h3
7 files changed, 84 insertions, 22 deletions
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)