When revoking caps the if we queue to defer releasing them after 5s
or client_caps_release_delay. What if when the client keeps doing
mark_caps_dirty() for that inode in some use cases, the inode will
always be pushed back to the end of dirty_list. And in the tick()
it will check the dirty_list from front and will skip looping it
when it finds current one is not out of date.
This may cause the revocation in the MDS side stuck for a long
time.
Fixes: https://tracker.ceph.com/issues/52994
Signed-off-by: Xiubo Li <xiubli@redhat.com>
(cherry picked from commit
66098eeb1dbd0ffb4478c866ab4208e471d709f1)
mds_rank_t mds = session->mds_num;
int used = get_caps_used(in);
int wanted = in->caps_wanted();
+ int flags = 0;
const unsigned new_caps = m->get_caps();
const bool was_stale = session->cap_gen > cap->gen;
!_flush(in, new C_Client_FlushComplete(this, in))) {
// waitin' for flush
} else if (used & revoked & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) {
- if (_release(in))
- check = true;
+ if (_release(in)) {
+ check = true;
+ flags = CHECK_CAPS_NODELAY;
+ }
} else {
cap->wanted = 0; // don't let check_caps skip sending a response to MDS
check = true;
+ flags = CHECK_CAPS_NODELAY;
}
} else if (cap->issued == new_caps) {
ldout(cct, 10) << " caps unchanged at " << ccap_string(cap->issued) << dendl;
}
if (check)
- check_caps(in, 0);
+ check_caps(in, flags);
// wake up waiters
if (new_caps)