aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-12-23 12:30:21 -0500
committerSage Weil <sage@newdream.net>2009-12-23 12:30:21 -0500
commit04a419f908b5291ff7e8ffd7aa351fa0ac0c08af (patch)
tree2e634bdca766c27b88280ab5c1ce067f47ffe536
parent6df058c025ce343052c5516b1d8a9a7e73cddd64 (diff)
ceph: add feature bits to connection handshake (protocol change)
Define supported and required feature set. Fail connection if the server requires features we do not support (TAG_FEATURES), or if the server does not support features we require. Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/ceph_fs.h6
-rw-r--r--fs/ceph/dir.c12
-rw-r--r--fs/ceph/messenger.c47
-rw-r--r--fs/ceph/msgr.h5
4 files changed, 53 insertions, 17 deletions
diff --git a/fs/ceph/ceph_fs.h b/fs/ceph/ceph_fs.h
index e87dfa6ec8e5..db3fed33c4aa 100644
--- a/fs/ceph/ceph_fs.h
+++ b/fs/ceph/ceph_fs.h
@@ -50,6 +50,12 @@
50#define CEPH_MAX_MON 31 50#define CEPH_MAX_MON 31
51 51
52 52
53/*
54 * feature bits
55 */
56#define CEPH_FEATURE_SUPPORTED 0
57#define CEPH_FEATURE_REQUIRED 0
58
53 59
54/* 60/*
55 * ceph_file_layout - describe data layout for a file/inode 61 * ceph_file_layout - describe data layout for a file/inode
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index fde839c61236..5107384ee029 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1135,9 +1135,9 @@ void ceph_dentry_lru_add(struct dentry *dn)
1135{ 1135{
1136 struct ceph_dentry_info *di = ceph_dentry(dn); 1136 struct ceph_dentry_info *di = ceph_dentry(dn);
1137 struct ceph_mds_client *mdsc; 1137 struct ceph_mds_client *mdsc;
1138 dout("dentry_lru_add %p %p\t%.*s\n",
1139 di, dn, dn->d_name.len, dn->d_name.name);
1140 1138
1139 dout("dentry_lru_add %p %p '%.*s'\n", di, dn,
1140 dn->d_name.len, dn->d_name.name);
1141 if (di) { 1141 if (di) {
1142 mdsc = &ceph_client(dn->d_sb)->mdsc; 1142 mdsc = &ceph_client(dn->d_sb)->mdsc;
1143 spin_lock(&mdsc->dentry_lru_lock); 1143 spin_lock(&mdsc->dentry_lru_lock);
@@ -1151,9 +1151,9 @@ void ceph_dentry_lru_touch(struct dentry *dn)
1151{ 1151{
1152 struct ceph_dentry_info *di = ceph_dentry(dn); 1152 struct ceph_dentry_info *di = ceph_dentry(dn);
1153 struct ceph_mds_client *mdsc; 1153 struct ceph_mds_client *mdsc;
1154 dout("dentry_lru_touch %p %p\t%.*s\n",
1155 di, dn, dn->d_name.len, dn->d_name.name);
1156 1154
1155 dout("dentry_lru_touch %p %p '%.*s'\n", di, dn,
1156 dn->d_name.len, dn->d_name.name);
1157 if (di) { 1157 if (di) {
1158 mdsc = &ceph_client(dn->d_sb)->mdsc; 1158 mdsc = &ceph_client(dn->d_sb)->mdsc;
1159 spin_lock(&mdsc->dentry_lru_lock); 1159 spin_lock(&mdsc->dentry_lru_lock);
@@ -1167,8 +1167,8 @@ void ceph_dentry_lru_del(struct dentry *dn)
1167 struct ceph_dentry_info *di = ceph_dentry(dn); 1167 struct ceph_dentry_info *di = ceph_dentry(dn);
1168 struct ceph_mds_client *mdsc; 1168 struct ceph_mds_client *mdsc;
1169 1169
1170 dout("dentry_lru_del %p %p\t%.*s\n", 1170 dout("dentry_lru_del %p %p '%.*s'\n", di, dn,
1171 di, dn, dn->d_name.len, dn->d_name.name); 1171 dn->d_name.len, dn->d_name.name);
1172 if (di) { 1172 if (di) {
1173 mdsc = &ceph_client(dn->d_sb)->mdsc; 1173 mdsc = &ceph_client(dn->d_sb)->mdsc;
1174 spin_lock(&mdsc->dentry_lru_lock); 1174 spin_lock(&mdsc->dentry_lru_lock);
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index 506b638a023b..68052f664280 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -631,6 +631,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
631 dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, 631 dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
632 con->connect_seq, global_seq, proto); 632 con->connect_seq, global_seq, proto);
633 633
634 con->out_connect.features = CEPH_FEATURE_SUPPORTED;
634 con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); 635 con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
635 con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); 636 con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
636 con->out_connect.global_seq = cpu_to_le32(global_seq); 637 con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -1080,15 +1081,37 @@ static int process_banner(struct ceph_connection *con)
1080 return 0; 1081 return 0;
1081} 1082}
1082 1083
1084static void fail_protocol(struct ceph_connection *con)
1085{
1086 reset_connection(con);
1087 set_bit(CLOSED, &con->state); /* in case there's queued work */
1088
1089 mutex_unlock(&con->mutex);
1090 if (con->ops->bad_proto)
1091 con->ops->bad_proto(con);
1092 mutex_lock(&con->mutex);
1093}
1094
1083static int process_connect(struct ceph_connection *con) 1095static int process_connect(struct ceph_connection *con)
1084{ 1096{
1097 u64 sup_feat = CEPH_FEATURE_SUPPORTED;
1098 u64 req_feat = CEPH_FEATURE_REQUIRED;
1099 u64 server_feat = le64_to_cpu(con->in_reply.features);
1100
1085 dout("process_connect on %p tag %d\n", con, (int)con->in_tag); 1101 dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
1086 1102
1087 switch (con->in_reply.tag) { 1103 switch (con->in_reply.tag) {
1104 case CEPH_MSGR_TAG_FEATURES:
1105 pr_err("%s%lld %s feature set mismatch,"
1106 " my %llx < server's %llx, missing %llx\n",
1107 ENTITY_NAME(con->peer_name),
1108 pr_addr(&con->peer_addr.in_addr),
1109 sup_feat, server_feat, server_feat & ~sup_feat);
1110 con->error_msg = "missing required protocol features";
1111 fail_protocol(con);
1112 return -1;
1113
1088 case CEPH_MSGR_TAG_BADPROTOVER: 1114 case CEPH_MSGR_TAG_BADPROTOVER:
1089 dout("process_connect got BADPROTOVER my %d != their %d\n",
1090 le32_to_cpu(con->out_connect.protocol_version),
1091 le32_to_cpu(con->in_reply.protocol_version));
1092 pr_err("%s%lld %s protocol version mismatch," 1115 pr_err("%s%lld %s protocol version mismatch,"
1093 " my %d != server's %d\n", 1116 " my %d != server's %d\n",
1094 ENTITY_NAME(con->peer_name), 1117 ENTITY_NAME(con->peer_name),
@@ -1096,13 +1119,7 @@ static int process_connect(struct ceph_connection *con)
1096 le32_to_cpu(con->out_connect.protocol_version), 1119 le32_to_cpu(con->out_connect.protocol_version),
1097 le32_to_cpu(con->in_reply.protocol_version)); 1120 le32_to_cpu(con->in_reply.protocol_version));
1098 con->error_msg = "protocol version mismatch"; 1121 con->error_msg = "protocol version mismatch";
1099 reset_connection(con); 1122 fail_protocol(con);
1100 set_bit(CLOSED, &con->state); /* in case there's queued work */
1101
1102 mutex_unlock(&con->mutex);
1103 if (con->ops->bad_proto)
1104 con->ops->bad_proto(con);
1105 mutex_lock(&con->mutex);
1106 return -1; 1123 return -1;
1107 1124
1108 case CEPH_MSGR_TAG_BADAUTHORIZER: 1125 case CEPH_MSGR_TAG_BADAUTHORIZER:
@@ -1173,6 +1190,16 @@ static int process_connect(struct ceph_connection *con)
1173 break; 1190 break;
1174 1191
1175 case CEPH_MSGR_TAG_READY: 1192 case CEPH_MSGR_TAG_READY:
1193 if (req_feat & ~server_feat) {
1194 pr_err("%s%lld %s protocol feature mismatch,"
1195 " my required %llx > server's %llx, need %llx\n",
1196 ENTITY_NAME(con->peer_name),
1197 pr_addr(&con->peer_addr.in_addr),
1198 req_feat, server_feat, req_feat & ~server_feat);
1199 con->error_msg = "missing required protocol features";
1200 fail_protocol(con);
1201 return -1;
1202 }
1176 clear_bit(CONNECTING, &con->state); 1203 clear_bit(CONNECTING, &con->state);
1177 con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); 1204 con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
1178 con->connect_seq++; 1205 con->connect_seq++;
diff --git a/fs/ceph/msgr.h b/fs/ceph/msgr.h
index e46d8b806dea..be83f93182ee 100644
--- a/fs/ceph/msgr.h
+++ b/fs/ceph/msgr.h
@@ -21,7 +21,7 @@
21 * whenever the wire protocol changes. try to keep this string length 21 * whenever the wire protocol changes. try to keep this string length
22 * constant. 22 * constant.
23 */ 23 */
24#define CEPH_BANNER "ceph v025" 24#define CEPH_BANNER "ceph v026"
25#define CEPH_BANNER_MAX_LEN 30 25#define CEPH_BANNER_MAX_LEN 30
26 26
27 27
@@ -100,12 +100,14 @@ struct ceph_entity_inst {
100#define CEPH_MSGR_TAG_KEEPALIVE 9 /* just a keepalive byte! */ 100#define CEPH_MSGR_TAG_KEEPALIVE 9 /* just a keepalive byte! */
101#define CEPH_MSGR_TAG_BADPROTOVER 10 /* bad protocol version */ 101#define CEPH_MSGR_TAG_BADPROTOVER 10 /* bad protocol version */
102#define CEPH_MSGR_TAG_BADAUTHORIZER 11 /* bad authorizer */ 102#define CEPH_MSGR_TAG_BADAUTHORIZER 11 /* bad authorizer */
103#define CEPH_MSGR_TAG_FEATURES 12 /* insufficient features */
103 104
104 105
105/* 106/*
106 * connection negotiation 107 * connection negotiation
107 */ 108 */
108struct ceph_msg_connect { 109struct ceph_msg_connect {
110 __le64 features; /* supported feature bits */
109 __le32 host_type; /* CEPH_ENTITY_TYPE_* */ 111 __le32 host_type; /* CEPH_ENTITY_TYPE_* */
110 __le32 global_seq; /* count connections initiated by this host */ 112 __le32 global_seq; /* count connections initiated by this host */
111 __le32 connect_seq; /* count connections initiated in this session */ 113 __le32 connect_seq; /* count connections initiated in this session */
@@ -117,6 +119,7 @@ struct ceph_msg_connect {
117 119
118struct ceph_msg_connect_reply { 120struct ceph_msg_connect_reply {
119 __u8 tag; 121 __u8 tag;
122 __le64 features; /* feature bits for this session */
120 __le32 global_seq; 123 __le32 global_seq;
121 __le32 connect_seq; 124 __le32 connect_seq;
122 __le32 protocol_version; 125 __le32 protocol_version;