The importer also needs to scatter pin. This avoids scatterlock gather
races like so:
A: start exporting to B
A: freeze, scatter pin tree
C: initiate gather
A: delay replay to gather
B: reply to gather, do not include (non-auth) dirfrag
A,B: finish migration
A: reply to gather, do not include (now non-auth) dirfrag
C: gets no info about the dirfrag!
By pinning on the importer, we ensure that at least one MDS will respond
to the gather with auth dirfrag info.
Signed-off-by: Sage Weil <sage@newdream.net>
// freeze.
dir->_freeze_tree();
+
+ // pin parent scatterlocks (sloppily!)
+ dir->inode->get_scatter_pin();
// ok!
dout(7) << " sending export_prep_ack on " << *dir << dendl;
{
dout(7) << "import_reverse_unfreeze " << *dir << dendl;
dir->unfreeze_tree();
+ list<Context*> ls;
+ dir->inode->put_scatter_pin(ls);
+ mds->queue_waiters(ls);
cache->discard_delayed_expire(dir);
import_reverse_final(dir);
}
cache->show_subtrees();
//audit(); // this fails, bc we munge up the subtree map during handle_import_map (resolve phase)
+ list<Context*> ls;
+ dir->inode->put_scatter_pin(ls);
+ mds->queue_waiters(ls);
+
// re-eval imported caps
for (map<CInode*, map<client_t,Capability::Export> >::iterator p = cap_imports.begin();
p != cap_imports.end();