]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: move dirty_list to MetaSession 44255/head
authorXiubo Li <xiubli@redhat.com>
Mon, 13 Dec 2021 04:45:40 +0000 (12:45 +0800)
committerXiubo Li <xiubli@redhat.com>
Mon, 13 Dec 2021 09:20:06 +0000 (17:20 +0800)
Then we can easily use the last dirty cap to flush the mdlog. This
will be useful when syncing the whole filesystem.

The delayed_list will hold both dirty and release caps. The dirty
caps will be checked by the dirty_list in each session and it makes
no sense to flush the release caps when syncing the filesystem.

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

index dd18cb51d48bda7b317c1b1fdf1f536d2042386c..1f20eedf60dae8f204a9e9cc4986e90fdc39296a 100644 (file)
@@ -4652,35 +4652,25 @@ void Client::adjust_session_flushing_caps(Inode *in, MetaSession *old_s,  MetaSe
 }
 
 /*
- * Flush all caps back to the MDS. Because the callers generally wait on the
- * result of this function (syncfs and umount cases), we set
- * CHECK_CAPS_SYNCHRONOUS on the last check_caps call.
+ * Flush all the dirty caps back to the MDS. Because the callers
+ * generally wait on the result of this function (syncfs and umount
+ * cases), we set CHECK_CAPS_SYNCHRONOUS on the last check_caps call.
  */
 void Client::flush_caps_sync()
 {
   ldout(cct, 10) << __func__ << dendl;
-  xlist<Inode*>::iterator p = delayed_list.begin();
-  while (!p.end()) {
-    unsigned flags = CHECK_CAPS_NODELAY;
-    Inode *in = *p;
-
-    ++p;
-    delayed_list.pop_front();
-    if (p.end() && dirty_list.empty())
-      flags |= CHECK_CAPS_SYNCHRONOUS;
-    check_caps(in, flags);
-  }
-
-  // other caps, too
-  p = dirty_list.begin();
-  while (!p.end()) {
-    unsigned flags = CHECK_CAPS_NODELAY;
-    Inode *in = *p;
+  for (auto &q : mds_sessions) {
+    auto s = q.second;
+    xlist<Inode*>::iterator p = s->dirty_list.begin();
+    while (!p.end()) {
+      unsigned flags = CHECK_CAPS_NODELAY;
+      Inode *in = *p;
 
-    ++p;
-    if (p.end())
-      flags |= CHECK_CAPS_SYNCHRONOUS;
-    check_caps(in, flags);
+      ++p;
+      if (p.end())
+        flags |= CHECK_CAPS_SYNCHRONOUS;
+      check_caps(in, flags);
+    }
   }
 }
 
@@ -6455,13 +6445,16 @@ void Client::_unmount(bool abort)
   }
 
   if (abort || blocklisted) {
-    for (auto p = dirty_list.begin(); !p.end(); ) {
-      Inode *in = *p;
-      ++p;
-      if (in->dirty_caps) {
-       ldout(cct, 0) << " drop dirty caps on " << *in << dendl;
-       in->mark_caps_clean();
-       put_inode(in);
+    for (auto &q : mds_sessions) {
+      auto s = q.second;
+      for (auto p = s->dirty_list.begin(); !p.end(); ) {
+        Inode *in = *p;
+        ++p;
+        if (in->dirty_caps) {
+          ldout(cct, 0) << " drop dirty caps on " << *in << dendl;
+          in->mark_caps_clean();
+          put_inode(in);
+        }
       }
     }
   } else {
index c6ba9bbf1bd454a0e0a41a7d0858b34d57c9f776..d7139983ef5e8b4361c5d41f273930b49fec8839 100644 (file)
@@ -875,8 +875,6 @@ public:
     return std::make_pair(opened_inodes, inode_map.size());
   }
 
-  xlist<Inode*> &get_dirty_list() { return dirty_list; }
-
   /* timer_lock for 'timer' */
   ceph::mutex timer_lock = ceph::make_mutex("Client::timer_lock");
   SafeTimer timer;
@@ -1530,8 +1528,7 @@ private:
   // cap flushing
   ceph_tid_t last_flush_tid = 1;
 
-  // dirty_list keeps all the dirty inodes before flushing.
-  xlist<Inode*> delayed_list, dirty_list;
+  xlist<Inode*> delayed_list;
   int num_flushing_caps = 0;
   ceph::unordered_map<inodeno_t,SnapRealm*> snap_realms;
   std::map<std::string, std::string> metadata;
index 0b3200bb0fa0778a527a158560f00c1cea98c17c..5c1523f2f427e52410f9de038f4c777a3570d709 100644 (file)
@@ -777,12 +777,26 @@ void Inode::unset_deleg(Fh *fh)
 */
 void Inode::mark_caps_dirty(int caps)
 {
+  /*
+   * If auth_cap is nullptr means the reonnecting is not finished or
+   * already rejected.
+   */
+  if (!auth_cap) {
+    ceph_assert(!dirty_caps);
+
+    lsubdout(client->cct, client, 1) << __func__ << " " << *this << " dirty caps '" << ccap_string(caps)
+            << "', but no auth cap." << dendl;
+    return;
+  }
+
   lsubdout(client->cct, client, 10) << __func__ << " " << *this << " " << ccap_string(dirty_caps) << " -> "
            << ccap_string(dirty_caps | caps) << dendl;
+
   if (caps && !caps_dirty())
     iget();
+
   dirty_caps |= caps;
-  client->get_dirty_list().push_back(&dirty_cap_item);
+  auth_cap->session->get_dirty_list().push_back(&dirty_cap_item);
   client->cap_delay_requeue(this);
 }
 
index cfeb26a471c90032f8ae938481a7c3cf67838075..4eae49b9d69a2011dcd802007c814e5d9d96fff4 100644 (file)
@@ -49,6 +49,8 @@ struct MetaSession {
   std::list<Context*> waiting_for_open;
 
   xlist<Cap*> caps;
+  // dirty_list keeps all the dirty inodes before flushing in current session.
+  xlist<Inode*> dirty_list;
   xlist<Inode*> flushing_caps;
   xlist<MetaRequest*> requests;
   xlist<MetaRequest*> unsafe_requests;
@@ -60,6 +62,8 @@ struct MetaSession {
     : mds_num(mds_num), con(con), addrs(addrs) {
   }
 
+  xlist<Inode*> &get_dirty_list() { return dirty_list; }
+
   const char *get_state_name() const;
 
   void dump(Formatter *f, bool cap_dump=false) const;