diff --git a/src/client/Client.cc b/src/client/Client.cc index 03b6438..b849328 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -456,14 +456,19 @@ void Client::shutdown() // =================== // metadata cache stuff -void Client::trim_cache() +void Client::trim_cache(unsigned max) { - ldout(cct, 20) << "trim_cache size " << lru.lru_get_size() << " max " << lru.lru_get_max() << dendl; + if (max > lru.lru_get_max()) + max = lru.lru_get_max(); + + ldout(cct, 20) << "trim_cache size " << lru.lru_get_size() << " max " << max << dendl; + unsigned last = 0; while (lru.lru_get_size() != last) { last = lru.lru_get_size(); - if (lru.lru_get_size() <= lru.lru_get_max()) break; + if (lru.lru_get_size() <= max) + break; // trim! Dentry *dn = static_cast(lru.lru_expire()); @@ -473,6 +478,22 @@ void Client::trim_cache() trim_dentry(dn); } + // notify kernel to invalidate top level directory entries. As a side effect, + // unused inodes underneath these entries get pruned. + if (dentry_invalidate_cb && lru.lru_get_size() > max) { + if (root->dir) { + for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); + p != root->dir->dentries.end(); + ++p) { + if (p->second->inode) + _schedule_invalidate_dentry_callback(p->second, false); + } + } else { + // This seems unnatural, as long as we are holding caps they must be on + // some descendent of the root, so why don't we have the root open?` + } + } + // hose root? if (lru.lru_get_size() == 0 && root && root->get_num_ref() == 0 && inode_map.size() == 1) { ldout(cct, 15) << "trim_cache trimmed root " << root << dendl; @@ -1953,8 +1974,13 @@ void Client::handle_mds_map(MMDSMap* m) if (!mdsmap->is_up(p->first) || mdsmap->get_inst(p->first) != p->second->inst) { messenger->mark_down(p->second->con); - if (mdsmap->is_up(p->first)) + if (mdsmap->is_up(p->first)) { p->second->inst = mdsmap->get_inst(p->first); + // When new MDS starts to take over, notify kernel to trim unused entries + // in its dcache/icache. Hopefully, the kernel will release some unused + // inodes before the new MDS enters reconnect state. + trim_cache(1); + } } else if (oldstate == newstate) continue; // no change @@ -1992,6 +2018,14 @@ void Client::send_reconnect(MetaSession *session) int mds = session->mds_num; ldout(cct, 10) << "send_reconnect to mds." << mds << dendl; + // trim unused caps to reduce MDS's cache rejoin time + trim_cache(1); + + if (session->release) { + session->release->put(); + session->release = NULL; + } + MClientReconnect *m = new MClientReconnect; // i have an open session. diff --git a/src/client/Client.h b/src/client/Client.h index 4a3d753..69492cb 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -392,7 +392,7 @@ protected: void touch_dn(Dentry *dn); // trim cache. - void trim_cache(); + void trim_cache(unsigned max=-1U); void trim_dentry(Dentry *dn); void trim_caps(MetaSession *s, int max);