]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: improve freeze deadlock detection 15510/head
authorYan, Zheng <zyan@redhat.com>
Thu, 22 Jun 2017 00:00:35 +0000 (08:00 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 26 Jun 2017 01:32:15 +0000 (09:32 +0800)
if request waits for unfreeze while holding remote auth pins,
deadlock may happen.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/Locker.cc
src/mds/Locker.h
src/mds/MDCache.cc
src/mds/Server.cc

index 6cb9a73511130e643d1c2ee69cb51db1007befab..cf795ed225d36ef91bbf2da8561b96fdfd402f02 100644 (file)
@@ -365,6 +365,10 @@ bool Locker::acquire_locks(MDRequestRef& mdr,
       }
       dout(10) << " can't auth_pin (freezing?), waiting to authpin " << *object << dendl;
       object->add_waiter(MDSCacheObject::WAIT_UNFREEZE, new C_MDS_RetryRequest(mdcache, mdr));
+
+      if (!mdr->remote_auth_pins.empty())
+       notify_freeze_waiter(object);
+
       return false;
     }
   }
@@ -615,6 +619,28 @@ bool Locker::acquire_locks(MDRequestRef& mdr,
   return result;
 }
 
+void Locker::notify_freeze_waiter(MDSCacheObject *o)
+{
+  CDir *dir = NULL;
+  if (CInode *in = dynamic_cast<CInode*>(o)) {
+    if (!in->is_root())
+      dir = in->get_parent_dir();
+  } else if (CDentry *dn = dynamic_cast<CDentry*>(o)) {
+    dir = dn->get_dir();
+  } else {
+    dir = dynamic_cast<CDir*>(o);
+    assert(dir);
+  }
+  if (dir) {
+    if (dir->is_freezing_dir())
+      mdcache->fragment_freeze_inc_num_waiters(dir);
+    if (dir->is_freezing_tree()) {
+      while (!dir->is_freezing_tree_root())
+       dir = dir->get_parent_dir();
+      mdcache->migrator->export_freeze_inc_num_waiters(dir);
+    }
+  }
+}
 
 void Locker::set_xlocks_done(MutationImpl *mut, bool skip_dentry)
 {
index 32b7d63016e4cdd8cabeb07eb6d3f9e9fa430b50..8cff4ec3e57b3d69ab19a74e392cfae02e8dffc5 100644 (file)
@@ -80,6 +80,7 @@ public:
                     CInode *auth_pin_freeze=NULL,
                     bool auth_pin_nonblock=false);
 
+  void notify_freeze_waiter(MDSCacheObject *o);
   void cancel_locking(MutationImpl *mut, set<CInode*> *pneed_issue);
   void drop_locks(MutationImpl *mut, set<CInode*> *pneed_issue=0);
   void set_xlocks_done(MutationImpl *mut, bool skip_dentry=false);
index 1c6936823bcb0a61592c6dbf9655785ce2d13d6e..1944e43bd00d13013d200c9ef36d656c5e5cbf87 100644 (file)
@@ -12084,9 +12084,12 @@ void MDCache::repair_dirfrag_stats_work(MDRequestRef& mdr)
   }
 
   if (!mdr->is_auth_pinned(dir) && !dir->can_auth_pin()) {
+    dir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryRequest(this, mdr));
+
     mds->locker->drop_locks(mdr.get());
     mdr->drop_local_auth_pins();
-    dir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryRequest(this, mdr));
+    if (!mdr->remote_auth_pins.empty())
+      mds->locker->notify_freeze_waiter(dir);
     return;
   }
 
index d65b3c9d9aa1f1834d28e1b84e29a9780f33cbc1..54b8ed2de471d85d71637f4904984265cffa460b 100644 (file)
@@ -2256,24 +2256,7 @@ void Server::handle_slave_auth_pin(MDRequestRef& mdr)
        (*p)->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryRequest(mdcache, mdr));
        mdr->drop_local_auth_pins();
 
-       CDir *dir = NULL;
-       if (CInode *in = dynamic_cast<CInode*>(*p)) {
-         if (!in->is_root())
-           dir = in->get_parent_dir();
-       } else if (CDentry *dn = dynamic_cast<CDentry*>(*p)) {
-         dir = dn->get_dir();
-       } else {
-         ceph_abort();
-       }
-       if (dir) {
-         if (dir->is_freezing_dir())
-           mdcache->fragment_freeze_inc_num_waiters(dir);
-         if (dir->is_freezing_tree()) {
-           while (!dir->is_freezing_tree_root())
-             dir = dir->get_parent_dir();
-           mdcache->migrator->export_freeze_inc_num_waiters(dir);
-         }
-       }
+       mds->locker->notify_freeze_waiter(*p);
        return;
       }
     }
@@ -2825,6 +2808,8 @@ CInode* Server::rdlock_path_pin_ref(MDRequestRef& mdr, int n,
        */
       mds->locker->drop_locks(mdr.get(), NULL);
       mdr->drop_local_auth_pins();
+      if (!mdr->remote_auth_pins.empty())
+       mds->locker->notify_freeze_waiter(ref);
       return 0;
     }
 
@@ -2970,7 +2955,7 @@ CDir* Server::try_open_auth_dirfrag(CInode *diri, frag_t fg, MDRequestRef& mdr)
   if (!dir && diri->is_frozen()) {
     dout(10) << "try_open_auth_dirfrag: dir inode is frozen, waiting " << *diri << dendl;
     assert(diri->get_parent_dir());
-    diri->get_parent_dir()->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryRequest(mdcache, mdr));
+    diri->add_waiter(CInode::WAIT_UNFREEZE, new C_MDS_RetryRequest(mdcache, mdr));
     return 0;
   }