]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: re-try_set_loner() after doing evals in eval(CInode*, int mask)
authorSage Weil <sage@inktank.com>
Fri, 9 Nov 2012 13:28:12 +0000 (05:28 -0800)
committerSage Weil <sage@inktank.com>
Fri, 9 Nov 2012 14:53:28 +0000 (06:53 -0800)
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>
src/mds/Locker.cc

index 8b771852d49f9f6dfea6609d3c915e67a594a5d2..a27f4fc121fd3b228eeb3a51ebf1d30478f0b180 100644 (file)
@@ -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;
+       }
+      }
     }
   }