]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: when prodding head inode on snapped behalf, avoid XSYN
authorSage Weil <sage@newdream.net>
Fri, 17 Jun 2011 02:27:50 +0000 (19:27 -0700)
committerSage Weil <sage@newdream.net>
Fri, 17 Jun 2011 02:44:06 +0000 (19:44 -0700)
If we try to rdlock a snapped inode in snap->sync state, we need to prod
the head inode into SYNC to get the data flushed.  Make sure we avoid
XSYN by passing as_anon=true to rdlock_start(head).

Also fix the waiting code.  If it succeeds, continue around the loop.  If
not, the rdlock_start will add the waiter for us--don't do it again!

Fixes workunit snaps/snaptest-snap-rm-cmp.sh.

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/Locker.cc
src/mds/Locker.h

index 0aa7e4e6fa25d230f567e23cbb8ceaf5323aa55e..a87edb10563ff2bc784418136d6024e5f25771b2 100644 (file)
@@ -840,7 +840,7 @@ void Locker::eval(SimpleLock *lock, bool *need_issue)
 // ------------------
 // rdlock
 
-bool Locker::_rdlock_kick(SimpleLock *lock)
+bool Locker::_rdlock_kick(SimpleLock *lock, bool as_anon)
 {
   // kick the lock
   if (lock->is_stable()) {
@@ -854,7 +854,8 @@ bool Locker::_rdlock_kick(SimpleLock *lock)
       } else if (lock->get_sm() == &sm_filelock) {
        CInode *in = (CInode*)lock->get_parent();
        if (lock->get_state() == LOCK_EXCL &&
-           in->get_target_loner() >= 0)
+           in->get_target_loner() >= 0 &&
+           !as_anon)   // as_anon => caller wants SYNC, not XSYN
          file_xsyn(lock);
        else
          simple_sync(lock);
@@ -881,7 +882,7 @@ bool Locker::rdlock_try(SimpleLock *lock, client_t client, Context *con)
   if (lock->can_rdlock(client)) 
     return true;
   
-  _rdlock_kick(lock);
+  _rdlock_kick(lock, false);
 
   if (lock->can_rdlock(client)) 
     return true;
@@ -904,6 +905,10 @@ bool Locker::rdlock_start(SimpleLock *lock, MDRequest *mut, bool as_anon)
     as_anon = true;
   client_t client = as_anon ? -1 : mut->get_client();
 
+  CInode *in = 0;
+  if (lock->get_type() != CEPH_LOCK_DN)
+    in = (CInode *)lock->get_parent();
+
   /*
   if (!lock->get_parent()->is_auth() &&
       lock->fw_rdlock_to_auth()) {
@@ -921,26 +926,22 @@ bool Locker::rdlock_start(SimpleLock *lock, MDRequest *mut, bool as_anon)
       return true;
     }
 
-    if (!_rdlock_kick(lock))
+    if (!_rdlock_kick(lock, as_anon))
       break;
-  }
 
-  // hmm, wait a second.
-  CInode *in = 0;
-  if (lock->get_type() != CEPH_LOCK_DN)
-    in = (CInode *)lock->get_parent();
-  
-  if (in && !in->is_head() && in->is_auth() &&
-      lock->get_state() == LOCK_SNAP_SYNC) {
-    // okay, we actually need to kick the head's lock to get ourselves synced up.
-    CInode *head = mdcache->get_inode(in->ino());
-    assert(head);
-    SimpleLock *hlock = head->get_lock(lock->get_type());
-    if (hlock->get_state() != LOCK_SYNC) {
-      dout(10) << "rdlock_start trying head inode " << *head << dendl;
-      rdlock_start(head->get_lock(lock->get_type()), mut, true); // ** as_anon, no rdlock on EXCL **
-      hlock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mut));
-      return false;
+    // hmm, wait a second.
+    if (in && !in->is_head() && in->is_auth() &&
+       lock->get_state() == LOCK_SNAP_SYNC) {
+      // okay, we actually need to kick the head's lock to get ourselves synced up.
+      CInode *head = mdcache->get_inode(in->ino());
+      assert(head);
+      SimpleLock *hlock = head->get_lock(lock->get_type());
+      if (hlock->get_state() != LOCK_SYNC) {
+       dout(10) << "rdlock_start trying head inode " << *head << dendl;
+       if (!rdlock_start(head->get_lock(lock->get_type()), mut, true)) // ** as_anon, no rdlock on EXCL **
+         return false;
+       // oh, check our lock again then
+      }
     }
   }
 
index 0af87a7f0206b26723023d9e3090576b86d05e11..68344984acff82758aafb905e5e06853abb17f2b 100644 (file)
@@ -120,7 +120,7 @@ public:
   bool eval(CInode *in, int mask);
   void try_eval(CInode *in, int mask);
 
-  bool _rdlock_kick(SimpleLock *lock);
+  bool _rdlock_kick(SimpleLock *lock, bool as_anon);
   bool rdlock_try(SimpleLock *lock, client_t client, Context *c);
   bool rdlock_start(SimpleLock *lock, MDRequest *mut, bool as_anon=false);
   void rdlock_finish(SimpleLock *lock, Mutation *mut, bool *pneed_issue);