]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Client: defer puting the inode 36580/head
authorXiubo Li <xiubli@redhat.com>
Wed, 19 Aug 2020 04:53:51 +0000 (00:53 -0400)
committerXiubo Li <xiubli@redhat.com>
Mon, 31 Aug 2020 01:12:25 +0000 (21:12 -0400)
To make sure the code is under client_lock when puting the inodes.

Fixes: https://tracker.ceph.com/issues/46882
Signed-off-by: Xiubo Li <xiubli@redhat.com>
src/client/Client.cc
src/client/Client.h

index 2a96ea71eef831fa1007bdd1a78c1e88b56a2d5b..6d9a047695f741569f6ceead6e75b0596d4eea39 100755 (executable)
@@ -3081,9 +3081,10 @@ void Client::handle_lease(const MConstRef<MClientLease>& m)
   }
 }
 
-void Client::put_inode(Inode *in, int n)
+void Client::_put_inode(Inode *in, int n)
 {
   ldout(cct, 10) << __func__ << " on " << *in << dendl;
+
   int left = in->_put(n);
   if (left == 0) {
     // release any caps
@@ -3107,6 +3108,31 @@ void Client::put_inode(Inode *in, int n)
   }
 }
 
+void Client::delay_put_inodes(bool wakeup)
+{
+  ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
+
+  std::map<Inode*,int> release;
+  {
+    std::scoped_lock dl(delay_i_lock);
+    release.swap(delay_i_release);
+  }
+
+  for (auto &[in, cnt] : release)
+    _put_inode(in, cnt);
+
+  if (wakeup)
+    mount_cond.notify_all();
+}
+
+void Client::put_inode(Inode *in, int n)
+{
+  ldout(cct, 20) << __func__ << " on " << *in << " n = " << n << dendl;
+
+  std::scoped_lock dl(delay_i_lock);
+  delay_i_release[in] += n;
+}
+
 void Client::close_dir(Dir *dir)
 {
   Inode *in = dir->parent_inode;
@@ -6301,12 +6327,15 @@ void Client::_unmount(bool abort)
   // empty lru cache
   trim_cache();
 
+  delay_put_inodes();
+
   while (lru.lru_get_size() > 0 ||
          !inode_map.empty()) {
     ldout(cct, 2) << "cache still has " << lru.lru_get_size()
             << "+" << inode_map.size() << " items"
            << ", waiting (for caps to release?)"
             << dendl;
+
     if (auto r = mount_cond.wait_for(lock, ceph::make_timespan(5));
        r == std::cv_status::timeout) {
       dump_cache(NULL);
@@ -6426,6 +6455,7 @@ void Client::tick()
   if (!mount_aborted)
     collect_and_send_metrics();
 
+  delay_put_inodes(is_unmounting());
   trim_cache(true);
 
   if (blocklisted && (is_mounted() || is_unmounting()) &&
index c1b4f57c1a4590d529c1c2ff876f7aa538c26dcb..1e52c2aa0ee53837ca1750b29bb9e0643e95e4b0 100644 (file)
@@ -867,6 +867,8 @@ protected:
   // -- metadata cache stuff
 
   // decrease inode ref.  delete if dangling.
+  void _put_inode(Inode *in, int n);
+  void delay_put_inodes(bool wakeup=false);
   void put_inode(Inode *in, int n=1);
   void close_dir(Dir *dir);
 
@@ -1413,6 +1415,9 @@ private:
 
   uint64_t cap_hits = 0;
   uint64_t cap_misses = 0;
+
+  ceph::spinlock delay_i_lock;
+  std::map<Inode*,int> delay_i_release;
 };
 
 /**