From: Xiubo Li Date: Tue, 16 May 2023 01:18:15 +0000 (+0800) Subject: client: issue a cap release immediately if no cap exists X-Git-Tag: v19.0.0~995^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7aaf4ba81b978db63b9cb11a90f881196530e5d5;p=ceph.git client: issue a cap release immediately if no cap exists In case: mds client - Releases cap and put Inode - Increase cap->seq and sends revokes req to the client - Receives release req and - Receives & drops the revoke req skip removing the cap and then eval the CInode and issue or revoke caps again. - Receives & drops the caps update or revoke req - Health warning for client isn't responding to mclientcaps(revoke) All the IMPORT/REVOKE/GRANT cap ops will increase the session seq in MDS side and then the client need to issue a cap release to unblock MDS to remove the corresponding cap to unblock possible waiters. Fixes: https://tracker.ceph.com/issues/57244 Fixes: https://tracker.ceph.com/issues/61148 Signed-off-by: Xiubo Li --- diff --git a/src/client/Client.cc b/src/client/Client.cc index a456ea2b81f..301b8e3903e 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -5309,24 +5309,48 @@ void Client::handle_caps(const MConstRef& m) got_mds_push(session.get()); + bool do_cap_release = false; Inode *in; vinodeno_t vino(m->get_ino(), CEPH_NOSNAP); if (auto it = inode_map.find(vino); it != inode_map.end()) { in = it->second; + + /* MDS maybe waiting for cap release with increased seq */ + switch (m->get_op()) { + case CEPH_CAP_OP_REVOKE: + case CEPH_CAP_OP_GRANT: + if (!in->caps.count(mds)) { + do_cap_release = true; + ldout(cct, 5) << __func__ << " vino " << vino << " don't have cap " + << m->get_cap_id() << " op " << m->get_op() + << ", immediately releasing" << dendl; + } + } } else { - if (m->get_op() == CEPH_CAP_OP_IMPORT) { - ldout(cct, 5) << __func__ << " don't have vino " << vino << " on IMPORT, immediately releasing" << dendl; - session->enqueue_cap_release( - m->get_ino(), - m->get_cap_id(), - m->get_seq(), - m->get_mseq(), - cap_epoch_barrier); - } else { - ldout(cct, 5) << __func__ << " don't have vino " << vino << ", dropping" << dendl; + /* MDS maybe waiting for cap release with increased seq */ + switch (m->get_op()) { + case CEPH_CAP_OP_IMPORT: + case CEPH_CAP_OP_REVOKE: + case CEPH_CAP_OP_GRANT: + do_cap_release = true; + ldout(cct, 5) << __func__ << " don't have vino " << vino << " op " + << m->get_op() << ", immediately releasing" << dendl; + break; + default: + ldout(cct, 5) << __func__ << " don't have vino " << vino << ", dropping" << dendl; + return; } + } + + // In case the mds is waiting on e.g. a revocation + if (do_cap_release) { + session->enqueue_cap_release( + m->get_ino(), + m->get_cap_id(), + m->get_seq(), + m->get_mseq(), + cap_epoch_barrier); - // in case the mds is waiting on e.g. a revocation flush_cap_releases(); return; }