diff mbox series

[v2] ceph: fail the request if the peer MDS doesn't support getvxattr op

Message ID 20220803091844.608743-1-xiubli@redhat.com (mailing list archive)
State New, archived
Headers show
Series [v2] ceph: fail the request if the peer MDS doesn't support getvxattr op | expand

Commit Message

Xiubo Li Aug. 3, 2022, 9:18 a.m. UTC
From: Xiubo Li <xiubli@redhat.com>

Just fail the request instead sending the request out, or the peer
MDS will crash.

URL: https://tracker.ceph.com/issues/56529
Signed-off-by: Xiubo Li <xiubli@redhat.com>
---

V2:
- Sync to the https://github.com/ceph/ceph/pull/47063. Will return -EOPNOTSUPP
  directly instead of falling back to old method.


 fs/ceph/inode.c      |  1 +
 fs/ceph/mds_client.c | 11 +++++++++++
 fs/ceph/mds_client.h |  6 +++++-
 fs/ceph/xattr.c      |  6 +-----
 4 files changed, 18 insertions(+), 6 deletions(-)

Comments

Xiubo Li Aug. 8, 2022, 2:26 a.m. UTC | #1
On 8/3/22 5:18 PM, xiubli@redhat.com wrote:
> From: Xiubo Li <xiubli@redhat.com>
>
> Just fail the request instead sending the request out, or the peer
> MDS will crash.
>
> URL: https://tracker.ceph.com/issues/56529
> Signed-off-by: Xiubo Li <xiubli@redhat.com>
> ---
>
> V2:
> - Sync to the https://github.com/ceph/ceph/pull/47063. Will return -EOPNOTSUPP
>    directly instead of falling back to old method.
>
As discussed in the PR#47063, it has switched to -ENODATA instead.

I will post the V3 to fix it.

Thanks!


>   fs/ceph/inode.c      |  1 +
>   fs/ceph/mds_client.c | 11 +++++++++++
>   fs/ceph/mds_client.h |  6 +++++-
>   fs/ceph/xattr.c      |  6 +-----
>   4 files changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
> index 79ff197c7cc5..cfa0b550eef2 100644
> --- a/fs/ceph/inode.c
> +++ b/fs/ceph/inode.c
> @@ -2607,6 +2607,7 @@ int ceph_do_getvxattr(struct inode *inode, const char *name, void *value,
>   		goto out;
>   	}
>   
> +	req->r_feature_needed = CEPHFS_FEATURE_OP_GETVXATTR;
>   	req->r_path2 = kstrdup(name, GFP_NOFS);
>   	if (!req->r_path2) {
>   		err = -ENOMEM;
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index 598012ddc401..e3683305445c 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -2501,6 +2501,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>   	INIT_LIST_HEAD(&req->r_unsafe_dir_item);
>   	INIT_LIST_HEAD(&req->r_unsafe_target_item);
>   	req->r_fmode = -1;
> +	req->r_feature_needed = -1;
>   	kref_init(&req->r_kref);
>   	RB_CLEAR_NODE(&req->r_node);
>   	INIT_LIST_HEAD(&req->r_wait);
> @@ -3255,6 +3256,16 @@ static void __do_request(struct ceph_mds_client *mdsc,
>   
>   	dout("do_request mds%d session %p state %s\n", mds, session,
>   	     ceph_session_state_name(session->s_state));
> +
> +	/*
> +	 * The old ceph will crash the MDSs when see unknown OPs
> +	 */
> +	if (req->r_feature_needed > 0 &&
> +	    !test_bit(req->r_feature_needed, &session->s_features)) {
> +		err = -EOPNOTSUPP;
> +		goto out_session;
> +	}
> +
>   	if (session->s_state != CEPH_MDS_SESSION_OPEN &&
>   	    session->s_state != CEPH_MDS_SESSION_HUNG) {
>   		/*
> diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
> index e15ee2858fef..728b7d72bf76 100644
> --- a/fs/ceph/mds_client.h
> +++ b/fs/ceph/mds_client.h
> @@ -31,8 +31,9 @@ enum ceph_feature_type {
>   	CEPHFS_FEATURE_METRIC_COLLECT,
>   	CEPHFS_FEATURE_ALTERNATE_NAME,
>   	CEPHFS_FEATURE_NOTIFY_SESSION_STATE,
> +	CEPHFS_FEATURE_OP_GETVXATTR,
>   
> -	CEPHFS_FEATURE_MAX = CEPHFS_FEATURE_NOTIFY_SESSION_STATE,
> +	CEPHFS_FEATURE_MAX = CEPHFS_FEATURE_OP_GETVXATTR,
>   };
>   
>   #define CEPHFS_FEATURES_CLIENT_SUPPORTED {	\
> @@ -45,6 +46,7 @@ enum ceph_feature_type {
>   	CEPHFS_FEATURE_METRIC_COLLECT,		\
>   	CEPHFS_FEATURE_ALTERNATE_NAME,		\
>   	CEPHFS_FEATURE_NOTIFY_SESSION_STATE,	\
> +	CEPHFS_FEATURE_OP_GETVXATTR,		\
>   }
>   
>   /*
> @@ -352,6 +354,8 @@ struct ceph_mds_request {
>   	long long	  r_dir_ordered_cnt;
>   	int		  r_readdir_cache_idx;
>   
> +	int		  r_feature_needed;
> +
>   	struct ceph_cap_reservation r_caps_reservation;
>   };
>   
> diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
> index b10d459c2326..5f29c1f08de1 100644
> --- a/fs/ceph/xattr.c
> +++ b/fs/ceph/xattr.c
> @@ -983,11 +983,7 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
>   		}
>   		return err;
>   	} else {
> -		err = ceph_do_getvxattr(inode, name, value, size);
> -		/* this would happen with a new client and old server combo */
> -		if (err == -EOPNOTSUPP)
> -			err = -ENODATA;
> -		return err;
> +		return ceph_do_getvxattr(inode, name, value, size);
>   	}
>   handle_non_vxattrs:
>   	req_mask = __get_request_mask(inode);
diff mbox series

Patch

diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 79ff197c7cc5..cfa0b550eef2 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2607,6 +2607,7 @@  int ceph_do_getvxattr(struct inode *inode, const char *name, void *value,
 		goto out;
 	}
 
+	req->r_feature_needed = CEPHFS_FEATURE_OP_GETVXATTR;
 	req->r_path2 = kstrdup(name, GFP_NOFS);
 	if (!req->r_path2) {
 		err = -ENOMEM;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 598012ddc401..e3683305445c 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2501,6 +2501,7 @@  ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 	INIT_LIST_HEAD(&req->r_unsafe_dir_item);
 	INIT_LIST_HEAD(&req->r_unsafe_target_item);
 	req->r_fmode = -1;
+	req->r_feature_needed = -1;
 	kref_init(&req->r_kref);
 	RB_CLEAR_NODE(&req->r_node);
 	INIT_LIST_HEAD(&req->r_wait);
@@ -3255,6 +3256,16 @@  static void __do_request(struct ceph_mds_client *mdsc,
 
 	dout("do_request mds%d session %p state %s\n", mds, session,
 	     ceph_session_state_name(session->s_state));
+
+	/*
+	 * The old ceph will crash the MDSs when see unknown OPs
+	 */
+	if (req->r_feature_needed > 0 &&
+	    !test_bit(req->r_feature_needed, &session->s_features)) {
+		err = -EOPNOTSUPP;
+		goto out_session;
+	}
+
 	if (session->s_state != CEPH_MDS_SESSION_OPEN &&
 	    session->s_state != CEPH_MDS_SESSION_HUNG) {
 		/*
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index e15ee2858fef..728b7d72bf76 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -31,8 +31,9 @@  enum ceph_feature_type {
 	CEPHFS_FEATURE_METRIC_COLLECT,
 	CEPHFS_FEATURE_ALTERNATE_NAME,
 	CEPHFS_FEATURE_NOTIFY_SESSION_STATE,
+	CEPHFS_FEATURE_OP_GETVXATTR,
 
-	CEPHFS_FEATURE_MAX = CEPHFS_FEATURE_NOTIFY_SESSION_STATE,
+	CEPHFS_FEATURE_MAX = CEPHFS_FEATURE_OP_GETVXATTR,
 };
 
 #define CEPHFS_FEATURES_CLIENT_SUPPORTED {	\
@@ -45,6 +46,7 @@  enum ceph_feature_type {
 	CEPHFS_FEATURE_METRIC_COLLECT,		\
 	CEPHFS_FEATURE_ALTERNATE_NAME,		\
 	CEPHFS_FEATURE_NOTIFY_SESSION_STATE,	\
+	CEPHFS_FEATURE_OP_GETVXATTR,		\
 }
 
 /*
@@ -352,6 +354,8 @@  struct ceph_mds_request {
 	long long	  r_dir_ordered_cnt;
 	int		  r_readdir_cache_idx;
 
+	int		  r_feature_needed;
+
 	struct ceph_cap_reservation r_caps_reservation;
 };
 
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index b10d459c2326..5f29c1f08de1 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -983,11 +983,7 @@  ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
 		}
 		return err;
 	} else {
-		err = ceph_do_getvxattr(inode, name, value, size);
-		/* this would happen with a new client and old server combo */
-		if (err == -EOPNOTSUPP)
-			err = -ENODATA;
-		return err;
+		return ceph_do_getvxattr(inode, name, value, size);
 	}
 handle_non_vxattrs:
 	req_mask = __get_request_mask(inode);