From 1c5f655044c2bdee72a92486e3fe2cb1639cfd9e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 16 Jun 2011 19:27:50 -0700 Subject: [PATCH] mds: when prodding head inode on snapped behalf, avoid XSYN 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 --- src/mds/Locker.cc | 43 ++++++++++++++++++++++--------------------- src/mds/Locker.h | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 0aa7e4e6fa25d..a87edb10563ff 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -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 + } } } diff --git a/src/mds/Locker.h b/src/mds/Locker.h index 0af87a7f0206b..68344984acff8 100644 --- a/src/mds/Locker.h +++ b/src/mds/Locker.h @@ -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); -- 2.39.5