Commit a7437954 authored by Xiubo Li's avatar Xiubo Li Committed by Ilya Dryomov

ceph: try to queue a writeback if revoking fails

If the pagecaches writeback just finished and the i_wrbuffer_ref
reaches zero it will try to trigger ceph_check_caps(). But if just
before ceph_check_caps() the i_wrbuffer_ref could be increased
again by mmap/cache write, then the Fwb revoke will fail.

We need to try to queue a writeback in this case instead of
triggering the writeback by BDI's delayed work per 5 seconds.

URL: https://tracker.ceph.com/issues/46904
URL: https://tracker.ceph.com/issues/55377Signed-off-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 55ab5520
...@@ -1911,6 +1911,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -1911,6 +1911,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
struct rb_node *p; struct rb_node *p;
bool queue_invalidate = false; bool queue_invalidate = false;
bool tried_invalidate = false; bool tried_invalidate = false;
bool queue_writeback = false;
if (session) if (session)
ceph_get_mds_session(session); ceph_get_mds_session(session);
...@@ -2063,10 +2064,27 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -2063,10 +2064,27 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
} }
/* completed revocation? going down and there are no caps? */ /* completed revocation? going down and there are no caps? */
if (revoking && (revoking & cap_used) == 0) { if (revoking) {
dout("completed revocation of %s\n", if ((revoking & cap_used) == 0) {
ceph_cap_string(cap->implemented & ~cap->issued)); dout("completed revocation of %s\n",
goto ack; 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? */ /* want more caps from mds? */
...@@ -2136,6 +2154,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -2136,6 +2154,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
ceph_put_mds_session(session); ceph_put_mds_session(session);
if (queue_writeback)
ceph_queue_writeback(inode);
if (queue_invalidate) if (queue_invalidate)
ceph_queue_invalidate(inode); ceph_queue_invalidate(inode);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment