struct C_MDC_OpenInoTraverseDir : public MDCacheContext {
inodeno_t ino;
+ MMDSOpenIno *msg;
+ bool parent;
public:
- C_MDC_OpenInoTraverseDir(MDCache *c, inodeno_t i) : MDCacheContext(c), ino(i) {}
+ C_MDC_OpenInoTraverseDir(MDCache *c, inodeno_t i, MMDSOpenIno *m, bool p) :
+ MDCacheContext(c), ino(i), msg(m), parent(p) {}
void finish(int r) {
+ if (r < 0 && !parent)
+ r = -EAGAIN;
+ if (msg) {
+ mdcache->handle_open_ino(msg, r);
+ return;
+ }
assert(mdcache->opening_inodes.count(ino));
- assert(r >= 0);
mdcache->_open_ino_traverse_dir(ino, mdcache->opening_inodes[ino], r);
}
};
new C_OnFinisher(fin, mds->finisher));
return;
}
+ err = 0; // backtrace.ancestors.empty() is checked below
}
if (err == 0) {
if (info.ancestors[0] == backtrace.ancestors[0]) {
dout(10) << " got same parents " << info.ancestors[0] << " 2 times" << dendl;
err = -EINVAL;
+ } else {
+ info.last_err = 0;
}
}
}
if (err) {
- dout(10) << " failed to open ino " << ino << dendl;
+ dout(0) << " failed to open ino " << ino << " err " << err << "/" << info.last_err << dendl;
+ if (info.last_err)
+ err = info.last_err;
open_ino_finish(ino, info, err);
return;
}
}
}
-MDSInternalContextBase* MDCache::_open_ino_get_waiter(inodeno_t ino, MMDSOpenIno *m)
-{
- if (m)
- return new C_MDS_RetryMessage(mds, m);
- else
- return new C_MDC_OpenInoTraverseDir(this, ino);
-}
-
void MDCache::_open_ino_traverse_dir(inodeno_t ino, open_ino_info_t& info, int ret)
{
dout(10) << __func__ << ": ino " << ino << " ret " << ret << dendl;
do_open_ino(ino, info, ret);
}
-void MDCache::_open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir)
+void MDCache::_open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir, bool parent)
{
if (dir->state_test(CDir::STATE_REJOINUNDEF))
assert(dir->get_inode()->dirfragtree.is_leaf(dir->get_frag()));
- dir->fetch(_open_ino_get_waiter(ino, m));
+ dir->fetch(new C_MDC_OpenInoTraverseDir(this, ino, m, parent));
}
int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m,
if (!diri) {
if (discover && MDS_INO_IS_MDSDIR(ancestors[i].dirino)) {
- open_foreign_mdsdir(ancestors[i].dirino, _open_ino_get_waiter(ino, m));
+ open_foreign_mdsdir(ancestors[i].dirino, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0));
return 1;
}
continue;
while (dir->state_test(CDir::STATE_REJOINUNDEF) &&
dir->get_inode()->state_test(CInode::STATE_REJOINUNDEF))
dir = dir->get_inode()->get_parent_dir();
- _open_ino_fetch_dir(ino, m, dir);
+ _open_ino_fetch_dir(ino, m, dir, i == 0);
return 1;
}
if (diri->is_auth()) {
if (diri->is_frozen()) {
dout(10) << " " << *diri << " is frozen, waiting " << dendl;
- diri->add_waiter(CDir::WAIT_UNFREEZE, _open_ino_get_waiter(ino, m));
+ diri->add_waiter(CDir::WAIT_UNFREEZE, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0));
return 1;
}
dir = diri->get_or_open_dirfrag(this, fg);
} else if (discover) {
- open_remote_dirfrag(diri, fg, _open_ino_get_waiter(ino, m));
+ open_remote_dirfrag(diri, fg, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0));
return 1;
}
}
if (dnl && dnl->is_primary() &&
dnl->get_inode()->state_test(CInode::STATE_REJOINUNDEF)) {
dout(10) << " fetching undef " << *dnl->get_inode() << dendl;
- _open_ino_fetch_dir(ino, m, dir);
+ _open_ino_fetch_dir(ino, m, dir, i == 0);
return 1;
}
if (!dnl && !dir->is_complete() &&
(!dir->has_bloom() || dir->is_in_bloom(name))) {
dout(10) << " fetching incomplete " << *dir << dendl;
- _open_ino_fetch_dir(ino, m, dir);
+ _open_ino_fetch_dir(ino, m, dir, i == 0);
return 1;
}
} else if (discover) {
if (!dnl) {
filepath path(name, 0);
- discover_path(dir, CEPH_NOSNAP, path, _open_ino_get_waiter(ino, m),
+ discover_path(dir, CEPH_NOSNAP, path, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0),
(i == 0 && want_xlocked));
return 1;
}
if (dnl->is_null() && !dn->lock.can_read(-1)) {
dout(10) << " null " << *dn << " is not readable, waiting" << dendl;
- dn->lock.add_waiter(SimpleLock::WAIT_RD, _open_ino_get_waiter(ino, m));
+ dn->lock.add_waiter(SimpleLock::WAIT_RD, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0));
return 1;
}
dout(10) << " no ino " << next_ino << " in " << *dir << dendl;
void MDCache::do_open_ino(inodeno_t ino, open_ino_info_t& info, int err)
{
- if (err < 0) {
+ if (err < 0 && err != -EAGAIN) {
info.checked.clear();
info.checked.insert(mds->get_nodeid());
info.checking = MDS_RANK_NONE;
info.discover = false;
info.ancestors.clear();
}
+ if (err != -ENOENT && err != -ENOTDIR)
+ info.last_err = err;
}
if (info.check_peers) {
}
}
-void MDCache::handle_open_ino(MMDSOpenIno *m)
+void MDCache::handle_open_ino(MMDSOpenIno *m, int err)
{
- dout(10) << "handle_open_ino " << *m << dendl;
+ dout(10) << "handle_open_ino " << *m << " err " << err << dendl;
inodeno_t ino = m->ino;
MMDSOpenInoReply *reply;
} else {
reply->hint = in->authority().first;
}
+ } else if (err < 0) {
+ reply = new MMDSOpenInoReply(m->get_tid(), ino, MDS_RANK_NONE, err);
} else {
mds_rank_t hint = MDS_RANK_NONE;
int ret = open_ino_traverse_dir(ino, m, m->ancestors, false, false, &hint);
bool want_xlocked;
version_t tid;
int64_t pool;
+ int last_err;
list<MDSInternalContextBase*> waiters;
open_ino_info_t() : checking(MDS_RANK_NONE), auth_hint(MDS_RANK_NONE),
check_peers(true), fetch_backtrace(true), discover(false),
- want_replica(false), want_xlocked(false), tid(0), pool(-1) {}
+ want_replica(false), want_xlocked(false), tid(0), pool(-1),
+ last_err(0) {}
};
ceph_tid_t open_ino_last_tid;
map<inodeno_t,open_ino_info_t> opening_inodes;
void _open_ino_backtrace_fetched(inodeno_t ino, bufferlist& bl, int err);
void _open_ino_parent_opened(inodeno_t ino, int ret);
void _open_ino_traverse_dir(inodeno_t ino, open_ino_info_t& info, int err);
- void _open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir);
- MDSInternalContextBase* _open_ino_get_waiter(inodeno_t ino, MMDSOpenIno *m);
+ void _open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir, bool parent);
int open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m,
vector<inode_backpointer_t>& ancestors,
bool discover, bool want_xlocked, mds_rank_t *hint);
void open_ino_finish(inodeno_t ino, open_ino_info_t& info, int err);
void do_open_ino(inodeno_t ino, open_ino_info_t& info, int err);
void do_open_ino_peer(inodeno_t ino, open_ino_info_t& info);
- void handle_open_ino(MMDSOpenIno *m);
+ void handle_open_ino(MMDSOpenIno *m, int err=0);
void handle_open_ino_reply(MMDSOpenInoReply *m);
friend class C_IO_MDC_OpenInoBacktraceFetched;
friend struct C_MDC_OpenInoTraverseDir;