Commit 902d6d01 authored by Xiubo Li's avatar Xiubo Li Committed by Ilya Dryomov
Browse files

ceph: always queue a writeback when revoking the Fb caps

In case there is 'Fw' dirty caps and 'CHECK_CAPS_FLUSH' is set we
will always ignore queue a writeback. Queue a writeback is very
important because it will block kclient flushing the snapcaps to
MDS and which will block MDS waiting for revoking the 'Fb' caps.

Link: https://tracker.ceph.com/issues/50223


Signed-off-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-by: default avatarMilind Changire <mchangir@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 841c3516
Loading
Loading
Loading
Loading
+24 −24
Original line number Diff line number Diff line
@@ -2156,6 +2156,30 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
		      ceph_cap_string(cap->implemented),
		      ceph_cap_string(revoking));

		/* completed revocation? going down and there are no caps? */
		if (revoking) {
			if ((revoking & cap_used) == 0) {
				doutc(cl, "completed revocation of %s\n",
				      ceph_cap_string(cap->implemented & ~cap->issued));
				goto ack;
			}

			/*
			 * If the "i_wrbuffer_ref" was increased by mmap or generic
			 * cache write just before the ceph_check_caps() is called,
			 * the Fb capability revoking will fail this time. Then we
			 * must wait for the BDI's delayed work to flush the dirty
			 * pages and to release the "i_wrbuffer_ref", which will cost
			 * at most 5 seconds. That means the MDS needs to wait at
			 * most 5 seconds to finished the Fb capability's revocation.
			 *
			 * Let's queue a writeback for it.
			 */
			if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
			    (revoking & CEPH_CAP_FILE_BUFFER))
				queue_writeback = true;
		}

		if (cap == ci->i_auth_cap &&
		    (cap->issued & CEPH_CAP_FILE_WR)) {
			/* request larger max_size from MDS? */
@@ -2183,30 +2207,6 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
			}
		}

		/* completed revocation? going down and there are no caps? */
		if (revoking) {
			if ((revoking & cap_used) == 0) {
				doutc(cl, "completed revocation of %s\n",
				      ceph_cap_string(cap->implemented & ~cap->issued));
				goto ack;
			}

			/*
			 * If the "i_wrbuffer_ref" was increased by mmap or generic
			 * cache write just before the ceph_check_caps() is called,
			 * the Fb capability revoking will fail this time. Then we
			 * must wait for the BDI's delayed work to flush the dirty
			 * pages and to release the "i_wrbuffer_ref", which will cost
			 * at most 5 seconds. That means the MDS needs to wait at
			 * most 5 seconds to finished the Fb capability's revocation.
			 *
			 * Let's queue a writeback for it.
			 */
			if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
			    (revoking & CEPH_CAP_FILE_BUFFER))
				queue_writeback = true;
		}

		/* want more caps from mds? */
		if (want & ~cap->mds_wanted) {
			if (want & ~(cap->mds_wanted | cap->issued))