* however, we may expire a replica whose authority is recovering.
*
*/
-bool MDCache::trim(int max)
+bool MDCache::trim(int max, int count)
{
// trim LRU
- if (max < 0) {
+ if (count > 0) {
+ max = lru.lru_get_size() - count;
+ if (max <= 0)
+ max = 1;
+ } else if (max < 0) {
max = g_conf->mds_cache_size;
- if (!max) return false;
+ if (max <= 0)
+ return false;
}
dout(7) << "trim max=" << max << " cur=" << lru.lru_get_size() << dendl;
size_t get_cache_size() { return lru.lru_get_size(); }
// trimming
- bool trim(int max = -1); // trim cache
+ bool trim(int max=-1, int count=-1); // trim cache
bool trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap);
void trim_dirfrag(CDir *dir, CDir *con,
map<int, MCacheExpire*>& expiremap);
}
void touch_dentry_bottom(CDentry *dn) {
lru.lru_bottouch(dn);
- if (dn->get_projected_linkage()->is_primary()) {
+ if (dn->get_projected_linkage()->is_primary() &&
+ dn->get_dir()->inode->is_stray()) {
CInode *in = dn->get_projected_linkage()->get_inode();
if (in->has_dirfrags()) {
list<CDir*> ls;
void Migrator::finish_export_dir(CDir *dir, utime_t now, int peer,
map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
- list<Context*>& finished)
+ list<Context*>& finished, int *num_dentries)
{
dout(10) << "finish_export_dir " << *dir << dendl;
// subdirs?
in->get_nested_dirfrags(subdirs);
}
+
+ cache->touch_dentry_bottom(dn); // move dentry to tail of LRU
+ ++(*num_dentries);
}
// subdirs
for (list<CDir*>::iterator it = subdirs.begin(); it != subdirs.end(); ++it)
- finish_export_dir(*it, now, peer, peer_imported, finished);
+ finish_export_dir(*it, now, peer, peer_imported, finished, num_dentries);
}
class C_MDS_ExportFinishLogged : public Context {
assert(g_conf->mds_kill_export_at != 13);
// finish export (adjust local cache state)
+ int num_dentries = 0;
C_Contexts *fin = new C_Contexts(g_ceph_context);
- finish_export_dir(dir, ceph_clock_now(g_ceph_context),
- it->second.peer, it->second.peer_imported, fin->contexts);
+ finish_export_dir(dir, ceph_clock_now(g_ceph_context), it->second.peer,
+ it->second.peer_imported, fin->contexts, &num_dentries);
dir->add_waiter(CDir::WAIT_UNFREEZE, fin);
// unfreeze
cache->show_subtrees();
audit();
+ cache->trim(-1, num_dentries); // try trimming exported dentries
+
// send pending import_maps?
mds->mdcache->maybe_send_pending_resolves();
!dir->get_inode()->has_subtree_root_dirfrag(mds->get_nodeid()))
dir->get_inode()->clear_scatter_dirty();
+ int num_dentries = 0;
// adjust auth bits.
list<CDir*> q;
q.push_back(dir);
if (bounds.count(*p) == 0)
q.push_back(*p);
}
+
+ cache->touch_dentry_bottom(dn); // move dentry to tail of LRU
+ ++num_dentries;
}
}
cache->try_subtree_merge(dir); // NOTE: this may journal subtree map as side effect
+ cache->trim(-1, num_dentries); // try trimming dentries
+
// bystanders?
if (stat.bystanders.empty()) {
dout(7) << "no bystanders, finishing reverse now" << dendl;
utime_t now);
void finish_export_dir(CDir *dir, utime_t now, int target,
map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
- list<Context*>& finished);
+ list<Context*>& finished, int *num_dentries);
void add_export_finish_waiter(CDir *dir, Context *c) {
map<CDir*, export_state_t>::iterator it = export_state.find(dir);