Skip to content

Commit

Permalink
ceph: allocate the correct amount of extra bytes for the session feat…
Browse files Browse the repository at this point in the history
…ures

The total bytes may potentially be larger than 8.

Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
  • Loading branch information
Xiubo Li authored and Ilya Dryomov committed Jan 27, 2020
1 parent 5b3248c commit 9ba1e22
Showing 2 changed files with 30 additions and 13 deletions.
20 changes: 14 additions & 6 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/ratelimit.h>
#include <linux/bits.h>

#include "super.h"
#include "mds_client.h"
@@ -1057,20 +1058,21 @@ static struct ceph_msg *create_session_msg(u32 op, u64 seq)
return msg;
}

static const unsigned char feature_bits[] = CEPHFS_FEATURES_CLIENT_SUPPORTED;
#define FEATURE_BYTES(c) (DIV_ROUND_UP((size_t)feature_bits[c - 1] + 1, 64) * 8)
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);
static const size_t count = ARRAY_SIZE(feature_bits);

if (count > 0) {
size_t i;
size_t size = ((size_t)bits[count - 1] + 64) / 64 * 8;
size_t size = FEATURE_BYTES(count);

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);
((unsigned char*)(*p))[i / 8] |= BIT(feature_bits[i] % 8);
*p += size;
} else {
BUG_ON(*p + 4 > end);
@@ -1091,6 +1093,7 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
int metadata_key_count = 0;
struct ceph_options *opt = mdsc->fsc->client->options;
struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
size_t size, count;
void *p, *end;

const char* metadata[][2] = {
@@ -1108,8 +1111,13 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
strlen(metadata[i][1]);
metadata_key_count++;
}

/* supported feature */
extra_bytes += 4 + 8;
size = 0;
count = ARRAY_SIZE(feature_bits);
if (count > 0)
size = FEATURE_BYTES(count);
extra_bytes += 4 + size;

/* Allocate the message */
msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
@@ -1129,7 +1137,7 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
* Serialize client metadata into waiting buffer space, using
* the format that userspace expects for map<string, string>
*
* ClientSession messages with metadata are v2
* ClientSession messages with metadata are v3
*/
msg->hdr.version = cpu_to_le16(3);
msg->hdr.compat_version = cpu_to_le16(1);
23 changes: 16 additions & 7 deletions fs/ceph/mds_client.h
Original file line number Diff line number Diff line change
@@ -17,22 +17,31 @@
#include <linux/ceph/auth.h>

/* The first 8 bits are reserved for old ceph releases */
#define CEPHFS_FEATURE_MIMIC 8
#define CEPHFS_FEATURE_REPLY_ENCODING 9
#define CEPHFS_FEATURE_RECLAIM_CLIENT 10
#define CEPHFS_FEATURE_LAZY_CAP_WANTED 11
#define CEPHFS_FEATURE_MULTI_RECONNECT 12
enum ceph_feature_type {
CEPHFS_FEATURE_MIMIC = 8,
CEPHFS_FEATURE_REPLY_ENCODING,
CEPHFS_FEATURE_RECLAIM_CLIENT,
CEPHFS_FEATURE_LAZY_CAP_WANTED,
CEPHFS_FEATURE_MULTI_RECONNECT,

CEPHFS_FEATURE_MAX = CEPHFS_FEATURE_MULTI_RECONNECT,
};

#define CEPHFS_FEATURES_CLIENT_SUPPORTED { \
/*
* This will always have the highest feature bit value
* as the last element of the array.
*/
#define CEPHFS_FEATURES_CLIENT_SUPPORTED { \
0, 1, 2, 3, 4, 5, 6, 7, \
CEPHFS_FEATURE_MIMIC, \
CEPHFS_FEATURE_REPLY_ENCODING, \
CEPHFS_FEATURE_LAZY_CAP_WANTED, \
CEPHFS_FEATURE_MULTI_RECONNECT, \
\
CEPHFS_FEATURE_MAX, \
}
#define CEPHFS_FEATURES_CLIENT_REQUIRED {}


/*
* Some lock dependencies:
*

0 comments on commit 9ba1e22

Please sign in to comment.