瀏覽代碼

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>
Sage Weil 15 年之前
父節點
當前提交
04a419f908
共有 4 個文件被更改,包括 53 次插入17 次删除
  1. 6 0
      fs/ceph/ceph_fs.h
  2. 6 6
      fs/ceph/dir.c
  3. 37 10
      fs/ceph/messenger.c
  4. 4 1
      fs/ceph/msgr.h

+ 6 - 0
fs/ceph/ceph_fs.h

@@ -50,6 +50,12 @@
 #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

+ 6 - 6
fs/ceph/dir.c

@@ -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);

+ 37 - 10
fs/ceph/messenger.c

@@ -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++;

+ 4 - 1
fs/ceph/msgr.h

@@ -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;