if (!straydn)
return;
dout(10) << " straydn is " << *straydn << dendl;
+ } else if (dnl->is_referent_remote()) {
+ straydn = prepare_stray_dentry(mdr, dnl->get_referent_inode());
+ if (!straydn)
+ return;
+ dout(10) << __func__ << " referent straydn is " << *straydn << dendl;
} else if (mdr->straydn) {
mdr->unpin(mdr->straydn);
mdr->straydn = NULL;
CDentry::linkage_t *dnl = dn->get_projected_linkage();
CInode *in = dnl->get_inode();
-
+ CInode *ref_in = dnl->get_referent_inode();
+ if (dnl->is_referent_remote())
+ ceph_assert(ref_in->is_auth());
// ok, let's do it.
mdr->ls = mdlog->get_current_segment();
}
if (straydn) {
- ceph_assert(dnl->is_primary());
- straydn->push_projected_linkage(in);
+ ceph_assert(dnl->is_primary() || dnl->is_referent_remote());
+ if (dnl->is_primary())
+ straydn->push_projected_linkage(in);
+ else if (dnl->is_referent_remote()) {
+ straydn->push_projected_linkage(ref_in);
+ }
}
// the unlinked dentry
// will manually pop projected inode
// primary link. add stray dentry.
- mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
- mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
+ if (dnl->is_primary()) {
+ mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
+ mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
- pi.inode->update_backtrace();
- le->metablob.add_primary_dentry(straydn, in, true, true);
+ pi.inode->update_backtrace();
+ le->metablob.add_primary_dentry(straydn, in, true, true);
+ } else if (dnl->is_referent_remote()) {
+ // referent remote link - to purge the referent inode created
+ auto pri = ref_in->project_inode(mdr);
+ {
+ std::string t;
+ dn->make_path_string(t, true);
+ pri.inode->stray_prior_path = std::move(t);
+ }
+ pri.inode->version = ref_in->pre_dirty();
+ // Purge enqueue requires inode to be primary and nlink to be 0
+ // link count is never > 1 for referent inode, just set it to 0
+ pri.inode->nlink = 0;
+ ref_in->state_set(CInode::STATE_ORPHAN);
+ mdcache->predirty_journal_parents(mdr, &le->metablob, ref_in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
+ pri.inode->update_backtrace();
+ le->metablob.add_primary_dentry(straydn, ref_in, true, true);
+
+ mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
+ mdcache->predirty_journal_parents(mdr, &le->metablob, in, 0, PREDIRTY_PRIMARY);
+ mdcache->journal_dirty_inode(mdr.get(), &le->metablob, in);
+ }
} else {
// remote link. update remote inode.
mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
if (straydn) {
// if there is newly created snaprealm, need to split old snaprealm's
// inodes_with_caps. So pop snaprealm before linkage changes.
- strayin = dn->get_linkage()->get_inode();
- hadrealm = strayin->snaprealm ? true : false;
- strayin->early_pop_projected_snaprealm();
+ if (dn->get_linkage()->is_primary()) {
+ strayin = dn->get_linkage()->get_inode();
+ hadrealm = strayin->snaprealm ? true : false;
+ strayin->early_pop_projected_snaprealm();
+ } else if (dn->get_linkage()->is_referent_remote()) {
+ // No snapshots on referent inodes - Ignore snaprealm related stuff for referent inodes
+ strayin = dn->get_linkage()->get_referent_inode();
+ }
}
// unlink main dentry