Luís Henriques 34ce54
From: Xiubo Li <xiubli@redhat.com>
Luís Henriques 34ce54
Date: Wed, 27 Apr 2022 14:14:41 +0800
Luís Henriques 34ce54
Subject: ceph: try to queue a writeback if revoking fails
Luís Henriques 34ce54
Git-commit: a74379543d229a3fb1af8cd44cbd19844a7bb1bc
Luís Henriques 34ce54
Patch-mainline: v5.19-rc1
Luís Henriques 34ce54
References: jsc#SES-1880
Luís Henriques 34ce54
Luís Henriques 34ce54
If the pagecaches writeback just finished and the i_wrbuffer_ref
Luís Henriques 34ce54
reaches zero it will try to trigger ceph_check_caps(). But if just
Luís Henriques 34ce54
before ceph_check_caps() the i_wrbuffer_ref could be increased
Luís Henriques 34ce54
again by mmap/cache write, then the Fwb revoke will fail.
Luís Henriques 34ce54
Luís Henriques 34ce54
We need to try to queue a writeback in this case instead of
Luís Henriques 34ce54
triggering the writeback by BDI's delayed work per 5 seconds.
Luís Henriques 34ce54
Luís Henriques 34ce54
URL: https://tracker.ceph.com/issues/46904
Luís Henriques 34ce54
URL: https://tracker.ceph.com/issues/55377
Luís Henriques 34ce54
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Luís Henriques 34ce54
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Luís Henriques 34ce54
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Luís Henriques 34ce54
Acked-by: Luis Henriques <lhenriques@suse.com>
Luís Henriques 34ce54
---
Luís Henriques 34ce54
 fs/ceph/caps.c | 28 ++++++++++++++++++++++++----
Luís Henriques 34ce54
 1 file changed, 24 insertions(+), 4 deletions(-)
Luís Henriques 34ce54
Luís Henriques 34ce54
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
Luís Henriques 34ce54
index a051e6e4d7ca..bf2e94005598 100644
Luís Henriques 34ce54
--- a/fs/ceph/caps.c
Luís Henriques 34ce54
+++ b/fs/ceph/caps.c
Luís Henriques 34ce54
@@ -1911,6 +1911,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
Luís Henriques 34ce54
 	struct rb_node *p;
Luís Henriques 34ce54
 	bool queue_invalidate = false;
Luís Henriques 34ce54
 	bool tried_invalidate = false;
Luís Henriques 34ce54
+	bool queue_writeback = false;
Luís Henriques 34ce54
 
Luís Henriques 34ce54
 	if (session)
Luís Henriques 34ce54
 		ceph_get_mds_session(session);
Luís Henriques 34ce54
@@ -2063,10 +2064,27 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
Luís Henriques 34ce54
 		}
Luís Henriques 34ce54
 
Luís Henriques 34ce54
 		/* completed revocation? going down and there are no caps? */
Luís Henriques 34ce54
-		if (revoking && (revoking & cap_used) == 0) {
Luís Henriques 34ce54
-			dout("completed revocation of %s\n",
Luís Henriques 34ce54
-			     ceph_cap_string(cap->implemented & ~cap->issued));
Luís Henriques 34ce54
-			goto ack;
Luís Henriques 34ce54
+		if (revoking) {
Luís Henriques 34ce54
+			if ((revoking & cap_used) == 0) {
Luís Henriques 34ce54
+				dout("completed revocation of %s\n",
Luís Henriques 34ce54
+				      ceph_cap_string(cap->implemented & ~cap->issued));
Luís Henriques 34ce54
+				goto ack;
Luís Henriques 34ce54
+			}
Luís Henriques 34ce54
+
Luís Henriques 34ce54
+			/*
Luís Henriques 34ce54
+			 * If the "i_wrbuffer_ref" was increased by mmap or generic
Luís Henriques 34ce54
+			 * cache write just before the ceph_check_caps() is called,
Luís Henriques 34ce54
+			 * the Fb capability revoking will fail this time. Then we
Luís Henriques 34ce54
+			 * must wait for the BDI's delayed work to flush the dirty
Luís Henriques 34ce54
+			 * pages and to release the "i_wrbuffer_ref", which will cost
Luís Henriques 34ce54
+			 * at most 5 seconds. That means the MDS needs to wait at
Luís Henriques 34ce54
+			 * most 5 seconds to finished the Fb capability's revocation.
Luís Henriques 34ce54
+			 *
Luís Henriques 34ce54
+			 * Let's queue a writeback for it.
Luís Henriques 34ce54
+			 */
Luís Henriques 34ce54
+			if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
Luís Henriques 34ce54
+			    (revoking & CEPH_CAP_FILE_BUFFER))
Luís Henriques 34ce54
+				queue_writeback = true;
Luís Henriques 34ce54
 		}
Luís Henriques 34ce54
 
Luís Henriques 34ce54
 		/* want more caps from mds? */
Luís Henriques 34ce54
@@ -2136,6 +2154,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
Luís Henriques 34ce54
 	spin_unlock(&ci->i_ceph_lock);
Luís Henriques 34ce54
 
Luís Henriques 34ce54
 	ceph_put_mds_session(session);
Luís Henriques 34ce54
+	if (queue_writeback)
Luís Henriques 34ce54
+		ceph_queue_writeback(inode);
Luís Henriques 34ce54
 	if (queue_invalidate)
Luís Henriques 34ce54
 		ceph_queue_invalidate(inode);
Luís Henriques 34ce54
 }
Luís Henriques 34ce54