summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2012-11-12 11:24:00 -0800
committerSage Weil <sage@inktank.com>2012-11-12 11:24:00 -0800
commit39b9da403541617fb088aa4ae03925850aa2de65 (patch)
tree9f48303a30468628cd0cabf066cfbebfcd8054a9 /src
parent83ab36655f397b7d781a611b4d82679c8484710f (diff)
parent8c115d3e81543a4c723bae217ba5b9d2c0e988f7 (diff)
downloadceph-39b9da403541617fb088aa4ae03925850aa2de65.tar.gz
Merge remote-tracking branch 'gh/wip-mds-stable' into stable
Diffstat (limited to 'src')
-rw-r--r--src/include/CompatSet.h34
-rw-r--r--src/mds/Locker.cc17
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