async_dentry_invalidator.queue(new C_Client_DentryInvalidate(this, dn, del));
}
-void Client::_invalidate_inode_parents(Inode *in)
+void Client::_try_to_trim_inode(Inode *in)
{
+ int ref = in->get_num_ref();
+
+ if (in->dir && !in->dir->dentry_list.empty()) {
+ for (xlist<Dentry*>::iterator p = in->dir->dentry_list.begin();
+ !p.end(); ) {
+ Dentry *dn = *p;
+ ++p;
+ if (dn->lru_is_expireable())
+ unlink(dn, false, false); // close dir, drop dentry
+ }
+ --ref;
+ }
+ // make sure inode was not freed when closing dir
+ if (ref == 0)
+ return;
+
set<Dentry*>::iterator q = in->dn_set.begin();
while (q != in->dn_set.end()) {
Dentry *dn = *q++;
// may drop inode's last ref
if (deleted_inode)
- _invalidate_inode_parents(in);
+ _try_to_trim_inode(in);
m->put();
}
void _schedule_invalidate_dentry_callback(Dentry *dn, bool del);
void _async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name);
- void _invalidate_inode_parents(Inode *in);
+ void _try_to_trim_inode(Inode *in);
void _schedule_invalidate_callback(Inode *in, int64_t off, int64_t len, bool keep_caps);
void _invalidate_inode_cache(Inode *in);