- per-mds, shared standby queues
-mds segments
-- reverse_export is fuggered by the log segment business. need to delay auth/clean step until export is confirmed (i.e. make second pass over the subtree?). retest migrator! pay close attention to cache_expire checks on auth ordering... ,.dkjasdfjdajfdkjl
- - upshot: once it's done, it'll be much cleaner!
-
bugs to fix
- fix server unlink .. needs to use slave_requests to clean up any failures during the resolve stage
- fix purge_stray bug
return;
}
- if (!in->is_auth()) {
+ CDir *dir = in->get_dirfrag(frag);
+
+ if (!dir && !in->is_auth()) {
dout(10) << "opening remote dirfrag " << frag << " under " << *in << dendl;
/* FIXME: we re-query the anchortable just to avoid a fragtree update race */
open_remote_dirfrag(in, frag,
return;
}
- CDir *dir = in->get_or_open_dirfrag(this, frag);
+ if (!dir && in->is_auth())
+ dir = in->get_or_open_dirfrag(this, frag);
+
assert(dir);
if (dir->is_auth()) {
if (dir->is_complete()) {
anchortrace[i].ino,
true); // being conservative here.
mds->send_message_mds(dis, dir->authority().first, MDS_PORT_CACHE);
+ ino_discover_waiters[anchortrace[i].ino].push_back(new C_MDC_OpenRemoteIno(this, ino, anchortrace, mdr, onfinish));
}
}
CInode *cur = 0;
MDiscoverReply *reply = new MDiscoverReply(dis->get_base_ino());
+ // note ino discover in reply (if we are discovering by ino)
+ if (dis->get_want_ino())
+ reply->set_discover_ino(dis->get_want_ino());
+
// get started.
if (dis->get_base_ino() == MDS_INO_ROOT) {
// wants root
reply->add_dir( curdir->replicate_to(dis->get_asker()) );
dout(7) << "handle_discover added dir " << *curdir << dendl;
}
- if (dis->get_want().depth() == 0) break;
-
- // lookup inode?
+
+ // lookup
CDentry *dn = 0;
if (dis->get_want_ino()) {
+ // lookup by ino
CInode *in = get_inode(dis->get_want_ino());
if (in && in->is_auth() && in->get_parent_dn()->get_dir() == curdir)
dn = in->get_parent_dn();
- } else {
+ } else if (dis->get_want().depth() > 0) {
// lookup dentry
dn = curdir->lookup( dis->get_dentry(i) );
- }
-
+ } else
+ break; // done!
+
// incomplete dir?
if (!dn) {
if (!curdir->is_complete()) {
// fyi
if (m->is_flag_error_dir()) dout(7) << " flag error, dir" << dendl;
if (m->is_flag_error_dn()) dout(7) << " flag error, dentry = " << m->get_error_dentry() << dendl;
+ if (m->is_flag_error_ino()) dout(7) << " flag error, ino = " << m->get_discover_ino() << dendl;
dout(10) << "depth = " << m->get_depth()
<< ", has base_dir/base_dn/root = "
<< m->has_base_dir() << " / " << m->has_base_dentry() << " / " << m->has_base_inode()
dir_discovers.erase(cur->ino());
}
+ // kick ino discover waiters?
+ if (m->get_discover_ino()) {
+ dout(7) << " was ino discover on " << m->get_discover_ino() << dendl;
+ list<Context*> ls;
+ ls.swap(ino_discover_waiters[m->get_discover_ino()]);
+ ino_discover_waiters.erase(m->get_discover_ino());
+ finish_contexts(ls); // fixme maybe: do we want an error code here? or better to retry?
+ //finish_contexts(ls, m->is_flag_error_ino() ? -1:0);
+ }
+
// finish errors directly
finish_contexts(error, -ENOENT);
mds->queue_waiters(finished);
// -- discover --
hash_map<inodeno_t, set<int> > dir_discovers; // dirino -> mds set i'm trying to discover.
+ map<inodeno_t, list<Context*> > ino_discover_waiters;
// -- requests --
rdlocks.insert(&srctrace[i]->lock);
xlocks.insert(&srcdn->lock);
wrlocks.insert(&srcdn->dir->inode->dirlock);
- rdlocks.insert(&srcdn->dir->inode->dirfragtreelock); // rd lock on srci dirfragtree.
+ /*
+ * no, this causes problems if the dftlock is scattered...
+ * and what was i thinking anyway?
+ * rdlocks.insert(&srcdn->dir->inode->dirfragtreelock); // rd lock on srci dirfragtree.
+ */
// rdlock destdir path, xlock dest dentry
for (int i=0; i<(int)desttrace.size(); i++)
++p) {
CDir *dir = srci->get_dirfrag(*p);
if (!dir) {
- dout(10) << " opening " << *dir << dendl;
+ dout(10) << " opening " << *p << " under " << *srci << dendl;
mdcache->open_remote_dirfrag(srci, *p, new C_MDS_RetryRequest(mdcache, mdr));
return;
}
// journal it?
if (srcdn->is_auth() ||
- destdn->inode->is_auth() ||
+ (destdn->inode && destdn->inode->is_auth()) ||
srcdn->inode->is_any_caps()) {
// journal.
mdr->ls = mdlog->get_current_segment();
mdr->ls = mdlog->get_current_segment();
ESlaveUpdate *le;
if (r == 0) {
- // commit
- _rename_apply(mdr, srcdn, destdn, straydn);
-
+ // finish the inode export
if (mdr->inode_export) {
C_Contexts *fin = new C_Contexts;
mdcache->migrator->finish_export_inode(mdr->inode_export, fin);
mds->queue_waiter(fin);
}
+ // commit
+ _rename_apply(mdr, srcdn, destdn, straydn);
+
// write a commit to the journal
le = new ESlaveUpdate(mdlog, "slave_rename_commit", mdr->reqid, mdr->slave_to_mds, ESlaveUpdate::OP_COMMIT);
} else {
mdr->now);
::_encode(exported_client_map, reply->inode_export);
reply->inode_export.claim_append(inodebl);
-
reply->inode_export_v = mdr->srcdn->inode->inode.version;
+ // take note of inode; we'll need to finish the export later!
+ mdr->inode_export = mdr->srcdn->inode;
+
mds->send_message_mds(reply, mdr->slave_to_mds, MDS_PORT_SERVER);
// clean up.
bool flag_error_ino;
bool flag_error_dir;
string error_dentry; // dentry that was not found (to trigger waiters on asker)
+ inodeno_t discover_ino;
int dir_auth_hint;
bool wanted_xlocks_hint;
bool is_flag_error_ino() { return flag_error_ino; }
bool is_flag_error_dir() { return flag_error_dir; }
string& get_error_dentry() { return error_dentry; }
+ inodeno_t get_discover_ino() { return discover_ino; }
int get_dir_auth_hint() { return dir_auth_hint; }
bool get_wanted_xlocks_hint() { return wanted_xlocks_hint; }
Message(MSG_MDS_DISCOVERREPLY) {
this->base_ino = base_ino;
flag_error_dn = false;
+ flag_error_ino = false;
flag_error_dir = false;
no_base_dir = no_base_dentry = false;
+ discover_ino = 0;
dir_auth_hint = CDIR_AUTH_UNKNOWN;
}
~MDiscoverReply() {
bool is_empty() {
return dirs.empty() && dentries.empty() && inodes.empty() &&
!flag_error_dn &&
+ !flag_error_ino &&
!flag_error_dir &&
dir_auth_hint == CDIR_AUTH_UNKNOWN;
}
dirs.push_back( dir );
}
+ void set_discover_ino(inodeno_t ino) {
+ discover_ino = ino;
+ }
+
// void set_flag_forward() { flag_forward = true; }
void set_flag_error_dn(const string& dn) {
flag_error_dn = true;
::_decode(flag_error_ino, payload, off);
::_decode(flag_error_dir, payload, off);
::_decode(error_dentry, payload, off);
+ ::_decode(discover_ino, payload, off);
::_decode(dir_auth_hint, payload, off);
::_decode(wanted_xlocks_hint, payload, off);
::_encode(flag_error_ino, payload);
::_encode(flag_error_dir, payload);
::_encode(error_dentry, payload);
+ ::_encode(discover_ino, payload);
::_encode(dir_auth_hint, payload);
::_encode(wanted_xlocks_hint, payload);