put(PIN_DNWAITER);
}
-void CDir::add_ino_waiter(inodeno_t ino, Context *c)
-{
- if (waiting_on_ino.empty())
- get(PIN_INOWAITER);
- waiting_on_ino[ino].push_back(c);
- dout(10) << "add_ino_waiter ino " << ino << " " << c << " on " << *this << dendl;
-}
-
-void CDir::take_ino_waiting(inodeno_t ino, list<Context*>& ls)
-{
- if (waiting_on_ino.empty()) return;
- if (waiting_on_ino.count(ino) == 0) return;
- dout(10) << "take_ino_waiting ino " << ino
- << " x " << waiting_on_ino[ino].size()
- << " on " << *this << dendl;
- ls.splice(ls.end(), waiting_on_ino[ino]);
- waiting_on_ino.erase(ino);
- if (waiting_on_ino.empty())
- put(PIN_INOWAITER);
-}
-
void CDir::take_sub_waiting(list<Context*>& ls)
{
dout(10) << "take_sub_waiting" << dendl;
waiting_on_dentry.clear();
put(PIN_DNWAITER);
}
- if (!waiting_on_ino.empty()) {
- for (map<inodeno_t, list<Context*> >::iterator p = waiting_on_ino.begin();
- p != waiting_on_ino.end();
- ++p)
- ls.splice(ls.end(), p->second);
- waiting_on_ino.clear();
- put(PIN_INOWAITER);
- }
}
// -- waiters --
protected:
map< string_snap_t, list<Context*> > waiting_on_dentry;
- map< inodeno_t, list<Context*> > waiting_on_ino;
public:
bool is_waiting_for_dentry(const string& dname, snapid_t snap) {
}
void add_dentry_waiter(const string& dentry, snapid_t snap, Context *c);
void take_dentry_waiting(const string& dentry, snapid_t first, snapid_t last, list<Context*>& ls);
-
- bool is_waiting_for_ino(inodeno_t ino) {
- return waiting_on_ino.count(ino);
- }
- void add_ino_waiter(inodeno_t ino, Context *c);
- void take_ino_waiting(inodeno_t ino, list<Context*>& ls);
-
void take_sub_waiting(list<Context*>& ls); // dentry or ino
void add_waiter(uint64_t mask, Context *c);
void MDCache::_send_discover(discover_info_t& d)
{
- MDiscover *dis = new MDiscover(d.ino, d.frag, d.snap,
- d.want_path, d.want_ino, d.want_base_dir, d.want_xlocked);
+ MDiscover *dis = new MDiscover(d.ino, d.frag, d.snap, d.want_path,
+ d.want_base_dir, d.want_xlocked);
dis->set_tid(d.tid);
mds->send_message_mds(dis, d.mds);
}
base->add_dentry_waiter(want_path[0], snap, onfinish);
}
-struct C_MDC_RetryDiscoverIno : public Context {
- MDCache *mdc;
- CDir *base;
- inodeno_t want_ino;
- C_MDC_RetryDiscoverIno(MDCache *c, CDir *b, inodeno_t i) :
- mdc(c), base(b), want_ino(i) {}
- void finish(int r) {
- mdc->discover_ino(base, want_ino, 0);
- }
-};
-
-void MDCache::discover_ino(CDir *base,
- inodeno_t want_ino,
- Context *onfinish,
- bool want_xlocked)
-{
- int from = base->authority().first;
-
- dout(7) << "discover_ino " << base->dirfrag() << " " << want_ino << " from mds." << from
- << (want_xlocked ? " want_xlocked":"")
- << dendl;
-
- if (base->is_ambiguous_auth()) {
- dout(10) << " waiting for single auth on " << *base << dendl;
- if (!onfinish)
- onfinish = new C_MDC_RetryDiscoverIno(this, base, want_ino);
- base->add_waiter(CDir::WAIT_SINGLEAUTH, onfinish);
- return;
- } else if (from == mds->get_nodeid()) {
- list<Context*> finished;
- base->take_sub_waiting(finished);
- mds->queue_waiters(finished);
- return;
- }
-
- if (want_xlocked || !base->is_waiting_for_ino(want_ino) || !onfinish) {
- discover_info_t& d = _create_discover(from);
- d.ino = base->ino();
- d.frag = base->get_frag();
- d.want_ino = want_ino;
- d.want_base_dir = false;
- d.want_xlocked = want_xlocked;
- _send_discover(d);
- }
-
- // register + wait
- if (onfinish)
- base->add_ino_waiter(want_ino, onfinish);
-}
-
-
-
void MDCache::kick_discovers(int who)
{
for (map<ceph_tid_t,discover_info_t>::iterator p = discovers.begin();
fg = cur->pick_dirfrag(dis->get_dentry(i));
} else {
// requester explicity specified the frag
- assert(dis->wants_base_dir() || dis->get_want_ino() || MDS_INO_IS_BASE(dis->get_base_ino()));
+ assert(dis->wants_base_dir() || MDS_INO_IS_BASE(dis->get_base_ino()));
fg = dis->get_base_dir_frag();
if (!cur->dirfragtree.is_leaf(fg))
fg = cur->dirfragtree[fg.value()];
CDentry *dn = 0;
if (curdir->get_version() == 0) {
// fetch newly opened dir
- } else if (dis->get_want_ino()) {
- // lookup by ino
- CInode *in = get_inode(dis->get_want_ino(), snapid);
- if (in && in->is_auth() && in->get_parent_dn()->get_dir() == curdir) {
- dn = in->get_parent_dn();
- if (dn->state_test(CDentry::STATE_PURGING)) {
- // set error flag in reply
- dout(7) << "dentry " << *dn << " is purging, flagging error ino" << dendl;
- reply->set_flag_error_ino();
- break;
- }
- }
} else if (dis->get_want().depth() > 0) {
// lookup dentry
dn = curdir->lookup(dis->get_dentry(i), snapid);
break;
}
}
-
- // don't have wanted ino in this dir?
- if (dis->get_want_ino()) {
- // set error flag in reply
- dout(7) << "no ino " << dis->get_want_ino() << " in this dir, flagging error in "
- << *curdir << dendl;
- reply->set_flag_error_ino();
- break;
- }
// send null dentry
dout(7) << "dentry " << dis->get_dentry(i) << " dne, returning null in "
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_wanted_ino() << dendl;
list<Context*> finished, error;
int from = m->get_source().num();
}
}
- // discover ino error
- if (p.end() && m->is_flag_error_ino()) {
- assert(cur);
- assert(cur->is_dir());
- CDir *dir = cur->get_dirfrag(m->get_base_dir_frag());
- if (dir) {
- dout(7) << " flag_error on ino " << m->get_wanted_ino()
- << ", triggering ino" << dendl;
- dir->take_ino_waiting(m->get_wanted_ino(), error);
- } else
- assert(0);
- }
-
// discover may start with an inode
if (!p.end() && next == MDiscoverReply::INODE) {
cur = add_replica_inode(p, NULL, finished);
} else
dout(7) << " doing nothing, have dir but nobody is waiting on dentry "
<< m->get_error_dentry() << dendl;
- } else {
- if (dir && m->get_wanted_ino() && dir->is_waiting_for_ino(m->get_wanted_ino())) {
- if (dir->is_auth() || get_inode(m->get_wanted_ino()))
- dir->take_ino_waiting(m->get_wanted_ino(), finished);
- else
- discover_ino(dir, m->get_wanted_ino(), 0, m->get_wanted_xlocked());
- } else
- dout(7) << " doing nothing, nobody is waiting for ino" << dendl;
}
}
if (dn) {
if (!dn->get_linkage()->is_primary() || dn->get_linkage()->get_inode() != in)
dout(10) << "add_replica_inode different linkage in dentry " << *dn << dendl;
-
- dn->get_dir()->take_ino_waiting(in->ino(), finished);
}
return in;
frag_t frag;
snapid_t snap;
filepath want_path;
- inodeno_t want_ino;
bool want_base_dir;
bool want_xlocked;
bool want_xlocked=false, int from=-1);
void discover_path(CDir *base, snapid_t snap, filepath want_path, Context *onfinish,
bool want_xlocked=false);
- void discover_ino(CDir *base, inodeno_t want_ino, Context *onfinish,
- bool want_xlocked=false);
-
void kick_discovers(int who); // after a failure.
snapid_t snapid;
filepath want; // ... [/]need/this/stuff
- inodeno_t want_ino;
bool want_base_dir;
bool want_xlocked;
snapid_t get_snapid() { return snapid; }
filepath& get_want() { return want; }
- inodeno_t get_want_ino() { return want_ino; }
const string& get_dentry(int n) { return want[n]; }
bool wants_base_dir() { return want_base_dir; }
frag_t base_frag_,
snapid_t s,
filepath& want_path_,
- inodeno_t want_ino_,
bool want_base_dir_ = true,
bool discover_xlocks_ = false) :
Message(MSG_MDS_DISCOVER),
base_dir_frag(base_frag_),
snapid(s),
want(want_path_),
- want_ino(want_ino_),
want_base_dir(want_base_dir_),
want_xlocked(discover_xlocks_) { }
private:
const char *get_type_name() const { return "Dis"; }
void print(ostream &out) const {
out << "discover(" << header.tid << " " << base_ino << "." << base_dir_frag
- << " " << want;
- if (want_ino)
- out << want_ino;
- out << ")";
+ << " " << want << ")";
}
void decode_payload() {
::decode(base_dir_frag, p);
::decode(snapid, p);
::decode(want, p);
- ::decode(want_ino, p);
::decode(want_base_dir, p);
::decode(want_xlocked, p);
}
::encode(base_dir_frag, payload);
::encode(snapid, payload);
::encode(want, payload);
- ::encode(want_ino, payload);
::encode(want_base_dir, payload);
::encode(want_xlocked, payload);
}
frag_t base_dir_frag;
bool wanted_base_dir;
bool wanted_xlocked;
- inodeno_t wanted_ino;
snapid_t wanted_snapid;
// and the response
bool flag_error_dn;
- bool flag_error_ino;
bool flag_error_dir;
string error_dentry; // dentry that was not found (to trigger waiters on asker)
bool unsolicited;
frag_t get_base_dir_frag() { return base_dir_frag; }
bool get_wanted_base_dir() { return wanted_base_dir; }
bool get_wanted_xlocked() { return wanted_xlocked; }
- inodeno_t get_wanted_ino() { return wanted_ino; }
snapid_t get_wanted_snapid() { return wanted_snapid; }
bool is_flag_error_dn() { return flag_error_dn; }
- 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; }
base_dir_frag(dis->get_base_dir_frag()),
wanted_base_dir(dis->wants_base_dir()),
wanted_xlocked(dis->wants_xlocked()),
- wanted_ino(dis->get_want_ino()),
wanted_snapid(dis->get_snapid()),
flag_error_dn(false),
- flag_error_ino(false),
flag_error_dir(false),
unsolicited(false),
dir_auth_hint(CDIR_AUTH_UNKNOWN),
base_dir_frag(df.frag),
wanted_base_dir(false),
wanted_xlocked(false),
- wanted_ino(inodeno_t()),
wanted_snapid(CEPH_NOSNAP),
flag_error_dn(false),
- flag_error_ino(false),
flag_error_dir(false),
unsolicited(false),
dir_auth_hint(CDIR_AUTH_UNKNOWN),
bool is_empty() {
return trace.length() == 0 &&
!flag_error_dn &&
- !flag_error_ino &&
!flag_error_dir &&
dir_auth_hint == CDIR_AUTH_UNKNOWN;
}
flag_error_dn = true;
error_dentry = dn;
}
- void set_flag_error_ino() {
- flag_error_ino = true;
- }
void set_flag_error_dir() {
flag_error_dir = true;
}
::decode(wanted_xlocked, p);
::decode(wanted_snapid, p);
::decode(flag_error_dn, p);
- ::decode(flag_error_ino, p);
::decode(flag_error_dir, p);
::decode(error_dentry, p);
::decode(dir_auth_hint, p);
::decode(starts_with, p);
::decode(trace, p);
- if (header.version >= 2)
- ::decode(wanted_ino, p);
}
void encode_payload(uint64_t features) {
::encode(base_ino, payload);
::encode(wanted_xlocked, payload);
::encode(wanted_snapid, payload);
::encode(flag_error_dn, payload);
- ::encode(flag_error_ino, payload);
::encode(flag_error_dir, payload);
::encode(error_dentry, payload);
::encode(dir_auth_hint, payload);
::encode(starts_with, payload);
::encode(trace, payload);
- ::encode(wanted_ino, payload);
}
-
};
#endif