From: Xiubo Li <xiubli@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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(-) 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); -- 2.36.0.rc1