}
}
-void Client::put_inode(Inode *in, int n)
+void Client::_put_inode(Inode *in, int n)
{
ldout(cct, 10) << __func__ << " on " << *in << dendl;
+
int left = in->_put(n);
if (left == 0) {
// release any caps
}
}
+void Client::delay_put_inodes(bool wakeup)
+{
+ ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
+
+ std::map<Inode*,int> release;
+ {
+ std::scoped_lock dl(delay_i_lock);
+ release.swap(delay_i_release);
+ }
+
+ for (auto &[in, cnt] : release)
+ _put_inode(in, cnt);
+
+ if (wakeup)
+ mount_cond.notify_all();
+}
+
+void Client::put_inode(Inode *in, int n)
+{
+ ldout(cct, 20) << __func__ << " on " << *in << " n = " << n << dendl;
+
+ std::scoped_lock dl(delay_i_lock);
+ delay_i_release[in] += n;
+}
+
void Client::close_dir(Dir *dir)
{
Inode *in = dir->parent_inode;
// empty lru cache
trim_cache();
+ delay_put_inodes();
+
while (lru.lru_get_size() > 0 ||
!inode_map.empty()) {
ldout(cct, 2) << "cache still has " << lru.lru_get_size()
<< "+" << inode_map.size() << " items"
<< ", waiting (for caps to release?)"
<< dendl;
+
if (auto r = mount_cond.wait_for(lock, ceph::make_timespan(5));
r == std::cv_status::timeout) {
dump_cache(NULL);
if (!mount_aborted)
collect_and_send_metrics();
+ delay_put_inodes(is_unmounting());
trim_cache(true);
if (blocklisted && (is_mounted() || is_unmounting()) &&
// -- metadata cache stuff
// decrease inode ref. delete if dangling.
+ void _put_inode(Inode *in, int n);
+ void delay_put_inodes(bool wakeup=false);
void put_inode(Inode *in, int n=1);
void close_dir(Dir *dir);
uint64_t cap_hits = 0;
uint64_t cap_misses = 0;
+
+ ceph::spinlock delay_i_lock;
+ std::map<Inode*,int> delay_i_release;
};
/**