filer(m->objecter, m->finisher),
exceeded_size_limit(false),
recovery_queue(m),
- stray_manager(m, purge_queue_)
+ stray_manager(m, purge_queue_),
+ trim_counter(ceph_clock_now(), g_conf->get_val<double>("mds_cache_trim_decay_rate"))
{
migrator.reset(new Migrator(mds, this));
root = NULL;
cache_health_threshold = g_conf->get_val<double>("mds_health_cache_threshold");
if (changed.count("mds_cache_mid"))
lru.lru_set_midpoint(g_conf->get_val<double>("mds_cache_mid"));
+ if (changed.count("mds_cache_trim_decay_rate")) {
+ trim_counter = DecayCounter(ceph_clock_now(), g_conf->get_val<double>("mds_cache_trim_decay_rate"));
+ }
migrator->handle_conf_change(conf, changed, mdsmap);
mds->balancer->handle_conf_change(conf, changed, mdsmap);
// ================================================================================
// cache trimming
-void MDCache::trim_lru(uint64_t count, map<mds_rank_t, MCacheExpire*> &expiremap)
+std::pair<bool, uint64_t> MDCache::trim_lru(uint64_t count, map<mds_rank_t, MCacheExpire*> &expiremap)
{
bool is_standby_replay = mds->is_standby_replay();
std::vector<CDentry *> unexpirables;
uint64_t trimmed = 0;
+ auto trim_threshold = g_conf->get_val<uint64_t>("mds_cache_trim_threshold");
+
dout(7) << "trim_lru trimming " << count
<< " items from LRU"
<< " size=" << lru.lru_get_size()
<< " pinned=" << lru.lru_get_num_pinned()
<< dendl;
- for (;;) {
+ const uint64_t trim_counter_start = trim_counter.get(ceph_clock_now());
+ bool throttled = false;
+ while (1) {
+ throttled |= trim_counter_start+trimmed >= trim_threshold;
+ if (throttled) break;
CDentry *dn = static_cast<CDentry*>(bottom_lru.lru_expire());
if (!dn)
break;
unexpirables.clear();
// trim dentries from the LRU until count is reached
- while (cache_toofull() || count > 0) {
+ while (!throttled && (cache_toofull() || count > 0)) {
+ throttled |= trim_counter_start+trimmed >= trim_threshold;
+ if (throttled) break;
CDentry *dn = static_cast<CDentry*>(lru.lru_expire());
if (!dn) {
break;
if (count > 0) count--;
}
}
+ trim_counter.hit(ceph_clock_now(), trimmed);
for (auto &dn : unexpirables) {
lru.lru_insert_mid(dn);
unexpirables.clear();
dout(7) << "trim_lru trimmed " << trimmed << " items" << dendl;
+ return std::pair<bool, uint64_t>(throttled, trimmed);
}
/*
*
* @param count is number of dentries to try to expire
*/
-bool MDCache::trim(uint64_t count)
+std::pair<bool, uint64_t> MDCache::trim(uint64_t count)
{
uint64_t used = cache_size();
uint64_t limit = cache_memory_limit;
// process delayed eval_stray()
stray_manager.advance_delayed();
- trim_lru(count, expiremap);
+ auto result = trim_lru(count, expiremap);
+ auto& trimmed = result.second;
// trim non-auth, non-bound subtrees
for (auto p = subtrees.begin(); p != subtrees.end();) {
continue;
migrator->export_empty_import(dir);
+ ++trimmed;
}
} else {
if (!diri->is_auth()) {
rejoin_ack_gather.count(dir->get_dir_auth().first))
continue;
trim_dirfrag(dir, 0, expiremap);
+ ++trimmed;
}
}
}
root->get_dirfrags(ls);
for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p) {
CDir *dir = *p;
- if (dir->get_num_ref() == 1) // subtree pin
+ if (dir->get_num_ref() == 1) { // subtree pin
trim_dirfrag(dir, 0, expiremap);
+ ++trimmed;
+ }
}
- if (root->get_num_ref() == 0)
+ if (root->get_num_ref() == 0) {
trim_inode(0, root, 0, expiremap);
+ ++trimmed;
+ }
}
std::set<mds_rank_t> stopping;
list<CDir*> ls;
mdsdir_in->get_dirfrags(ls);
for (auto dir : ls) {
- if (dir->get_num_ref() == 1) // subtree pin
+ if (dir->get_num_ref() == 1) { // subtree pin
trim_dirfrag(dir, dir, expiremap);
+ ++trimmed;
+ }
}
- if (mdsdir_in->get_num_ref() == 0)
+ if (mdsdir_in->get_num_ref() == 0) {
trim_inode(NULL, mdsdir_in, NULL, expiremap);
+ ++trimmed;
+ }
} else {
dout(20) << __func__ << ": some unexpirable contents in mdsdir" << dendl;
}
dout(20) << __func__ << ": maybe trimming base: " << *(*p) << dendl;
if ((*p)->get_num_ref() == 0) {
trim_inode(NULL, *p, NULL, expiremap);
+ ++trimmed;
}
}
}
// send any expire messages
send_expire_messages(expiremap);
- return true;
+ return result;
}
void MDCache::send_expire_messages(map<mds_rank_t, MCacheExpire*>& expiremap)
#include <boost/utility/string_view.hpp>
+#include "common/DecayCounter.h"
#include "include/types.h"
#include "include/filepath.h"
#include "include/elist.h"
size_t get_cache_size() { return lru.lru_get_size(); }
// trimming
- bool trim(uint64_t count=0);
+ std::pair<bool, uint64_t> trim(uint64_t count=0);
private:
- void trim_lru(uint64_t count, map<mds_rank_t, MCacheExpire*>& expiremap);
+ std::pair<bool, uint64_t> trim_lru(uint64_t count, map<mds_rank_t, MCacheExpire*>& expiremap);
bool trim_dentry(CDentry *dn, map<mds_rank_t, MCacheExpire*>& expiremap);
void trim_dirfrag(CDir *dir, CDir *con,
map<mds_rank_t, MCacheExpire*>& expiremap);
LogSegment *ls, bufferlist *rollback=NULL);
void finish_uncommitted_fragment(dirfrag_t basedirfrag, int op);
void rollback_uncommitted_fragment(dirfrag_t basedirfrag, list<frag_t>& old_frags);
+
+
+ DecayCounter trim_counter;
+
public:
void wait_for_uncommitted_fragment(dirfrag_t dirfrag, MDSInternalContextBase *c) {
assert(uncommitted_fragments.count(dirfrag));