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

ceph: 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.

Link: https://tracker.ceph.com/issues/61332Signed-off-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-by: default avatarMilind Changire <mchangir@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 2d12ad95
......@@ -4092,6 +4092,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct cap_extra_info extra_info = {};
bool queue_trunc;
bool close_sessions = false;
bool do_cap_release = false;
dout("handle_caps from mds%d\n", session->s_mds);
......@@ -4198,17 +4199,14 @@ void ceph_handle_caps(struct ceph_mds_session *session,
if (!inode) {
dout(" i don't have ino %llx\n", vino.ino);
if (op == CEPH_CAP_OP_IMPORT) {
cap = ceph_get_cap(mdsc, NULL);
cap->cap_ino = vino.ino;
cap->queue_release = 1;
cap->cap_id = le64_to_cpu(h->cap_id);
cap->mseq = mseq;
cap->seq = seq;
cap->issue_seq = seq;
spin_lock(&session->s_cap_lock);
__ceph_queue_cap_release(session, cap);
spin_unlock(&session->s_cap_lock);
switch (op) {
case CEPH_CAP_OP_IMPORT:
case CEPH_CAP_OP_REVOKE:
case CEPH_CAP_OP_GRANT:
do_cap_release = true;
break;
default:
break;
}
goto flush_cap_releases;
}
......@@ -4258,6 +4256,14 @@ void ceph_handle_caps(struct ceph_mds_session *session,
inode, ceph_ino(inode), ceph_snap(inode),
session->s_mds);
spin_unlock(&ci->i_ceph_lock);
switch (op) {
case CEPH_CAP_OP_REVOKE:
case CEPH_CAP_OP_GRANT:
do_cap_release = true;
break;
default:
break;
}
goto flush_cap_releases;
}
......@@ -4308,6 +4314,18 @@ void ceph_handle_caps(struct ceph_mds_session *session,
* along for the mds (who clearly thinks we still have this
* cap).
*/
if (do_cap_release) {
cap = ceph_get_cap(mdsc, NULL);
cap->cap_ino = vino.ino;
cap->queue_release = 1;
cap->cap_id = le64_to_cpu(h->cap_id);
cap->mseq = mseq;
cap->seq = seq;
cap->issue_seq = seq;
spin_lock(&session->s_cap_lock);
__ceph_queue_cap_release(session, cap);
spin_unlock(&session->s_cap_lock);
}
ceph_flush_cap_releases(mdsc, session);
goto done;
......
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