locker->eval_gather(&lock);
}
-
+void CDentry::_put()
+{
+ if (get_num_ref() <= (int)is_dirty() + 1) {
+ CDentry::linkage_t *dnl = get_projected_linkage();
+ if (dnl->is_primary()) {
+ CInode *in = dnl->get_inode();
+ if (get_num_ref() == (int)is_dirty() + !!in->get_num_ref())
+ in->mdcache->maybe_eval_stray(in, true);
+ }
+ }
+}
static const int STATE_FRAGMENTING = (1<<1);
static const int STATE_PURGING = (1<<2);
static const int STATE_BADREMOTEINO = (1<<3);
+ // stray dentry needs notification of releasing reference
+ static const int STATE_STRAY = STATE_NOTIFYREF;
// -- pins --
static const int PIN_INODEPIN = 1; // linked inode is pinned
void last_put() {
lru_unpin();
}
+ void _put();
// auth pins
bool can_auth_pin();
}
bool purged_any = false;
+ bool stray = inode->is_stray();
//int num_new_inodes_loaded = 0;
loff_t baseoff = p.get_off();
if (in->inode.is_dirty_rstat())
in->mark_dirty_rstat();
+ if (stray) {
+ dn->state_set(CDentry::STATE_STRAY);
+ if (in->inode.nlink == 0)
+ in->state_set(CInode::STATE_ORPHAN);
+ }
+
//in->hack_accessed = false;
//in->hack_load_stamp = ceph_clock_now(g_ceph_context);
//num_new_inodes_loaded++;
parent->put(CDentry::PIN_INODEPIN);
}
+void CInode::_put()
+{
+ if (get_num_ref() == (int)is_dirty() + (int)is_dirty_parent())
+ mdcache->maybe_eval_stray(this, true);
+}
+
void CInode::add_remote_parent(CDentry *p)
{
if (remote_parents.empty())
static const int STATE_STRAYPINNED = (1<<16);
static const int STATE_FROZENAUTHPIN = (1<<17);
static const int STATE_DIRTYPOOL = (1<<18);
+ // orphan inode needs notification of releasing reference
+ static const int STATE_ORPHAN = STATE_NOTIFYREF;
static const int MASK_STATE_EXPORTED =
(STATE_DIRTY|STATE_NEEDSRECOVER|STATE_DIRTYPARENT|STATE_DIRTYPOOL);
}
void first_get();
void last_put();
+ void _put();
// -- hierarchy stuff --
} else
assert(straydn->get_projected_linkage()->is_null());
+ straydn->state_set(CDentry::STATE_STRAY);
return straydn;
}
// add back into lru (at the top)
lru.lru_insert_top(dn);
+ if (dn->get_dir()->get_inode()->is_stray()) {
+ dn->state_set(CDentry::STATE_STRAY);
+ if (dnl->is_primary() && dnl->get_inode()->inode.nlink == 0)
+ dnl->get_inode()->state_set(CInode::STATE_ORPHAN);
+ }
+
if (!first_auth) {
first_auth = dn;
} else {
CInode *in = dn->get_linkage()->get_inode();
dout(10) << "_purge_stray_logged " << *dn << " " << *in << dendl;
- dn->state_clear(CDentry::STATE_PURGING);
- dn->put(CDentry::PIN_PURGING);
-
assert(!in->state_test(CInode::STATE_RECOVERING));
// unlink
dn->dir->pop_and_dirty_projected_fnode(ls);
+ in->state_clear(CInode::STATE_ORPHAN);
+ dn->state_clear(CDentry::STATE_PURGING);
+ dn->put(CDentry::PIN_PURGING);
+
// drop inode
if (in->is_dirty())
in->mark_clean();
inode_t *pi = in->project_inode();
mdr->add_projected_inode(in); // do this _after_ my dn->pre_dirty().. we apply that one manually.
pi->version = in->pre_dirty();
- pi->nlink--;
pi->ctime = mdr->now;
+ pi->nlink--;
+ if (pi->nlink == 0)
+ in->state_set(CInode::STATE_ORPHAN);
if (dnl->is_primary()) {
// primary link. add stray dentry.
pi->nlink--;
}
if (tpi) {
- tpi->nlink--;
tpi->ctime = mdr->now;
+ tpi->nlink--;
+ if (tpi->nlink == 0)
+ oldin->state_set(CInode::STATE_ORPHAN);
}
}
// -- state --
const static int STATE_AUTH = (1<<30);
const static int STATE_DIRTY = (1<<29);
- const static int STATE_REJOINING = (1<<28); // replica has not joined w/ primary copy
- const static int STATE_REJOINUNDEF = (1<<27); // contents undefined.
+ const static int STATE_NOTIFYREF = (1<<28); // notify dropping ref drop through _put()
+ const static int STATE_REJOINING = (1<<27); // replica has not joined w/ primary copy
+ const static int STATE_REJOINUNDEF = (1<<26); // contents undefined.
// -- wait --
#endif
assert(ref > 0);
}
+ virtual void _put() {}
void put(int by) {
#ifdef MDS_REF_SET
if (ref == 0 || ref_map[by] == 0) {
#endif
if (ref == 0)
last_put();
+ if (state_test(STATE_NOTIFYREF))
+ _put();
}
}