.set_default(64_K)
.set_description("maximum aggregate size of extended attributes on a file"),
+ Option("mds_cache_trim_interval", Option::TYPE_SECS, Option::LEVEL_ADVANCED)
+ .set_default(1)
+ .set_description("interval in seconds between cache trimming"),
+
Option("mds_cache_size", Option::TYPE_INT, Option::LEVEL_ADVANCED)
.set_default(0)
.set_description("maximum number of inodes in MDS cache (<=0 is unlimited)")
bottom_lru.lru_set_midpoint(0);
decayrate.set_halflife(g_conf()->mds_decay_halflife);
+
+ upkeeper = std::thread([this]() {
+ std::unique_lock lock(upkeep_mutex);
+ while (!upkeep_trim_shutdown.load()) {
+ auto now = clock::now();
+ auto since = now-upkeep_last_trim;
+ auto interval = clock::duration(g_conf().get_val<std::chrono::seconds>("mds_cache_trim_interval"));
+ if (since >= interval*.90) {
+ lock.unlock(); /* mds_lock -> upkeep_mutex */
+ std::scoped_lock mds_lock(mds->mds_lock);
+ lock.lock();
+ if (upkeep_trim_shutdown.load())
+ return;
+ if (mds->is_cache_trimmable()) {
+ dout(20) << "upkeep thread trimming cache; last trim " << since << " ago" << dendl;
+ trim_client_leases();
+ trim();
+ check_memory_usage();
+ mds->server->recall_client_state(nullptr, Server::RecallFlags::ENFORCE_MAX);
+ upkeep_last_trim = clock::now();
+ } else {
+ dout(10) << "cache not ready for trimming" << dendl;
+ }
+ } else {
+ interval -= since;
+ }
+ dout(20) << "upkeep thread waiting interval " << interval << dendl;
+ upkeep_cvar.wait_for(lock, interval);
+ }
+ });
}
MDCache::~MDCache()
if (logger) {
g_ceph_context->get_perfcounters_collection()->remove(logger.get());
}
+ if (upkeeper.joinable())
+ upkeeper.join();
}
void MDCache::handle_conf_change(const std::set<std::string>& changed, const MDSMap& mdsmap)
bool MDCache::shutdown()
{
+ {
+ std::scoped_lock lock(upkeep_mutex);
+ upkeep_trim_shutdown = true;
+ upkeep_cvar.notify_one();
+ }
if (lru.lru_get_size() > 0) {
dout(7) << "WARNING: mdcache shutdown with non-empty cache" << dendl;
//show_cache();
#ifndef CEPH_MDCACHE_H
#define CEPH_MDCACHE_H
+#include <atomic>
#include <string_view>
+#include <thread>
#include "common/DecayCounter.h"
#include "include/types.h"
std::set<CInode *> export_pin_delayed_queue;
OpenFileTable open_file_table;
+
+private:
+ std::thread upkeeper;
+ ceph::mutex upkeep_mutex = ceph::make_mutex("MDCache::upkeep_mutex");
+ ceph::condition_variable upkeep_cvar;
+ time upkeep_last_trim = time::min();
+ std::atomic<bool> upkeep_trim_shutdown{false};
};
class C_MDS_RetryRequest : public MDSInternalContext {
}
// ...
- if (is_clientreplay() || is_active() || is_stopping()) {
- mdcache->trim_client_leases();
- mdcache->trim();
- mdcache->check_memory_usage();
-
- server->recall_client_state(nullptr, Server::RecallFlags::ENFORCE_MAX);
-
+ if (is_cache_trimmable()) {
server->find_idle_sessions();
server->evict_cap_revoke_non_responders();
locker->tick();
bool is_cluster_degraded() const { return cluster_degraded; }
bool allows_multimds_snaps() const { return mdsmap->allows_multimds_snaps(); }
+ bool is_cache_trimmable() const {
+ return is_clientreplay() || is_active() || is_stopping();
+ }
+
void handle_write_error(int err);
void update_mlogger();