From: Sage Weil Date: Sat, 18 Dec 2010 05:02:58 +0000 (-0800) Subject: mds: make nested scatterlock state change check more robust X-Git-Tag: v0.24~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=b04b6f48237fcbd22716279726f827237a3eb4af;p=ceph.git mds: make nested scatterlock state change check more robust 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 --- diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index e1e22c36db790..9bc6e6357a7c2 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -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;