summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2012-11-09 05:28:12 -0800
committerSage Weil <sage@inktank.com>2012-11-09 06:53:28 -0800
commit8c115d3e81543a4c723bae217ba5b9d2c0e988f7 (patch)
treea448100b30f3143c69639c63f9ce5f2c0078b762
parent1a23bd6981e2a308be4a905021453a6d5feac9e3 (diff)
downloadceph-8c115d3e81543a4c723bae217ba5b9d2c0e988f7.tar.gz
mds: re-try_set_loner() after doing evals in eval(CInode*, int mask)
Consider a case where current loner is A and wanted loner is B. At the top of the function we try to set the loner, but that may fail because we haven't processed the gathered caps yet for the previous loner. In the body we do that and potentially drop the old loner, but we do not try_set_loner() again on the desired loner. Try after our drop. If it succeeds, loop through the eval's one more time so that we can issue caps approriately. This fixes a hang induced by a simple loop like: while true ; do echo asdf >> mnt.a/foo ; tail mnt.b/foo ; done & while true ; do ls mnt.a mnt.b ; done (The second loop may not be necessary.) Signed-off-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/mds/Locker.cc13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc
index 8b771852d49..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;
+ }
+ }
}
}