Message ID | 20200310113421.174873-4-zyan@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fix ceph_get_caps() bugs | expand |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 295b61201d85..f63db3cb9c4f 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2008,8 +2008,12 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, } /* want more caps from mds? */ - if (want & ~(cap->mds_wanted | cap->issued)) - goto ack; + if (want & ~cap->mds_wanted) { + if (want & ~(cap->mds_wanted | cap->issued)) + goto ack; + if (!__cap_is_valid(cap)) + goto ack; + } /* things we might delay */ if ((cap->issued & ~retain) == 0)
1. try_get_cap_refs() fails to get caps and finds that mds_wanted does not include what it wants. It return -ESTALE. 2. ceph_get_caps() calls ceph_renew_caps(). ceph_renew_caps() finds that inode has cap, so it calls ceph_check_caps(). 3. ceph_check_caps() finds that issued caps (without checking if it's stale) already includes caps wanted by open file, so it skips updating wanted caps. Above events can cause infinite loop inside ceph_get_caps() Signed-off-by: "Yan, Zheng" <zyan@redhat.com> --- fs/ceph/caps.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)