From: Xiubo Li <xiubli@xxxxxxxxxx> For write when trying to get the Fwb caps we need to keep waiting on transition from WRBUFFER|WR -> WR to avoid a new WR sync write from going before a prior buffered writeback happens. Whild for read there is not need to wait on transition from RDCACHE|RD -> RD, and we can just exclude the revoking caps and force to sync read. Signed-off-by: Xiubo Li <xiubli@xxxxxxxxxx> --- fs/ceph/caps.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 139d21b8fb49..d5fc9b1be7c3 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2811,13 +2811,17 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, * on transition from wanted -> needed caps. This is needed * for WRBUFFER|WR -> WR to avoid a new WR sync write from * going before a prior buffered writeback happens. + * + * For RDCACHE|RD -> RD, there is not need to wait and we can + * just exclude the revoking caps and force to sync read. */ int not = want & ~(have & need); int revoking = implemented & ~have; + int exclude = revoking & not; dout("get_cap_refs %p have %s but not %s (revoking %s)\n", inode, ceph_cap_string(have), ceph_cap_string(not), ceph_cap_string(revoking)); - if ((revoking & not) == 0) { + if (!exclude || !(exclude & CEPH_CAP_FILE_BUFFER)) { if (!snap_rwsem_locked && !ci->i_head_snapc && (need & CEPH_CAP_FILE_WR)) { @@ -2839,7 +2843,7 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, snap_rwsem_locked = true; } if ((have & want) == want) - *got = need | want; + *got = need | (want & ~exclude); else *got = need; ceph_take_cap_refs(ci, *got, true); -- 2.36.0.rc1