]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix 'if there is lock cache on dir' check 34273/head
authorYan, Zheng <zyan@redhat.com>
Thu, 5 Mar 2020 14:54:50 +0000 (22:54 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 30 Mar 2020 01:23:07 +0000 (09:23 +0800)
When invalidating lock cache, current code detach lock cache from all
its locks immediately. So diri->filelock.is_cached() only tells us if
there is active (not being invalidated) lock cache on a dir.

But MDCache::path_traverse() and Server::_dir_is_nonempty_unlocked() use
diri->filelock.is_cached() to check if there is any lock cache on a dir.
This bug can result in processing async requests and normal requests out
of order.

The fix is detaching lock cache from its locks when lock cache is
completely invalidated .

Fixes: https://tracker.ceph.com/issues/44448
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit 20d21cff89e1bb2bd6d7af311b4cc3272ce5fe65)

src/mds/Locker.cc
src/mds/Mutation.cc
src/mds/Mutation.h
src/mds/SimpleLock.cc
src/mds/SimpleLock.h

index a42945bb27a215c34bdfec103fb9b18147837c54..b811db4870cf315f59bcc160d4bc5ede125453fd 100644 (file)
@@ -802,6 +802,8 @@ void Locker::put_lock_cache(MDLockCache* lock_cache)
 
   ceph_assert(lock_cache->invalidating);
 
+  lock_cache->detach_locks();
+
   CInode *diri = lock_cache->get_dir_inode();
   for (auto dir : lock_cache->auth_pinned_dirfrags) {
     if (dir->get_inode() != diri)
@@ -832,7 +834,7 @@ void Locker::invalidate_lock_cache(MDLockCache *lock_cache)
     ceph_assert(!lock_cache->client_cap);
   } else {
     lock_cache->invalidating = true;
-    lock_cache->detach_all();
+    lock_cache->detach_dirfrags();
   }
 
   Capability *cap = lock_cache->client_cap;
@@ -880,8 +882,10 @@ void Locker::invalidate_lock_caches(CDir *dir)
 void Locker::invalidate_lock_caches(SimpleLock *lock)
 {
   dout(10) << "invalidate_lock_caches " << *lock << " on " << *lock->get_parent() << dendl;
-  while (lock->is_cached()) {
-    invalidate_lock_cache(lock->get_first_cache());
+  if (lock->is_cached()) {
+    auto&& lock_caches = lock->get_active_caches();
+    for (auto& lc : lock_caches)
+      invalidate_lock_cache(lc);
   }
 }
 
index 03555b4f09805246f4b578b0b622a0d6afb27f22..d9f3f7cadcc60b049014a2096d964b0027d5f56f 100644 (file)
@@ -578,7 +578,7 @@ void MDLockCache::attach_dirfrags(std::vector<CDir*>&& dfv)
   }
 }
 
-void MDLockCache::detach_all()
+void MDLockCache::detach_locks()
 {
   ceph_assert(items_lock);
   int i = 0;
@@ -588,9 +588,12 @@ void MDLockCache::detach_all()
     ++i;
   }
   items_lock.reset();
+}
 
+void MDLockCache::detach_dirfrags()
+{
   ceph_assert(items_dir);
-  i = 0;
+  int i = 0;
   for (auto dir : auth_pinned_dirfrags) {
     (void)dir;
     items_dir[i].item_dir.remove_myself();
index d79b430de6622efd1724a83b46a508d717aeca2c..0b4070420d3793c7bade40c3caf1fe6b145db83b 100644 (file)
@@ -496,7 +496,8 @@ struct MDLockCache : public MutationImpl {
 
   void attach_locks();
   void attach_dirfrags(std::vector<CDir*>&& dfv);
-  void detach_all();
+  void detach_locks();
+  void detach_dirfrags();
 
   CInode *diri;
   Capability *client_cap;
index 1f3b732169b7b751faeb71854075a67f7ce60811..7c447419bb6ee0c5a45c0cf0f760a18672b0d791 100644 (file)
@@ -95,12 +95,14 @@ void SimpleLock::remove_cache(MDLockCacheItem& item) {
   }
 }
 
-MDLockCache* SimpleLock::get_first_cache() {
+std::vector<MDLockCache*> SimpleLock::get_active_caches() {
+  std::vector<MDLockCache*> result;
   if (have_more()) {
-    auto& lock_caches = more()->lock_caches;
-    if (!lock_caches.empty()) {
-      return lock_caches.front()->parent;
+    for (auto it = more()->lock_caches.begin_use_current(); !it.end(); ++it) {
+      auto lock_cache = (*it)->parent;
+      if (!lock_cache->invalidating)
+       result.push_back(lock_cache);
     }
   }
-  return nullptr;
+  return result;
 }
index 1ad4cd91300450a4326bb6cfc7d0ada0b34b7722..37bdc8d20d94af625a42b59af6dad7ff7cd30644 100644 (file)
@@ -228,7 +228,7 @@ public:
   }
   void add_cache(MDLockCacheItem& item);
   void remove_cache(MDLockCacheItem& item);
-  MDLockCache* get_first_cache();
+  std::vector<MDLockCache*> get_active_caches();
 
   // state
   int get_state() const { return state; }