dout(7) << *dnl->get_inode() << " is frozen, non-empty reply, stopping" << dendl;
break;
}
+ } else if (dnl->is_referent_remote() && dnl->get_referent_inode()->is_frozen_inode()) {
+ if (tailitem && dis->is_path_locked()) {
+ dout(7) << __func__ << " allowing discovery of frozen tail referent inode" << *dnl->get_referent_inode() << dendl;
+ } else if (reply->is_empty()) {
+ dout(7) << __func__ << *dnl->get_referent_inode() << " referent inode is frozen, empty reply, waiting" << dendl;
+ dnl->get_referent_inode()->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryMessage(mds, dis));
+ return;
+ } else {
+ dout(7) << __func__ << *dnl->get_referent_inode() << " referent inode is frozen, non-empty reply, stopping" << dendl;
+ break;
+ }
}
// add dentry
encode_replica_dentry(dn, from, reply->trace);
dout(7) << "handle_discover added dentry " << *dn << dendl;
+ // add referent inode
+ if (dnl->is_referent_remote()) {
+ CInode *referent_inode = dnl->get_referent_inode();
+ ceph_assert(referent_inode->is_auth());
+
+ encode_replica_inode(referent_inode, from, reply->trace, mds->mdsmap->get_up_features());
+ dout(7) << "handle_discover added referent inode " << *referent_inode << dendl;
+ }
+
if (!dnl->is_primary()) break; // stop on null or remote link.
// add inode
void MDCache::encode_replica_dentry(CDentry *dn, mds_rank_t to, bufferlist& bl)
{
- ENCODE_START(2, 1, bl);
+ ENCODE_START(3, 1, bl);
encode(dn->get_name(), bl);
encode(dn->last, bl);
bool need_recover = mds->get_state() < MDSMap::STATE_ACTIVE;
encode(need_recover, bl);
encode(dn->alternate_name, bl);
+ encode(dn->linkage.referent_ino, bl);
ENCODE_FINISH(bl);
}
decode(alternate_name, p);
}
+ inodeno_t referent_ino;
+ if (struct_v >= 3) {
+ decode(referent_ino, p);
+ }
+
if (is_new) {
dn->set_alternate_name(std::move(alternate_name));
- if (rino)
+ if (rino && !referent_ino)
dir->link_remote_inode(dn, rino, rdtype);
+ else if (rino && referent_ino)
+ dir->link_null_referent_inode(dn, referent_ino, rino, rdtype);
if (need_recover)
dn->lock.mark_need_recover();
} else {
else if (in->is_mdsdir())
in->inode_auth.first = in->ino() - MDS_INO_MDSDIR_OFFSET;
dout(10) << __func__ << " added " << *in << dendl;
- if (dn) {
+ if (dn && dn->get_linkage()->get_referent_ino() > 0) {
+ dout(10) << __func__ << " linking referent inode " << *in << dendl;
+ ceph_assert(!dn->get_linkage()->get_referent_inode());
+ ceph_assert(dn->get_linkage()->get_referent_ino() == in->ino());
+ dn->dir->link_referent_inode(dn, in, dn->get_linkage()->get_remote_ino(), dn->get_linkage()->get_remote_d_type());
+ } else if (dn) {
ceph_assert(dn->get_linkage()->is_null());
dn->dir->link_primary_inode(dn, in);
}
in->_decode_base(p);
in->_decode_locks_state_for_replica(p, false);
dout(10) << __func__ << " had " << *in << dendl;
+ if (dn && dn->get_linkage()->get_referent_ino() > 0) {
+ if (!dn->get_linkage()->is_referent_remote() || dn->get_linkage()->get_referent_inode() != in)
+ dout(10) << __func__ << " different referent inode linkage in dentry " << *dn << " inode " << *in << dendl;
+ }
}
- if (dn) {
+ if (dn && !dn->get_linkage()->is_referent_remote()) {
if (!dn->get_linkage()->is_primary() || dn->get_linkage()->get_inode() != in)
dout(10) << __func__ << " different linkage in dentry " << *dn << dendl;
}