ceph: add feature bits to connection handshake (protocol change)
authorSage Weil <sage@newdream.net>
Wed, 23 Dec 2009 17:30:21 +0000 (09:30 -0800)
committerSage Weil <sage@newdream.net>
Wed, 23 Dec 2009 17:30:21 +0000 (09:30 -0800)
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>
fs/ceph/ceph_fs.h
fs/ceph/dir.c
fs/ceph/messenger.c
fs/ceph/msgr.h

index e87dfa6ec8e5286af1b532ae344557254a00e9d9..db3fed33c4aac3e9892b187b6aa5fcc846eccb7e 100644 (file)
 #define CEPH_MAX_MON   31
 
 
+/*
+ * feature bits
+ */
+#define CEPH_FEATURE_SUPPORTED  0
+#define CEPH_FEATURE_REQUIRED   0
+
 
 /*
  * ceph_file_layout - describe data layout for a file/inode
index fde839c61236e84f89becaf7dce23fed642d4d04..5107384ee02927351889ace8f32c5535f718dda8 100644 (file)
@@ -1135,9 +1135,9 @@ void ceph_dentry_lru_add(struct dentry *dn)
 {
        struct ceph_dentry_info *di = ceph_dentry(dn);
        struct ceph_mds_client *mdsc;
-       dout("dentry_lru_add %p %p\t%.*s\n",
-                       di, dn, dn->d_name.len, dn->d_name.name);
 
+       dout("dentry_lru_add %p %p '%.*s'\n", di, dn,
+            dn->d_name.len, dn->d_name.name);
        if (di) {
                mdsc = &ceph_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
@@ -1151,9 +1151,9 @@ void ceph_dentry_lru_touch(struct dentry *dn)
 {
        struct ceph_dentry_info *di = ceph_dentry(dn);
        struct ceph_mds_client *mdsc;
-       dout("dentry_lru_touch %p %p\t%.*s\n",
-                       di, dn, dn->d_name.len, dn->d_name.name);
 
+       dout("dentry_lru_touch %p %p '%.*s'\n", di, dn,
+            dn->d_name.len, dn->d_name.name);
        if (di) {
                mdsc = &ceph_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
@@ -1167,8 +1167,8 @@ void ceph_dentry_lru_del(struct dentry *dn)
        struct ceph_dentry_info *di = ceph_dentry(dn);
        struct ceph_mds_client *mdsc;
 
-       dout("dentry_lru_del %p %p\t%.*s\n",
-                       di, dn, dn->d_name.len, dn->d_name.name);
+       dout("dentry_lru_del %p %p '%.*s'\n", di, dn,
+            dn->d_name.len, dn->d_name.name);
        if (di) {
                mdsc = &ceph_client(dn->d_sb)->mdsc;
                spin_lock(&mdsc->dentry_lru_lock);
index 506b638a023b207c32e621733a0169731661b372..68052f6642808bda98e3a6226860699c186a491e 100644 (file)
@@ -631,6 +631,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
        dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
             con->connect_seq, global_seq, proto);
 
+       con->out_connect.features = CEPH_FEATURE_SUPPORTED;
        con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
        con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
        con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -1080,15 +1081,37 @@ static int process_banner(struct ceph_connection *con)
        return 0;
 }
 
+static void fail_protocol(struct ceph_connection *con)
+{
+       reset_connection(con);
+       set_bit(CLOSED, &con->state);  /* in case there's queued work */
+
+       mutex_unlock(&con->mutex);
+       if (con->ops->bad_proto)
+               con->ops->bad_proto(con);
+       mutex_lock(&con->mutex);
+}
+
 static int process_connect(struct ceph_connection *con)
 {
+       u64 sup_feat = CEPH_FEATURE_SUPPORTED;
+       u64 req_feat = CEPH_FEATURE_REQUIRED;
+       u64 server_feat = le64_to_cpu(con->in_reply.features);
+
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
        switch (con->in_reply.tag) {
+       case CEPH_MSGR_TAG_FEATURES:
+               pr_err("%s%lld %s feature set mismatch,"
+                      " my %llx < server's %llx, missing %llx\n",
+                      ENTITY_NAME(con->peer_name),
+                      pr_addr(&con->peer_addr.in_addr),
+                      sup_feat, server_feat, server_feat & ~sup_feat);
+               con->error_msg = "missing required protocol features";
+               fail_protocol(con);
+               return -1;
+
        case CEPH_MSGR_TAG_BADPROTOVER:
-               dout("process_connect got BADPROTOVER my %d != their %d\n",
-                    le32_to_cpu(con->out_connect.protocol_version),
-                    le32_to_cpu(con->in_reply.protocol_version));
                pr_err("%s%lld %s protocol version mismatch,"
                       " my %d != server's %d\n",
                       ENTITY_NAME(con->peer_name),
@@ -1096,13 +1119,7 @@ static int process_connect(struct ceph_connection *con)
                       le32_to_cpu(con->out_connect.protocol_version),
                       le32_to_cpu(con->in_reply.protocol_version));
                con->error_msg = "protocol version mismatch";
-               reset_connection(con);
-               set_bit(CLOSED, &con->state);  /* in case there's queued work */
-
-               mutex_unlock(&con->mutex);
-               if (con->ops->bad_proto)
-                       con->ops->bad_proto(con);
-               mutex_lock(&con->mutex);
+               fail_protocol(con);
                return -1;
 
        case CEPH_MSGR_TAG_BADAUTHORIZER:
@@ -1173,6 +1190,16 @@ static int process_connect(struct ceph_connection *con)
                break;
 
        case CEPH_MSGR_TAG_READY:
+               if (req_feat & ~server_feat) {
+                       pr_err("%s%lld %s protocol feature mismatch,"
+                              " my required %llx > server's %llx, need %llx\n",
+                              ENTITY_NAME(con->peer_name),
+                              pr_addr(&con->peer_addr.in_addr),
+                              req_feat, server_feat, req_feat & ~server_feat);
+                       con->error_msg = "missing required protocol features";
+                       fail_protocol(con);
+                       return -1;
+               }
                clear_bit(CONNECTING, &con->state);
                con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
                con->connect_seq++;
index e46d8b806dea7b5712562f2ae0b26c9bb2fddcac..be83f93182ee8040d37b158964c5059f760f0955 100644 (file)
@@ -21,7 +21,7 @@
  * whenever the wire protocol changes.  try to keep this string length
  * constant.
  */
-#define CEPH_BANNER "ceph v025"
+#define CEPH_BANNER "ceph v026"
 #define CEPH_BANNER_MAX_LEN 30
 
 
@@ -100,12 +100,14 @@ struct ceph_entity_inst {
 #define CEPH_MSGR_TAG_KEEPALIVE     9  /* just a keepalive byte! */
 #define CEPH_MSGR_TAG_BADPROTOVER  10  /* bad protocol version */
 #define CEPH_MSGR_TAG_BADAUTHORIZER 11 /* bad authorizer */
+#define CEPH_MSGR_TAG_FEATURES      12 /* insufficient features */
 
 
 /*
  * connection negotiation
  */
 struct ceph_msg_connect {
+       __le64 features;     /* supported feature bits */
        __le32 host_type;    /* CEPH_ENTITY_TYPE_* */
        __le32 global_seq;   /* count connections initiated by this host */
        __le32 connect_seq;  /* count connections initiated in this session */
@@ -117,6 +119,7 @@ struct ceph_msg_connect {
 
 struct ceph_msg_connect_reply {
        __u8 tag;
+       __le64 features;     /* feature bits for this session */
        __le32 global_seq;
        __le32 connect_seq;
        __le32 protocol_version;