diff options
author | Sage Weil <sage@newdream.net> | 2009-12-23 12:30:21 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-12-23 12:30:21 -0500 |
commit | 04a419f908b5291ff7e8ffd7aa351fa0ac0c08af (patch) | |
tree | 2e634bdca766c27b88280ab5c1ce067f47ffe536 /fs/ceph/messenger.c | |
parent | 6df058c025ce343052c5516b1d8a9a7e73cddd64 (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>
Diffstat (limited to 'fs/ceph/messenger.c')
-rw-r--r-- | fs/ceph/messenger.c | 47 |
1 files changed, 37 insertions, 10 deletions
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 | ||
1084 | static 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 | |||
1083 | static int process_connect(struct ceph_connection *con) | 1095 | static 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++; |