dout(12) << "_fetched got remote link " << ino << " (don't have it)" << dendl;
}
}
- } else if (type == 'R' || type == 'r') {
- // hard link with referent inode
- InodeStore inode_data;
- inodeno_t remote_ino;
- inodeno_t referent_ino;
- unsigned char d_type;
- mempool::mds_co::string alternate_name;
-
- //Load referent inode and get remote inode details
- if (type == 'r') {
- DECODE_START(2, q);
- if (struct_v >= 2) {
- decode(alternate_name, q);
- }
- inode_data.decode(q);
- DECODE_FINISH(q);
- } else {
- inode_data.decode_bare(q);
- }
-
- //Fill in remote inode details
- remote_ino = inode_data.inode->remote_ino;
- referent_ino = inode_data.inode->ino;
- d_type = IFTODT(inode_data.inode->mode);
-
- if (stale) {
- if (!dn) {
- stale_items.insert(mempool::mds_co::string(key));
- *force_dirty = true;
- }
- return dn;
- }
-
- bool undef_inode = false;
- if (dn) {
- CDentry::linkage_t *dnl = dn->get_linkage();
- dout(12) << __func__ << "_fetched had " << (dnl->is_null() ? "NEG" : "") << " dentry " << *dn << dendl;
- if (dnl->is_referent_remote()) {
- CInode *ref_in = dnl->get_referent_inode();
- if (ref_in->state_test(CInode::STATE_REJOINUNDEF)) {
- undef_inode = true;
- } else if (committed_version == 0 &&
- dnl->is_referent_remote() &&
- dn->is_dirty() &&
- remote_ino == dnl->get_remote_ino() &&
- d_type == dnl->get_remote_d_type() &&
- alternate_name == dn->get_alternate_name() &&
- referent_ino == dnl->get_referent_ino() &&
- referent_ino == ref_in->ino() &&
- inode_data.inode->version == ref_in->get_version()) {
- // see comment below
- dout(10) << __func__ << "_fetched had underwater dentry " << *dn << ", marking clean" << dendl;
- dn->mark_clean();
- dout(10) << __func__ << "_fetched had underwater referent inode " << *dnl->get_referent_inode() << ", marking clean" << dendl;
- ref_in->mark_clean();
- }
- } else {
- dout(10) << __func__ << "_fetched dentry was present but dnl is not referent!!! " << *dn << dendl;
- }
- }
-
- if (!dn || undef_inode) {
- // (referent remote) link
- // add referent inode
- CInode *ref_in = mdcache->get_inode(referent_ino, last);
- if (!ref_in || undef_inode) {
- if (undef_inode && ref_in) {
- ref_in->first = first;
- } else {
- ref_in = new CInode(mdcache, true, first, last);
- }
-
- ref_in->reset_inode(std::move(inode_data.inode));
- ref_in->reset_xattrs(std::move(inode_data.xattrs));
-
- ref_in->dirfragtree.swap(inode_data.dirfragtree);
- ref_in->reset_old_inodes(std::move(inode_data.old_inodes));
- if (ref_in->is_any_old_inodes()) {
- snapid_t min_first = ref_in->get_old_inodes()->rbegin()->first + 1;
- if (min_first > ref_in->first)
- ref_in->first = min_first;
- }
-
- ref_in->oldest_snap = inode_data.oldest_snap;
- ref_in->decode_snap_blob(inode_data.snap_blob);
- if (snaps && !ref_in->snaprealm)
- ref_in->purge_stale_snap_data(*snaps);
-
- if (!undef_inode) {
- dout(15) << __func__ << "_fetched referent inode created " << *ref_in << " parent " << ref_in->parent << dendl;
- mdcache->add_inode(ref_in); // add
- mdcache->insert_taken_inos(ref_in->ino());
- dn = add_remote_dentry(dname, ref_in, remote_ino, d_type, std::move(alternate_name), first, last);
- } else {
- dout(15) << __func__ << "_fetched referent inode found in memory " << *ref_in << " parent " << ref_in->parent << dendl;
- }
-
- ref_in->maybe_ephemeral_rand(rand_threshold);
-
- // link to inode?
- CInode *remote_in = mdcache->get_inode(remote_ino); // we may or may not have it.
- if (remote_in) {
- //referent_inode is already linked above in add_remote_dentry
- dn->link_remote(dn->get_linkage(), remote_in, ref_in);
- dout(12) << __func__ << "_fetched got remote link " << remote_ino << " which we have " << *remote_in << dendl;
- } else {
- dout(12) << __func__ << "_fetched got remote link " << remote_ino << " (don't have it)" << dendl;
- }
- } else {
- dout(0) << __func__ << "_fetched badness: got referent inode (but i already had) " << *ref_in
- << " mode " << ref_in->get_inode()->mode
- << " mtime " << ref_in->get_inode()->mtime << dendl;
- string dirpath, inopath;
- this->inode->make_trimmed_path_string(dirpath);
- ref_in->make_trimmed_path_string(inopath);
- mdcache->mds->clog->error() << "loaded dup referent inode " << inode_data.inode->ino
- << " [" << first << "," << last << "] v" << inode_data.inode->version
- << " at " << dirpath << "/" << dname
- << ", but inode " << ref_in->vino() << " v" << ref_in->get_version()
- << " already exists at " << inopath;
- return dn;
- }
- }
} else if (type == 'I' || type == 'i') {
InodeStore inode_data;
mempool::mds_co::string alternate_name;