inodeno_t dirino;
__u32 dn_hash;
int nref; // reference count
+ version_t updated;
- Anchor() : dn_hash(0), nref(0) {}
- Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr=0) :
- ino(i), dirino(di), dn_hash(hash), nref(nr) { }
- Anchor(inodeno_t i, inodeno_t di, const nstring &dname, int nr=0) :
+ Anchor() : dn_hash(0), nref(0), updated(0) {}
+ Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr, version_t u) :
+ ino(i), dirino(di), dn_hash(hash), nref(nr), updated(u) { }
+ Anchor(inodeno_t i, inodeno_t di, const nstring &dname, int nr, version_t u) :
ino(i), dirino(di),
dn_hash(ceph_full_name_hash(dname.data(), dname.length())),
- nref(nr) { }
+ nref(nr), updated(u) { }
void encode(bufferlist &bl) const {
::encode(ino, bl);
::encode(dirino, bl);
::encode(dn_hash, bl);
::encode(nref, bl);
+ ::encode(updated, bl);
}
void decode(bufferlist::iterator &bl) {
::decode(ino, bl);
::decode(dirino, bl);
::decode(dn_hash, bl);
::decode(nref, bl);
+ ::decode(updated, bl);
}
};
WRITE_CLASS_ENCODER(Anchor)
inline ostream& operator<<(ostream& out, const Anchor &a)
{
- return out << "a(" << a.ino << " " << a.dirino << "/" << a.dn_hash << " " << a.nref << ")";
+ return out << "a(" << a.ino << " " << a.dirino << "/" << a.dn_hash << " " << a.nref << " v" << a.updated << ")";
}
#endif
if (anchor_map.count(ino) == 0) {
// new item
- anchor_map[ino] = Anchor(ino, dirino, dn_hash);
+ anchor_map[ino] = Anchor(ino, dirino, dn_hash, 0, version);
dout(7) << "add added " << anchor_map[ino] << dendl;
return true;
} else {
while (1) {
Anchor &anchor = anchor_map[ino];
anchor.nref++;
+ anchor.updated = version;
dout(10) << "inc now " << anchor << dendl;
ino = anchor.dirino;
while (true) {
Anchor &anchor = anchor_map[ino];
anchor.nref--;
-
+ anchor.updated = version;
+
if (anchor.nref == 0) {
dout(10) << "dec removing " << anchor << dendl;
inodeno_t dirino = anchor.dirino;
class C_MDC_OpenRemoteIno : public Context {
MDCache *mdcache;
inodeno_t ino;
+ inodeno_t hadino;
+ version_t hadv;
Context *onfinish;
public:
vector<Anchor> anchortrace;
- C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, Context *c) :
- mdcache(mdc), ino(i), onfinish(c) {}
- C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, vector<Anchor>& at,
- Context *c) :
- mdcache(mdc), ino(i), onfinish(c), anchortrace(at) {}
+ C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, inodeno_t hi, version_t hv, Context *c) :
+ mdcache(mdc), ino(i), hadino(hi), hadv(hv), onfinish(c) {}
+ C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, vector<Anchor>& at, Context *c) :
+ mdcache(mdc), ino(i), hadino(0), hadv(0), onfinish(c), anchortrace(at) {}
void finish(int r) {
assert(r == 0);
if (r == 0)
- mdcache->open_remote_ino_2(ino, anchortrace, onfinish);
+ mdcache->open_remote_ino_2(ino, anchortrace, hadino, hadv, onfinish);
else {
onfinish->finish(r);
delete onfinish;
}
};
-void MDCache::open_remote_ino(inodeno_t ino, Context *onfinish)
+void MDCache::open_remote_ino(inodeno_t ino, Context *onfinish, inodeno_t hadino, version_t hadv)
{
dout(7) << "open_remote_ino on " << ino << dendl;
- C_MDC_OpenRemoteIno *c = new C_MDC_OpenRemoteIno(this, ino, onfinish);
+ C_MDC_OpenRemoteIno *c = new C_MDC_OpenRemoteIno(this, ino, hadino, hadv, onfinish);
mds->anchorclient->lookup(ino, c->anchortrace, c);
}
void MDCache::open_remote_ino_2(inodeno_t ino,
vector<Anchor>& anchortrace,
+ inodeno_t hadino, version_t hadv,
Context *onfinish)
{
dout(7) << "open_remote_ino_2 on " << ino
if (dir->is_auth()) {
if (dir->is_complete()) {
- // hrm. requery anchor table.
- dout(10) << "expected ino " << anchortrace[i].ino
- << " in complete dir " << *dir
- << ", requerying anchortable"
- << dendl;
- open_remote_ino(ino, onfinish);
+ // make sure we didn't get to the same version anchor 2x in a row
+ if (hadv && hadino == anchortrace[i].ino && hadv == anchortrace[i].updated) {
+ dout(10) << "expected ino " << anchortrace[i].ino
+ << " in complete dir " << *dir
+ << ", got same anchor " << anchortrace[i] << " 2x in a row" << dendl;
+ onfinish->finish(-ENOENT);
+ delete onfinish;
+ } else {
+ // hrm. requery anchor table.
+ dout(10) << "expected ino " << anchortrace[i].ino
+ << " in complete dir " << *dir
+ << ", requerying anchortable"
+ << dendl;
+ open_remote_ino(ino, onfinish, anchortrace[i].ino, anchortrace[i].updated);
+ }
} else {
dout(10) << "need ino " << anchortrace[i].ino
<< ", fetching incomplete dir " << *dir
void open_remote_dirfrag(CInode *diri, frag_t fg, Context *fin);
CInode *get_dentry_inode(CDentry *dn, MDRequest *mdr);
- void open_remote_ino(inodeno_t ino, Context *fin);
+ void open_remote_ino(inodeno_t ino, Context *fin, inodeno_t hadino=0, version_t hadv=0);
void open_remote_ino_2(inodeno_t ino,
vector<Anchor>& anchortrace,
+ inodeno_t hadino, version_t hadv,
Context *onfinish);
C_Gather *parallel_fetch(map<inodeno_t,string>& pathmap);