Commit 04a419f9 authored by Sage Weil's avatar Sage Weil
Browse files

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: default avatarSage Weil <sage@newdream.net>
parent 6df058c0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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;