diff options
author | Sage Weil <sage@inktank.com> | 2012-11-12 11:24:00 -0800 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2012-11-12 11:24:00 -0800 |
commit | 39b9da403541617fb088aa4ae03925850aa2de65 (patch) | |
tree | 9f48303a30468628cd0cabf066cfbebfcd8054a9 /src | |
parent | 83ab36655f397b7d781a611b4d82679c8484710f (diff) | |
parent | 8c115d3e81543a4c723bae217ba5b9d2c0e988f7 (diff) | |
download | ceph-39b9da403541617fb088aa4ae03925850aa2de65.tar.gz |
Merge remote-tracking branch 'gh/wip-mds-stable' into stable
Diffstat (limited to 'src')
-rw-r--r-- | src/include/CompatSet.h | 34 | ||||
-rw-r--r-- | src/mds/Locker.cc | 17 |
2 files changed, 44 insertions, 7 deletions
diff --git a/src/include/CompatSet.h b/src/include/CompatSet.h index 1c18d6193a9..b5bf450b97e 100644 --- a/src/include/CompatSet.h +++ b/src/include/CompatSet.h @@ -33,9 +33,11 @@ struct CompatSet { uint64_t mask; map <uint64_t,string> names; - FeatureSet() : mask(0), names() {} + FeatureSet() : mask(1), names() {} void insert(Feature f) { - mask |= f.id; + assert(f.id > 0); + assert(f.id < 63); + mask |= (1<<f.id); names[f.id] = f.name; } @@ -45,18 +47,42 @@ struct CompatSet { void remove(uint64_t f) { if (names.count(f)) { names.erase(f); - mask &= ~f; + mask &= ~(1<<f); } } void encode(bufferlist& bl) const { - ::encode(mask, bl); + /* See below, mask always has the lowest bit set in memory, but + * unset in the encoding */ + ::encode(mask & (~(uint64_t)1), bl); ::encode(names, bl); } void decode(bufferlist::iterator& bl) { ::decode(mask, bl); ::decode(names, bl); + /** + * Previously, there was a bug where insert did + * mask |= f.id rather than mask |= (1 << f.id). + * In FeatureSets from those version, mask always + * has the lowest bit set. Since then, masks always + * have the lowest bit unset. + * + * When we encounter such a FeatureSet, we have to + * reconstruct the mask from the names map. + */ + if (mask & 1) { + mask = 1; + map<uint64_t, string> temp_names; + temp_names.swap(names); + for (map<uint64_t, string>::iterator i = temp_names.begin(); + i != temp_names.end(); + ++i) { + insert(Feature(i->first, i->second)); + } + } else { + mask |= 1; + } } void dump(Formatter *f) const { diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 72802ea7e7c..a27f4fc121f 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -778,7 +778,8 @@ bool Locker::eval(CInode *in, int mask) } else dout(10) << "eval doesn't want loner" << dendl; } - + + retry: if (mask & CEPH_LOCK_IFILE) eval_any(&in->filelock, &need_issue); if (mask & CEPH_LOCK_IAUTH) @@ -800,6 +801,16 @@ bool Locker::eval(CInode *in, int mask) if (in->try_drop_loner()) { dout(10) << " dropped loner" << dendl; need_issue = true; + + if (in->get_wanted_loner() >= 0) { + if (in->try_set_loner()) { + dout(10) << "eval end set loner to client." << in->get_loner() << dendl; + mask = -1; + goto retry; + } else { + dout(10) << "eval want loner client." << in->get_wanted_loner() << " but failed to set it" << dendl; + } + } } } @@ -4001,11 +4012,11 @@ void Locker::file_eval(ScatterLock *lock, bool *need_issue) in->get_caps_issued(&loner_issued, &other_issued, &xlocker_issued, CEPH_CAP_SFILE); if (!((loner_wanted|loner_issued) & (CEPH_CAP_GEXCL|CEPH_CAP_GWR|CEPH_CAP_GBUFFER)) || - (other_wanted & (CEPH_CAP_GEXCL|CEPH_CAP_GWR|CEPH_CAP_GBUFFER|CEPH_CAP_GRD|CEPH_CAP_GCACHE)) || + (other_wanted & (CEPH_CAP_GEXCL|CEPH_CAP_GWR|CEPH_CAP_GRD)) || (in->inode.is_dir() && in->multiple_nonstale_caps())) { // FIXME.. :/ dout(20) << " should lose it" << dendl; // we should lose it. - if ((other_wanted & (CEPH_CAP_GRD|CEPH_CAP_GWR)) || + if (((other_wanted|loner_wanted) & (CEPH_CAP_GRD|CEPH_CAP_GWR)) || lock->is_waiter_for(SimpleLock::WAIT_WR)) scatter_mix(lock, need_issue); else if (!lock->is_wrlocked()) // let excl wrlocks drain first |