diff mbox series

ceph: issue a cap release immediately if no cap exists

Message ID 20230618231011.9077-1-xiubli@redhat.com
State New
Headers show
Series ceph: issue a cap release immediately if no cap exists | expand

Commit Message

Xiubo Li June 18, 2023, 11:10 p.m. UTC
From: Xiubo Li <xiubli@redhat.com>

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.

URL: https://tracker.ceph.com/issues/61332
Signed-off-by: Xiubo Li <xiubli@redhat.com>
---
 fs/ceph/caps.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

Comments

Milind Changire June 27, 2023, 1:42 p.m. UTC | #1
Looks good to me.

Reviewed-by: Milind Changire <mchangir@redhat.com>

On Mon, Jun 19, 2023 at 4:42 AM <xiubli@redhat.com> wrote:
>
> From: Xiubo Li <xiubli@redhat.com>
>
> 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.
>
> URL: https://tracker.ceph.com/issues/61332
> Signed-off-by: Xiubo Li <xiubli@redhat.com>
> ---
>  fs/ceph/caps.c | 40 +++++++++++++++++++++++++++++-----------
>  1 file changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
> index 5498bc36c1e7..59ab5d905ac4 100644
> --- a/fs/ceph/caps.c
> +++ b/fs/ceph/caps.c
> @@ -4232,6 +4232,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);
>
> @@ -4349,17 +4350,14 @@ void ceph_handle_caps(struct ceph_mds_session *session,
>                 else
>                         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;
>         }
> @@ -4413,6 +4411,14 @@ void ceph_handle_caps(struct ceph_mds_session *session,
>                         pr_info("%s: no cap on %p ino %llx:%llx from mds%d for flush_ack!\n",
>                                 __func__, inode, ceph_ino(inode),
>                                 ceph_snap(inode), session->s_mds);
> +               switch (op) {
> +               case CEPH_CAP_OP_REVOKE:
> +               case CEPH_CAP_OP_GRANT:
> +                       do_cap_release = true;
> +                       break;
> +               default:
> +                       break;
> +               }
>                 goto flush_cap_releases;
>         }
>
> @@ -4467,6 +4473,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;
>
> --
> 2.40.1
>
diff mbox series

Patch

diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 5498bc36c1e7..59ab5d905ac4 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -4232,6 +4232,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);
 
@@ -4349,17 +4350,14 @@  void ceph_handle_caps(struct ceph_mds_session *session,
 		else
 			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;
 	}
@@ -4413,6 +4411,14 @@  void ceph_handle_caps(struct ceph_mds_session *session,
 			pr_info("%s: no cap on %p ino %llx:%llx from mds%d for flush_ack!\n",
 				__func__, inode, ceph_ino(inode),
 				ceph_snap(inode), session->s_mds);
+		switch (op) {
+		case CEPH_CAP_OP_REVOKE:
+		case CEPH_CAP_OP_GRANT:
+			do_cap_release = true;
+			break;
+		default:
+			break;
+		}
 		goto flush_cap_releases;
 	}
 
@@ -4467,6 +4473,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;