]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: cleanup unneeded client_snap_caps when splitting snap inode 29344/head
authorYan, Zheng <zyan@redhat.com>
Tue, 21 May 2019 09:50:25 +0000 (17:50 +0800)
committerPrashant D <pdhange@redhat.com>
Fri, 26 Jul 2019 02:00:42 +0000 (22:00 -0400)
Fixes: http://tracker.ceph.com/issues/39987
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit df79944a773ee0d77babe343b0b7107d58e5a1cd)

src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc

index 97db2deb66dc6d2166c456f05d10cb8ae0c0c19e..f1c2682a0d220c6722dcb96d7fb077a29835d7b0 100644 (file)
@@ -335,23 +335,28 @@ void CInode::remove_need_snapflush(CInode *snapin, snapid_t snapid, client_t cli
   }
 }
 
-bool CInode::split_need_snapflush(CInode *cowin, CInode *in)
+pair<bool,bool> CInode::split_need_snapflush(CInode *cowin, CInode *in)
 {
   dout(10) << __func__ << " [" << cowin->first << "," << cowin->last << "] for " << *cowin << dendl;
-  bool need_flush = false;
-  for (auto it = client_need_snapflush.lower_bound(cowin->first);
-       it != client_need_snapflush.end() && it->first < in->first; ) {
+  bool cowin_need_flush = false;
+  bool orig_need_flush = false;
+  auto it = client_need_snapflush.lower_bound(cowin->first);
+  while (it != client_need_snapflush.end() && it->first < in->first) {
     ceph_assert(!it->second.empty());
     if (cowin->last >= it->first) {
       cowin->auth_pin(this);
-      need_flush = true;
+      cowin_need_flush = true;
       ++it;
     } else {
       it = client_need_snapflush.erase(it);
     }
     in->auth_unpin(this);
   }
-  return need_flush;
+
+  if (it != client_need_snapflush.end() && it->first <= in->last)
+    orig_need_flush = true;
+
+  return make_pair(cowin_need_flush, orig_need_flush);
 }
 
 void CInode::mark_dirty_rstat()
index d609ab3037c250d54d508084cfa32ba7f1525e1c..2c48e3b2d9969abe23f4aa8793edd226f2919b3e 100644 (file)
@@ -631,7 +631,7 @@ public:
 
   void add_need_snapflush(CInode *snapin, snapid_t snapid, client_t client);
   void remove_need_snapflush(CInode *snapin, snapid_t snapid, client_t client);
-  bool split_need_snapflush(CInode *cowin, CInode *in);
+  pair<bool,bool> split_need_snapflush(CInode *cowin, CInode *in);
 
 protected:
 
index 5417ca22253518eb2ce633ab560d71c61e31f325..5b6770689508d8d55d6c14ef1b4b9c13b667a666 100644 (file)
@@ -1465,19 +1465,41 @@ CInode *MDCache::cow_inode(CInode *in, snapid_t last)
   if (in->last != CEPH_NOSNAP) {
     CInode *head_in = get_inode(in->ino());
     ceph_assert(head_in);
-    if (head_in->split_need_snapflush(oldin, in)) {
+    auto ret = head_in->split_need_snapflush(oldin, in);
+    if (ret.first) {
       oldin->client_snap_caps = in->client_snap_caps;
-      for (const auto &p : in->client_snap_caps) {
+      for (const auto &p : oldin->client_snap_caps) {
        SimpleLock *lock = oldin->get_lock(p.first);
        ceph_assert(lock);
        for (const auto &q : p.second) {
-         oldin->auth_pin(lock);
-         lock->set_state(LOCK_SNAP_SYNC);  // gathering
+         if (lock->get_state() != LOCK_SNAP_SYNC) {
+           ceph_assert(lock->is_stable());
+           lock->set_state(LOCK_SNAP_SYNC);  // gathering
+           oldin->auth_pin(lock);
+         }
          lock->get_wrlock(true);
-          (void)q; /* unused */
+         (void)q; /* unused */
        }
       }
     }
+    if (!ret.second) {
+      auto client_snap_caps = std::move(in->client_snap_caps);
+      in->client_snap_caps.clear();
+      in->item_open_file.remove_myself();
+      in->item_caps.remove_myself();
+      for (const auto &p : client_snap_caps) {
+       SimpleLock *lock = in->get_lock(p.first);
+       ceph_assert(lock);
+       ceph_assert(lock->get_state() == LOCK_SNAP_SYNC); // gathering
+       for (const auto &q : p.second) {
+         lock->put_wrlock();
+         (void)q; /* unused */
+       }
+       ceph_assert(!lock->get_num_wrlocks());
+       lock->set_state(LOCK_SYNC);
+       in->auth_unpin(lock);
+      }
+    }
     return oldin;
   }
 
@@ -1496,10 +1518,13 @@ CInode *MDCache::cow_inode(CInode *in, snapid_t last)
            int lockid = cinode_lock_info[i].lock;
            SimpleLock *lock = oldin->get_lock(lockid);
            ceph_assert(lock);
-           oldin->client_snap_caps[lockid].insert(client);
-           oldin->auth_pin(lock);
-           lock->set_state(LOCK_SNAP_SYNC);  // gathering
+           if (lock->get_state() != LOCK_SNAP_SYNC) {
+             ceph_assert(lock->is_stable());
+             lock->set_state(LOCK_SNAP_SYNC);  // gathering
+             oldin->auth_pin(lock);
+           }
            lock->get_wrlock(true);
+           oldin->client_snap_caps[lockid].insert(client);
            dout(10) << " client." << client << " cap " << ccap_string(issued & cinode_lock_info[i].wr_caps)
                     << " wrlock lock " << *lock << " on " << *oldin << dendl;
          }