Merge tag 'acpi-4.19-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6-block.git] / fs / ceph / mds_client.c
index dc8bc664a8716a5c946c70efa2dc5911cfb32962..bc43c822426a27673eb19754dabc282d182bfc12 100644 (file)
@@ -902,6 +902,27 @@ static struct ceph_msg *create_session_msg(u32 op, u64 seq)
        return msg;
 }
 
+static void encode_supported_features(void **p, void *end)
+{
+       static const unsigned char bits[] = CEPHFS_FEATURES_CLIENT_SUPPORTED;
+       static const size_t count = ARRAY_SIZE(bits);
+
+       if (count > 0) {
+               size_t i;
+               size_t size = ((size_t)bits[count - 1] + 64) / 64 * 8;
+
+               BUG_ON(*p + 4 + size > end);
+               ceph_encode_32(p, size);
+               memset(*p, 0, size);
+               for (i = 0; i < count; i++)
+                       ((unsigned char*)(*p))[i / 8] |= 1 << (bits[i] % 8);
+               *p += size;
+       } else {
+               BUG_ON(*p + 4 > end);
+               ceph_encode_32(p, 0);
+       }
+}
+
 /*
  * session message, specialization for CEPH_SESSION_REQUEST_OPEN
  * to include additional client metadata fields.
@@ -911,11 +932,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
        struct ceph_msg *msg;
        struct ceph_mds_session_head *h;
        int i = -1;
-       int metadata_bytes = 0;
+       int extra_bytes = 0;
        int metadata_key_count = 0;
        struct ceph_options *opt = mdsc->fsc->client->options;
        struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
-       void *p;
+       void *p, *end;
 
        const char* metadata[][2] = {
                {"hostname", mdsc->nodename},
@@ -926,21 +947,26 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
        };
 
        /* Calculate serialized length of metadata */
-       metadata_bytes = 4;  /* map length */
+       extra_bytes = 4;  /* map length */
        for (i = 0; metadata[i][0]; ++i) {
-               metadata_bytes += 8 + strlen(metadata[i][0]) +
+               extra_bytes += 8 + strlen(metadata[i][0]) +
                        strlen(metadata[i][1]);
                metadata_key_count++;
        }
+       /* supported feature */
+       extra_bytes += 4 + 8;
 
        /* Allocate the message */
-       msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + metadata_bytes,
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
                           GFP_NOFS, false);
        if (!msg) {
                pr_err("create_session_msg ENOMEM creating msg\n");
                return NULL;
        }
-       h = msg->front.iov_base;
+       p = msg->front.iov_base;
+       end = p + msg->front.iov_len;
+
+       h = p;
        h->op = cpu_to_le32(CEPH_SESSION_REQUEST_OPEN);
        h->seq = cpu_to_le64(seq);
 
@@ -950,11 +976,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
         *
         * ClientSession messages with metadata are v2
         */
-       msg->hdr.version = cpu_to_le16(2);
+       msg->hdr.version = cpu_to_le16(3);
        msg->hdr.compat_version = cpu_to_le16(1);
 
        /* The write pointer, following the session_head structure */
-       p = msg->front.iov_base + sizeof(*h);
+       p += sizeof(*h);
 
        /* Number of entries in the map */
        ceph_encode_32(&p, metadata_key_count);
@@ -972,6 +998,10 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
                p += val_len;
        }
 
+       encode_supported_features(&p, end);
+       msg->front.iov_len = p - msg->front.iov_base;
+       msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
+
        return msg;
 }
 
@@ -1779,6 +1809,7 @@ struct ceph_mds_request *
 ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 {
        struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
+       struct timespec64 ts;
 
        if (!req)
                return ERR_PTR(-ENOMEM);
@@ -1797,7 +1828,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
        init_completion(&req->r_safe_completion);
        INIT_LIST_HEAD(&req->r_unsafe_item);
 
-       req->r_stamp = timespec_trunc(current_kernel_time(), mdsc->fsc->sb->s_time_gran);
+       ktime_get_coarse_real_ts64(&ts);
+       req->r_stamp = timespec64_trunc(ts, mdsc->fsc->sb->s_time_gran);
 
        req->r_op = op;
        req->r_direct_mode = mode;
@@ -2094,7 +2126,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
        /* time stamp */
        {
                struct ceph_timespec ts;
-               ceph_encode_timespec(&ts, &req->r_stamp);
+               ceph_encode_timespec64(&ts, &req->r_stamp);
                ceph_encode_copy(&p, &ts, sizeof(ts));
        }
 
@@ -2187,7 +2219,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
                p = msg->front.iov_base + req->r_request_release_offset;
                {
                        struct ceph_timespec ts;
-                       ceph_encode_timespec(&ts, &req->r_stamp);
+                       ceph_encode_timespec64(&ts, &req->r_stamp);
                        ceph_encode_copy(&p, &ts, sizeof(ts));
                }
 
@@ -2225,7 +2257,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
 /*
  * send request, or put it on the appropriate wait list.
  */
-static int __do_request(struct ceph_mds_client *mdsc,
+static void __do_request(struct ceph_mds_client *mdsc,
                        struct ceph_mds_request *req)
 {
        struct ceph_mds_session *session = NULL;
@@ -2235,7 +2267,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
        if (req->r_err || test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
                if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags))
                        __unregister_request(mdsc, req);
-               goto out;
+               return;
        }
 
        if (req->r_timeout &&
@@ -2258,7 +2290,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
                if (mdsc->mdsmap->m_epoch == 0) {
                        dout("do_request no mdsmap, waiting for map\n");
                        list_add(&req->r_wait, &mdsc->waiting_for_map);
-                       goto finish;
+                       return;
                }
                if (!(mdsc->fsc->mount_options->flags &
                      CEPH_MOUNT_OPT_MOUNTWAIT) &&
@@ -2276,7 +2308,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
            ceph_mdsmap_get_state(mdsc->mdsmap, mds) < CEPH_MDS_STATE_ACTIVE) {
                dout("do_request no mds or not active, waiting for map\n");
                list_add(&req->r_wait, &mdsc->waiting_for_map);
-               goto out;
+               return;
        }
 
        /* get, open session */
@@ -2326,8 +2358,7 @@ finish:
                complete_request(mdsc, req);
                __unregister_request(mdsc, req);
        }
-out:
-       return err;
+       return;
 }
 
 /*
@@ -2748,7 +2779,7 @@ static void handle_session(struct ceph_mds_session *session,
        int wake = 0;
 
        /* decode */
-       if (msg->front.iov_len != sizeof(*h))
+       if (msg->front.iov_len < sizeof(*h))
                goto bad;
        op = le32_to_cpu(h->op);
        seq = le64_to_cpu(h->seq);
@@ -2958,15 +2989,12 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
                rec.v2.flock_len = (__force __le32)
                        ((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
        } else {
-               struct timespec ts;
                rec.v1.cap_id = cpu_to_le64(cap->cap_id);
                rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
                rec.v1.issued = cpu_to_le32(cap->issued);
                rec.v1.size = cpu_to_le64(inode->i_size);
-               ts = timespec64_to_timespec(inode->i_mtime);
-               ceph_encode_timespec(&rec.v1.mtime, &ts);
-               ts = timespec64_to_timespec(inode->i_atime);
-               ceph_encode_timespec(&rec.v1.atime, &ts);
+               ceph_encode_timespec64(&rec.v1.mtime, &inode->i_mtime);
+               ceph_encode_timespec64(&rec.v1.atime, &inode->i_atime);
                rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
                rec.v1.pathbase = cpu_to_le64(pathbase);
        }
@@ -3378,10 +3406,10 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        vino.ino = le64_to_cpu(h->ino);
        vino.snap = CEPH_NOSNAP;
        seq = le32_to_cpu(h->seq);
-       dname.name = (void *)h + sizeof(*h) + sizeof(u32);
-       dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
-       if (dname.len != get_unaligned_le32(h+1))
+       dname.len = get_unaligned_le32(h + 1);
+       if (msg->front.iov_len < sizeof(*h) + sizeof(u32) + dname.len)
                goto bad;
+       dname.name = (void *)(h + 1) + sizeof(u32);
 
        /* lookup inode */
        inode = ceph_find_inode(sb, vino);
@@ -3644,8 +3672,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        init_rwsem(&mdsc->pool_perm_rwsem);
        mdsc->pool_perm_tree = RB_ROOT;
 
-       strncpy(mdsc->nodename, utsname()->nodename,
-               sizeof(mdsc->nodename) - 1);
+       strscpy(mdsc->nodename, utsname()->nodename,
+               sizeof(mdsc->nodename));
        return 0;
 }
 
@@ -4019,7 +4047,8 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
        } else {
                mdsc->mdsmap = newmap;  /* first mds map */
        }
-       mdsc->fsc->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
+       mdsc->fsc->max_file_size = min((loff_t)mdsc->mdsmap->m_max_file_size,
+                                       MAX_LFS_FILESIZE);
 
        __wake_requests(mdsc, &mdsc->waiting_for_map);
        ceph_monc_got_map(&mdsc->fsc->client->monc, CEPH_SUB_MDSMAP,
@@ -4155,6 +4184,16 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
        return auth;
 }
 
+static int add_authorizer_challenge(struct ceph_connection *con,
+                                   void *challenge_buf, int challenge_buf_len)
+{
+       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_client *mdsc = s->s_mdsc;
+       struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
+
+       return ceph_auth_add_authorizer_challenge(ac, s->s_auth.authorizer,
+                                           challenge_buf, challenge_buf_len);
+}
 
 static int verify_authorizer_reply(struct ceph_connection *con)
 {
@@ -4218,6 +4257,7 @@ static const struct ceph_connection_operations mds_con_ops = {
        .put = con_put,
        .dispatch = dispatch,
        .get_authorizer = get_authorizer,
+       .add_authorizer_challenge = add_authorizer_challenge,
        .verify_authorizer_reply = verify_authorizer_reply,
        .invalidate_authorizer = invalidate_authorizer,
        .peer_reset = peer_reset,