]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: fix dirty caps might never be flushed
authordongdong tao <tdd21151186@gmail.com>
Wed, 27 Dec 2017 15:47:16 +0000 (23:47 +0800)
committerPatrick Donnelly <pdonnell@redhat.com>
Mon, 4 Jun 2018 19:20:37 +0000 (12:20 -0700)
Fixes: http://tracker.ceph.com/issues/22546
Signed-off-by: dongdong tao <tdd21151186@gmail.com>
(cherry picked from commit aeb920be8ab5f0e5e47d82943c214b012bb8ec5c)

Conflicts:
src/client/Client.cc

src/client/Client.cc
src/client/Client.h
src/client/Inode.cc
src/client/Inode.h

index 044c29f3a08156818acfde4bd481b4a68903d109..b1b61757bd4bdff6f0a040cb6720c37585c9350c 100644 (file)
@@ -3232,7 +3232,7 @@ void Client::cap_delay_requeue(Inode *in)
   ldout(cct, 10) << "cap_delay_requeue on " << *in << dendl;
   in->hold_caps_until = ceph_clock_now();
   in->hold_caps_until += cct->_conf->client_caps_release_delay;
-  delayed_caps.push_back(&in->cap_item);
+  delayed_list.push_back(&in->delay_cap_item);
 }
 
 void Client::send_cap(Inode *in, MetaSession *session, Cap *cap,
@@ -3901,7 +3901,6 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id
     cap->session = mds_session;
     cap->inode = in;
     cap->gen = mds_session->cap_gen;
-    cap_list.push_back(&in->cap_item);
   }
 
   check_cap_issue(in, cap, issued);
@@ -4020,7 +4019,7 @@ void Client::remove_session_caps(MetaSession *s)
        in->flushing_cap_tids.clear();
       }
       in->flushing_caps = 0;
-      in->dirty_caps = 0;
+      mark_caps_clean(in);
       put_inode(in);
     }
   }
@@ -4161,11 +4160,19 @@ void Client::force_session_readonly(MetaSession *s)
 
 void Client::mark_caps_dirty(Inode *in, int caps)
 {
-  ldout(cct, 10) << "mark_caps_dirty " << *in << " " << ccap_string(in->dirty_caps) << " -> "
+  ldout(cct, 10) << __func__ << " " << *in << " " << ccap_string(in->dirty_caps) << " -> "
           << ccap_string(in->dirty_caps | caps) << dendl;
   if (caps && !in->caps_dirty())
     in->get();
   in->dirty_caps |= caps;
+  dirty_list.push_back(&in->dirty_cap_item);
+}
+
+void Client::mark_caps_clean(Inode *in)
+{
+  ldout(cct, 10) << __func__ << " " << *in << dendl;
+  in->dirty_caps = 0;
+  in->dirty_cap_item.remove_myself(); 
 }
 
 int Client::mark_caps_flushing(Inode *in, ceph_tid_t* ptid)
@@ -4186,7 +4193,7 @@ int Client::mark_caps_flushing(Inode *in, ceph_tid_t* ptid)
   }
 
   in->flushing_caps |= flushing;
-  in->dirty_caps = 0;
+  mark_caps_clean(in);
  
   if (!in->flushing_cap_item.is_on_list())
     session->flushing_caps.push_back(&in->flushing_cap_item);
@@ -4222,20 +4229,20 @@ void Client::adjust_session_flushing_caps(Inode *in, MetaSession *old_s,  MetaSe
 void Client::flush_caps_sync()
 {
   ldout(cct, 10) << __func__ << dendl;
-  xlist<Inode*>::iterator p = delayed_caps.begin();
+  xlist<Inode*>::iterator p = delayed_list.begin();
   while (!p.end()) {
     unsigned flags = CHECK_CAPS_NODELAY;
     Inode *in = *p;
 
     ++p;
-    delayed_caps.pop_front();
-    if (p.end() && cap_list.empty())
+    delayed_list.pop_front();
+    if (p.end() && dirty_list.empty())
       flags |= CHECK_CAPS_SYNCHRONOUS;
     check_caps(in, flags);
   }
 
   // other caps, too
-  p = cap_list.begin();
+  p = dirty_list.begin();
   while (!p.end()) {
     unsigned flags = CHECK_CAPS_NODELAY;
     Inode *in = *p;
@@ -6054,14 +6061,13 @@ void Client::tick()
   }
 
   // delayed caps
-  xlist<Inode*>::iterator p = delayed_caps.begin();
+  xlist<Inode*>::iterator p = delayed_list.begin();
   while (!p.end()) {
     Inode *in = *p;
     ++p;
     if (in->hold_caps_until > now)
       break;
-    delayed_caps.pop_front();
-    cap_list.push_back(&in->cap_item);
+    delayed_list.pop_front();
     check_caps(in, CHECK_CAPS_NODELAY);
   }
 
index 6c131182b8a4c698d277b194d8c7dfd30e07fd22..6940053f87cebb2a770b2e423bfb639c76bda728 100644 (file)
@@ -432,8 +432,8 @@ protected:
   Inode*                 root_ancestor;
   LRU                    lru;    // lru list of Dentry's in our local metadata cache.
 
-  // all inodes with caps sit on either cap_list or delayed_caps.
-  xlist<Inode*> delayed_caps, cap_list;
+  // dirty_list keeps all the dirty inodes before flushing.
+  xlist<Inode*> delayed_list, dirty_list;
   int num_flushing_caps;
   ceph::unordered_map<inodeno_t,SnapRealm*> snap_realms;
 
@@ -636,6 +636,7 @@ protected:
   void remove_all_caps(Inode *in);
   void remove_session_caps(MetaSession *session);
   void mark_caps_dirty(Inode *in, int caps);
+  void mark_caps_clean(Inode *in);
   int mark_caps_flushing(Inode *in, ceph_tid_t *ptid);
   void adjust_session_flushing_caps(Inode *in, MetaSession *old_s, MetaSession *new_s);
   void flush_caps_sync();
index 60689db06c435a3176a0eae341468cfdf003ee1f..d877757faa1e1debf2f3840be122b419c934404f 100644 (file)
@@ -14,7 +14,8 @@
 
 Inode::~Inode()
 {
-  cap_item.remove_myself();
+  delay_cap_item.remove_myself();
+  dirty_cap_item.remove_myself(); 
   snaprealm_item.remove_myself();
 
   if (snapdir_parent) {
index 5242630d5d1a23b4954a6f4c27d0185d18a78ab7..9c9ebe0c3770431434e4713cf033031ff0ca8a77 100644 (file)
@@ -177,7 +177,7 @@ struct Inode {
   int shared_gen, cache_gen;
   int snap_caps, snap_cap_refs;
   utime_t hold_caps_until;
-  xlist<Inode*>::item cap_item, flushing_cap_item;
+  xlist<Inode*>::item delay_cap_item, dirty_cap_item, flushing_cap_item;
 
   SnapRealm *snaprealm;
   xlist<Inode*>::item snaprealm_item;
@@ -247,7 +247,7 @@ struct Inode {
       cap_dirtier_uid(-1), cap_dirtier_gid(-1),
       dirty_caps(0), flushing_caps(0), shared_gen(0), cache_gen(0),
       snap_caps(0), snap_cap_refs(0),
-      cap_item(this), flushing_cap_item(this),
+      delay_cap_item(this), dirty_cap_item(this), flushing_cap_item(this),
       snaprealm(0), snaprealm_item(this),
       oset((void *)this, newlayout->pool_id, this->ino),
       reported_size(0), wanted_max_size(0), requested_max_size(0),