aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/mds_client.c48
-rw-r--r--fs/ceph/mds_client.h12
2 files changed, 51 insertions, 9 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 8dbfca01c7ea..5b767cf1f780 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -902,6 +902,27 @@ static struct ceph_msg *create_session_msg(u32 op, u64 seq)
902 return msg; 902 return msg;
903} 903}
904 904
905static void encode_supported_features(void **p, void *end)
906{
907 static const unsigned char bits[] = CEPHFS_FEATURES_CLIENT_SUPPORTED;
908 static const size_t count = ARRAY_SIZE(bits);
909
910 if (count > 0) {
911 size_t i;
912 size_t size = ((size_t)bits[count - 1] + 64) / 64 * 8;
913
914 BUG_ON(*p + 4 + size > end);
915 ceph_encode_32(p, size);
916 memset(*p, 0, size);
917 for (i = 0; i < count; i++)
918 ((unsigned char*)(*p))[i / 8] |= 1 << (bits[i] % 8);
919 *p += size;
920 } else {
921 BUG_ON(*p + 4 > end);
922 ceph_encode_32(p, 0);
923 }
924}
925
905/* 926/*
906 * session message, specialization for CEPH_SESSION_REQUEST_OPEN 927 * session message, specialization for CEPH_SESSION_REQUEST_OPEN
907 * to include additional client metadata fields. 928 * to include additional client metadata fields.
@@ -911,11 +932,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
911 struct ceph_msg *msg; 932 struct ceph_msg *msg;
912 struct ceph_mds_session_head *h; 933 struct ceph_mds_session_head *h;
913 int i = -1; 934 int i = -1;
914 int metadata_bytes = 0; 935 int extra_bytes = 0;
915 int metadata_key_count = 0; 936 int metadata_key_count = 0;
916 struct ceph_options *opt = mdsc->fsc->client->options; 937 struct ceph_options *opt = mdsc->fsc->client->options;
917 struct ceph_mount_options *fsopt = mdsc->fsc->mount_options; 938 struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
918 void *p; 939 void *p, *end;
919 940
920 const char* metadata[][2] = { 941 const char* metadata[][2] = {
921 {"hostname", mdsc->nodename}, 942 {"hostname", mdsc->nodename},
@@ -926,21 +947,26 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
926 }; 947 };
927 948
928 /* Calculate serialized length of metadata */ 949 /* Calculate serialized length of metadata */
929 metadata_bytes = 4; /* map length */ 950 extra_bytes = 4; /* map length */
930 for (i = 0; metadata[i][0]; ++i) { 951 for (i = 0; metadata[i][0]; ++i) {
931 metadata_bytes += 8 + strlen(metadata[i][0]) + 952 extra_bytes += 8 + strlen(metadata[i][0]) +
932 strlen(metadata[i][1]); 953 strlen(metadata[i][1]);
933 metadata_key_count++; 954 metadata_key_count++;
934 } 955 }
956 /* supported feature */
957 extra_bytes += 4 + 8;
935 958
936 /* Allocate the message */ 959 /* Allocate the message */
937 msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + metadata_bytes, 960 msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
938 GFP_NOFS, false); 961 GFP_NOFS, false);
939 if (!msg) { 962 if (!msg) {
940 pr_err("create_session_msg ENOMEM creating msg\n"); 963 pr_err("create_session_msg ENOMEM creating msg\n");
941 return NULL; 964 return NULL;
942 } 965 }
943 h = msg->front.iov_base; 966 p = msg->front.iov_base;
967 end = p + msg->front.iov_len;
968
969 h = p;
944 h->op = cpu_to_le32(CEPH_SESSION_REQUEST_OPEN); 970 h->op = cpu_to_le32(CEPH_SESSION_REQUEST_OPEN);
945 h->seq = cpu_to_le64(seq); 971 h->seq = cpu_to_le64(seq);
946 972
@@ -950,11 +976,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
950 * 976 *
951 * ClientSession messages with metadata are v2 977 * ClientSession messages with metadata are v2
952 */ 978 */
953 msg->hdr.version = cpu_to_le16(2); 979 msg->hdr.version = cpu_to_le16(3);
954 msg->hdr.compat_version = cpu_to_le16(1); 980 msg->hdr.compat_version = cpu_to_le16(1);
955 981
956 /* The write pointer, following the session_head structure */ 982 /* The write pointer, following the session_head structure */
957 p = msg->front.iov_base + sizeof(*h); 983 p += sizeof(*h);
958 984
959 /* Number of entries in the map */ 985 /* Number of entries in the map */
960 ceph_encode_32(&p, metadata_key_count); 986 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
972 p += val_len; 998 p += val_len;
973 } 999 }
974 1000
1001 encode_supported_features(&p, end);
1002 msg->front.iov_len = p - msg->front.iov_base;
1003 msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
1004
975 return msg; 1005 return msg;
976} 1006}
977 1007
@@ -2749,7 +2779,7 @@ static void handle_session(struct ceph_mds_session *session,
2749 int wake = 0; 2779 int wake = 0;
2750 2780
2751 /* decode */ 2781 /* decode */
2752 if (msg->front.iov_len != sizeof(*h)) 2782 if (msg->front.iov_len < sizeof(*h))
2753 goto bad; 2783 goto bad;
2754 op = le32_to_cpu(h->op); 2784 op = le32_to_cpu(h->op);
2755 seq = le64_to_cpu(h->seq); 2785 seq = le64_to_cpu(h->seq);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 80a7523e1523..32fcce0d4d3c 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -16,6 +16,18 @@
16#include <linux/ceph/mdsmap.h> 16#include <linux/ceph/mdsmap.h>
17#include <linux/ceph/auth.h> 17#include <linux/ceph/auth.h>
18 18
19/* The first 8 bits are reserved for old ceph releases */
20#define CEPHFS_FEATURE_MIMIC 8
21
22#define CEPHFS_FEATURES_ALL { \
23 0, 1, 2, 3, 4, 5, 6, 7, \
24 CEPHFS_FEATURE_MIMIC, \
25}
26
27#define CEPHFS_FEATURES_CLIENT_SUPPORTED CEPHFS_FEATURES_ALL
28#define CEPHFS_FEATURES_CLIENT_REQUIRED {}
29
30
19/* 31/*
20 * Some lock dependencies: 32 * Some lock dependencies:
21 * 33 *