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

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/61332


Signed-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
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -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;