diff mbox series

ceph: fall back to use old method to get xattr

Message ID 20220727055637.11949-1-xiubli@redhat.com
State New
Headers show
Series ceph: fall back to use old method to get xattr | expand

Commit Message

Xiubo Li July 27, 2022, 5:56 a.m. UTC
From: Xiubo Li <xiubli@redhat.com>

If the peer MDS doesn't support getvxattr op then just fall back to
use old getattr method to get it. Or for the old MDSs they will crash
when receive an unknown op.

URL: https://tracker.ceph.com/issues/56529
Signed-off-by: Xiubo Li <xiubli@redhat.com>
---
 fs/ceph/mds_client.c | 10 ++++++++++
 fs/ceph/mds_client.h |  4 +++-
 fs/ceph/xattr.c      |  9 ++++++---
 3 files changed, 19 insertions(+), 4 deletions(-)

Comments

Xiubo Li July 27, 2022, 9:41 a.m. UTC | #1
On 7/27/22 5:05 PM, Luís Henriques wrote:
> On Wed, Jul 27, 2022 at 01:56:37PM +0800, xiubli@redhat.com wrote:
>> From: Xiubo Li <xiubli@redhat.com>
>>
>> If the peer MDS doesn't support getvxattr op then just fall back to
>> use old getattr method to get it. Or for the old MDSs they will crash
>> when receive an unknown op.
>>
>> URL: https://tracker.ceph.com/issues/56529
>> Signed-off-by: Xiubo Li <xiubli@redhat.com>
>> ---
>>   fs/ceph/mds_client.c | 10 ++++++++++
>>   fs/ceph/mds_client.h |  4 +++-
>>   fs/ceph/xattr.c      |  9 ++++++---
>>   3 files changed, 19 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>> index 598012ddc401..bfe6d6393eba 100644
>> --- a/fs/ceph/mds_client.c
>> +++ b/fs/ceph/mds_client.c
>> @@ -3255,6 +3255,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_op == CEPH_MDS_OP_GETVXATTR &&
>> +	    !test_bit(CEPHFS_FEATURE_OP_GETVXATTR, &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..0e03efab872a 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,		\
>>   }
>>   
>>   /*
>> diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
>> index b10d459c2326..8f8db621772a 100644
>> --- a/fs/ceph/xattr.c
>> +++ b/fs/ceph/xattr.c
>> @@ -984,9 +984,12 @@ 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 */
>> +		/*
>> +		 * This would happen with a new client and old server combo,
>> +		 * then fall back to use old method to get it
>> +		 */
>>   		if (err == -EOPNOTSUPP)
>> -			err = -ENODATA;
>> +			goto handle_non_vxattrs;
>>   		return err;
> Nit: maybe just do:
>
> 		if (err != -EOPNOTSUPP)
> 			return err
>
> instead of using a 'goto' statement.

Sounds better.

>>   	}
>>   handle_non_vxattrs:
>> @@ -996,7 +999,7 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
>>   	dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
>>   	     ci->i_xattrs.version, ci->i_xattrs.index_version);
>>   
>> -	if (ci->i_xattrs.version == 0 ||
>> +	if (ci->i_xattrs.version == 0 || err == -EOPNOTSUPP ||
> You'll need to initialise 'err' when declaring it.

Yeah, will fix it.

Thanks Luis!

-- Xiubo

>
> Cheers,
> --
> Luís
>
>>   	    !((req_mask & CEPH_CAP_XATTR_SHARED) ||
>>   	      __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) {
>>   		spin_unlock(&ci->i_ceph_lock);
>> -- 
>> 2.36.0.rc1
>>
diff mbox series

Patch

diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 598012ddc401..bfe6d6393eba 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3255,6 +3255,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_op == CEPH_MDS_OP_GETVXATTR &&
+	    !test_bit(CEPHFS_FEATURE_OP_GETVXATTR, &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..0e03efab872a 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,		\
 }
 
 /*
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index b10d459c2326..8f8db621772a 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -984,9 +984,12 @@  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 */
+		/*
+		 * This would happen with a new client and old server combo,
+		 * then fall back to use old method to get it
+		 */
 		if (err == -EOPNOTSUPP)
-			err = -ENODATA;
+			goto handle_non_vxattrs;
 		return err;
 	}
 handle_non_vxattrs:
@@ -996,7 +999,7 @@  ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
 	dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
 	     ci->i_xattrs.version, ci->i_xattrs.index_version);
 
-	if (ci->i_xattrs.version == 0 ||
+	if (ci->i_xattrs.version == 0 || err == -EOPNOTSUPP ||
 	    !((req_mask & CEPH_CAP_XATTR_SHARED) ||
 	      __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) {
 		spin_unlock(&ci->i_ceph_lock);