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 | |
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')
-rw-r--r-- | fs/ceph/ceph_fs.h | 6 | ||||
-rw-r--r-- | fs/ceph/dir.c | 12 | ||||
-rw-r--r-- | fs/ceph/messenger.c | 47 | ||||
-rw-r--r-- | fs/ceph/msgr.h | 5 |
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 | ||
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++; |
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 | */ |
108 | struct ceph_msg_connect { | 109 | struct 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 | ||
118 | struct ceph_msg_connect_reply { | 120 | struct 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; |