]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: always add one new capsnap if Fb is used and Fw is not used
authorXiubo Li <xiubli@redhat.com>
Mon, 8 May 2023 05:48:43 +0000 (13:48 +0800)
committerXiubo Li <xiubli@redhat.com>
Tue, 18 Jul 2023 02:28:13 +0000 (10:28 +0800)
If we set the 'writing' to 1 when the 'Fb' caps is used then later
if we have any dirty caps it will be skipped and will reuse the
existing capsnap, which is incorrect.

At the same time trigger to flush the buffer when making snapshot
and if the Fb is being used.

Fixes: https://tracker.ceph.com/issues/59343
Signed-off-by: Xiubo Li <xiubli@redhat.com>
(cherry picked from commit 6262351f7da9413d8306a6f1765ecab1f0ab912e)

src/client/Client.cc

index 52980d5ecb07ca185b4a154bbb11b69a7afcb643..8c12b6505e4934034ebc929693c52bdb08e7550a 100644 (file)
@@ -3514,7 +3514,7 @@ void Client::put_cap_ref(Inode *in, int cap)
     int put_nref = 0;
     int drop = last & ~in->caps_issued();
     if (in->snapid == CEPH_NOSNAP) {
-      if ((last & (CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER)) &&
+      if ((last & CEPH_CAP_FILE_WR) &&
          !in->cap_snaps.empty() &&
          in->cap_snaps.rbegin()->second.writing) {
        ldout(cct, 10) << __func__ << " finishing pending cap_snap on " << *in << dendl;
@@ -3528,6 +3528,10 @@ void Client::put_cap_ref(Inode *in, int cap)
        signal_cond_list(in->waitfor_commit);
        ldout(cct, 5) << __func__ << " dropped last FILE_BUFFER ref on " << *in << dendl;
        ++put_nref;
+
+       if (!in->cap_snaps.empty()) {
+         flush_snaps(in);
+       }
       }
     }
     if (last & CEPH_CAP_FILE_CACHE) {
@@ -4042,9 +4046,11 @@ void Client::finish_cap_snap(Inode *in, CapSnap &capsnap, int used)
   }
 
   if (used & CEPH_CAP_FILE_BUFFER) {
-    capsnap.writing = 1;
     ldout(cct, 10) << __func__ << " " << *in << " cap_snap " << &capsnap << " used " << used
-            << " WRBUFFER, delaying" << dendl;
+            << " WRBUFFER, trigger to flush dirty buffer" << dendl;
+
+    /* trigger to flush the buffer */
+    _flush(in, new C_Client_FlushComplete(this, in));
   } else {
     capsnap.dirty_data = 0;
     flush_snaps(in);