]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ceph: save the cap_auths in client when session being opened
authorXiubo Li <xiubli@redhat.com>
Mon, 25 Sep 2023 08:25:20 +0000 (16:25 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 13 Feb 2024 10:25:12 +0000 (11:25 +0100)
Save the cap_auths, which have been parsed by the MDS, in the opened
session.

URL: https://tracker.ceph.com/issues/61333
Signed-off-by: Xiubo Li <xiubli@redhat.com>
fs/ceph/mds_client.c
fs/ceph/mds_client.h

index 968918bcefddac9d0481a5061a145cd313000b81..b715ccfff419ae12a8bf47120e600702ab699c74 100644 (file)
@@ -4140,10 +4140,13 @@ static void handle_session(struct ceph_mds_session *session,
        void *p = msg->front.iov_base;
        void *end = p + msg->front.iov_len;
        struct ceph_mds_session_head *h;
-       u32 op;
+       struct ceph_mds_cap_auth *cap_auths = NULL;
+       u32 op, cap_auths_num = 0;
        u64 seq, features = 0;
        int wake = 0;
        bool blocklisted = false;
+       u32 i;
+
 
        /* decode */
        ceph_decode_need(&p, end, sizeof(*h), bad);
@@ -4188,7 +4191,103 @@ static void handle_session(struct ceph_mds_session *session,
                }
        }
 
+       if (msg_version >= 6) {
+               ceph_decode_32_safe(&p, end, cap_auths_num, bad);
+               doutc(cl, "cap_auths_num %d\n", cap_auths_num);
+
+               if (cap_auths_num && op != CEPH_SESSION_OPEN) {
+                       WARN_ON_ONCE(op != CEPH_SESSION_OPEN);
+                       goto skip_cap_auths;
+               }
+
+               cap_auths = kcalloc(cap_auths_num,
+                                   sizeof(struct ceph_mds_cap_auth),
+                                   GFP_KERNEL);
+               if (!cap_auths) {
+                       pr_err_client(cl, "No memory for cap_auths\n");
+                       return;
+               }
+
+               for (i = 0; i < cap_auths_num; i++) {
+                       u32 _len, j;
+
+                       /* struct_v, struct_compat, and struct_len in MDSCapAuth */
+                       ceph_decode_skip_n(&p, end, 2 + sizeof(u32), bad);
+
+                       /* struct_v, struct_compat, and struct_len in MDSCapMatch */
+                       ceph_decode_skip_n(&p, end, 2 + sizeof(u32), bad);
+                       ceph_decode_64_safe(&p, end, cap_auths[i].match.uid, bad);
+                       ceph_decode_32_safe(&p, end, _len, bad);
+                       if (_len) {
+                               cap_auths[i].match.gids = kcalloc(_len, sizeof(int64_t),
+                                                                 GFP_KERNEL);
+                               if (!cap_auths[i].match.gids) {
+                                       pr_err_client(cl, "No memory for gids\n");
+                                       goto fail;
+                               }
+
+                               cap_auths[i].match.num_gids = _len;
+                               for (j = 0; j < _len; j++)
+                                       ceph_decode_64_safe(&p, end,
+                                                           cap_auths[i].match.gids[j],
+                                                           bad);
+                       }
+
+                       ceph_decode_32_safe(&p, end, _len, bad);
+                       if (_len) {
+                               cap_auths[i].match.path = kcalloc(_len + 1, sizeof(char),
+                                                                 GFP_KERNEL);
+                               if (!cap_auths[i].match.path) {
+                                       pr_err_client(cl, "No memory for path\n");
+                                       goto fail;
+                               }
+                               ceph_decode_copy(&p, cap_auths[i].match.path, _len);
+
+                               /* Remove the tailing '/' */
+                               while (_len && cap_auths[i].match.path[_len - 1] == '/') {
+                                       cap_auths[i].match.path[_len - 1] = '\0';
+                                       _len -= 1;
+                               }
+                       }
+
+                       ceph_decode_32_safe(&p, end, _len, bad);
+                       if (_len) {
+                               cap_auths[i].match.fs_name = kcalloc(_len + 1, sizeof(char),
+                                                                    GFP_KERNEL);
+                               if (!cap_auths[i].match.fs_name) {
+                                       pr_err_client(cl, "No memory for fs_name\n");
+                                       goto fail;
+                               }
+                               ceph_decode_copy(&p, cap_auths[i].match.fs_name, _len);
+                       }
+
+                       ceph_decode_8_safe(&p, end, cap_auths[i].match.root_squash, bad);
+                       ceph_decode_8_safe(&p, end, cap_auths[i].readable, bad);
+                       ceph_decode_8_safe(&p, end, cap_auths[i].writeable, bad);
+                       doutc(cl, "uid %lld, num_gids %d, path %s, fs_name %s,"
+                             " root_squash %d, readable %d, writeable %d\n",
+                             cap_auths[i].match.uid, cap_auths[i].match.num_gids,
+                             cap_auths[i].match.path, cap_auths[i].match.fs_name,
+                             cap_auths[i].match.root_squash,
+                             cap_auths[i].readable, cap_auths[i].writeable);
+               }
+
+       }
+
+skip_cap_auths:
        mutex_lock(&mdsc->mutex);
+       if (op == CEPH_SESSION_OPEN) {
+               if (mdsc->s_cap_auths) {
+                       for (i = 0; i < mdsc->s_cap_auths_num; i++) {
+                               kfree(mdsc->s_cap_auths[i].match.gids);
+                               kfree(mdsc->s_cap_auths[i].match.path);
+                               kfree(mdsc->s_cap_auths[i].match.fs_name);
+                       }
+                       kfree(mdsc->s_cap_auths);
+               }
+               mdsc->s_cap_auths_num = cap_auths_num;
+               mdsc->s_cap_auths = cap_auths;
+       }
        if (op == CEPH_SESSION_CLOSE) {
                ceph_get_mds_session(session);
                __unregister_session(mdsc, session);
@@ -4318,6 +4417,13 @@ bad:
        pr_err_client(cl, "corrupt message mds%d len %d\n", mds,
                      (int)msg->front.iov_len);
        ceph_msg_dump(msg);
+fail:
+       for (i = 0; i < cap_auths_num; i++) {
+               kfree(cap_auths[i].match.gids);
+               kfree(cap_auths[i].match.path);
+               kfree(cap_auths[i].match.fs_name);
+       }
+       kfree(cap_auths);
        return;
 }
 
index 03f8ff00874f727adff8b88cc8d538fc989692d8..b98aadac480e9729688a5e2dde3ca9a90c7850bf 100644 (file)
@@ -71,6 +71,24 @@ enum ceph_feature_type {
 struct ceph_fs_client;
 struct ceph_cap;
 
+#define MDS_AUTH_UID_ANY -1
+
+struct ceph_mds_cap_match {
+       int64_t uid; // MDS_AUTH_UID_ANY as default
+       uint32_t num_gids;
+       int64_t *gids;  // Use these GIDs
+       char *path;  // Require path to be child of this (may be "" or "/" for any)
+       char *fs_name;
+       u8 root_squash; // False as default
+};
+
+struct ceph_mds_cap_auth {
+       struct ceph_mds_cap_match match;
+       u8 readable;
+       u8 writeable;
+};
+
+
 /*
  * parsed info about a single inode.  pointers are into the encoded
  * on-wire structures within the mds reply message payload.
@@ -514,6 +532,9 @@ struct ceph_mds_client {
        struct rw_semaphore     pool_perm_rwsem;
        struct rb_root          pool_perm_tree;
 
+       u32                      s_cap_auths_num;
+       struct ceph_mds_cap_auth *s_cap_auths;
+
        char nodename[__NEW_UTS_LEN + 1];
 };