ceph: fail the request if the peer MDS doesn't support getvxattr op
authorXiubo Li <xiubli@redhat.com>
Wed, 27 Jul 2022 04:29:10 +0000 (12:29 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 4 Oct 2022 17:18:08 +0000 (19:18 +0200)
Just fail the request instead sending the request out, or the peer
MDS will crash.

Link: https://tracker.ceph.com/issues/56529
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h

index 42351d7..b4a3cb0 100644 (file)
@@ -2356,6 +2356,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;
index 80f8b9e..26a0a8b 100644 (file)
@@ -2318,6 +2318,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);
@@ -2916,6 +2917,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) {
                /*
index 256e3ea..0598faa 100644 (file)
@@ -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 {     \
@@ -44,6 +45,7 @@ enum ceph_feature_type {
        CEPHFS_FEATURE_DELEG_INO,               \
        CEPHFS_FEATURE_METRIC_COLLECT,          \
        CEPHFS_FEATURE_NOTIFY_SESSION_STATE,    \
+       CEPHFS_FEATURE_OP_GETVXATTR,            \
 }
 
 /*
@@ -336,6 +338,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;
 };