]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: make nested scatterlock state change check more robust
authorSage Weil <sage@newdream.net>
Sat, 18 Dec 2010 05:02:58 +0000 (21:02 -0800)
committerSage Weil <sage@newdream.net>
Sat, 18 Dec 2010 05:02:58 +0000 (21:02 -0800)
The predirty_journal_parents() calls wrlock_start() with nowait=true
because it has a journal entry open and we don't want to trigger a nested
scatterlock change that needs to journal something again (either
via scatter_writebehind or scatter_start).  (MDLog can only handle a single
log entry open at once because building multiple at once would require very
very very careful ordering of predirty() calls and versions.)

We were already check for the simple_lock() case (which may call
writebehind); fix up the check to also cover the scatter_mix() (which may
call scatter_start) case.

Fixes this crash:

mds/MDLog.h: In function 'void MDLog::start_entry(LogEvent*)':
mds/MDLog.h:191: FAILED assert(cur_event == __null)
 ceph version 0.24~rc (commit:fe10300317383ec29948d7dbe3cb31b3aa277e3c)
 1: (CInode::finish_scatter_update(ScatterLock*, CDir*, unsigned long, unsigned long)+0x804) [0x606e14]
 2: (CInode::start_scatter(ScatterLock*)+0xaa) [0x60dc1a]
 3: (Locker::scatter_mix(ScatterLock*, bool*)+0x1ca) [0x589a9a]
 4: (Locker::wrlock_start(SimpleLock*, MDRequest*, bool)+0x165) [0x597d65]
 5: (MDCache::predirty_journal_parents(Mutation*, EMetaBlob*, CInode*, CDir*, int, int, snapid_t)+0x153e) [0x55a70e]
 6: (Locker::scatter_writebehind(ScatterLock*)+0x42d) [0x58553d]
 7: (Locker::simple_lock(SimpleLock*, bool*)+0x7ab) [0x58beeb]
 8: (Locker::scatter_nudge(ScatterLock*, Context*, bool)+0x3ad) [0x58c49d]
 9: (Locker::scatter_tick()+0x28a) [0x58c98a]
 10: (MDS::tick()+0x4e4) [0x4b26a4]
 11: (SafeTimer::timer_thread()+0x22c) [0x6d164c]
 12: (SafeTimerThread::entry()+0xd) [0x6d34bd]
 13: (Thread::_entry_func(void*)+0xa) [0x4943da]
 14: /lib/libpthread.so.0 [0x7fc87810b73a]
 15: (clone()+0x6d) [0x7fc876dad69d]

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

index e1e22c36db79011774c7432ef1a2ac8e4102a25f..9bc6e6357a7c25e1b9ff049cb1df296db80016ba 100644 (file)
@@ -953,13 +953,16 @@ bool Locker::wrlock_start(SimpleLock *lock, MDRequest *mut, bool nowait)
       break;
 
     if (in->is_auth()) {
-      if (want_scatter) {
+      // don't do nested lock state change if we have dirty scatterdata and
+      // may scatter_writebehind or start_scatter, because nowait==true implies
+      // that the caller already has a log entry open!
+      if (nowait && lock->is_dirty())
+       return false;
+
+      if (want_scatter)
        scatter_mix((ScatterLock*)lock);
-      } else {
-       if (nowait && lock->is_dirty())
-         return false;   // don't do nested lock, as that may scatter_writebehind in simple_lock!
+      else
        simple_lock(lock);
-      }
 
       if (nowait && !lock->can_wrlock(client))
        return false;