cluster: RHEL55 - cmirror: Endian fixes for mixed architecture clusters (bug 488102)

Jonathan Brassow jbrassow at fedoraproject.org
Mon Feb 8 17:53:37 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=5239e25bfd9967a08427bcbcc15548731dad34f1
Commit:        5239e25bfd9967a08427bcbcc15548731dad34f1
Parent:        af9b2042ec0f0ca80229051bc158f18c241347ed
Author:        Jonathan Brassow <jbrassow at redhat.com>
AuthorDate:    Mon Feb 8 11:49:16 2010 -0600
Committer:     Jonathan Brassow <jbrassow at redhat.com>
CommitterDate: Mon Feb 8 11:49:56 2010 -0600

cmirror: Endian fixes for mixed architecture clusters (bug 488102)

Some data from non-like architecture machines in the cluster was
not being converted along with the communication structure.

bug 488102 also addresses or is similar to bugs 533204 and 479321.
These changes are only useful to those who have mixed arch
clusters or are running multiple versions of rhel5 at the same
time.
---
 cmirror/src/compat.c |  329 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 325 insertions(+), 4 deletions(-)

diff --git a/cmirror/src/compat.c b/cmirror/src/compat.c
index 3639d99..da104a1 100644
--- a/cmirror/src/compat.c
+++ b/cmirror/src/compat.c
@@ -3,6 +3,7 @@
  *
  * This file is released under the GPL.
  */
+#include <stdlib.h>
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
@@ -339,6 +340,124 @@ static int v4_to_v5(struct clog_tfr_v4 *v4, struct clog_request *rq)
 	return COMPAT_OFFSET + sizeof(*rq) + u_rq->data_size;
 }
 
+#define switch_64(x, to_wire) \
+	(to_wire) ? le64_to_cpu(x) : cpu_to_le64(x)
+
+void v5_data_endian_switch(struct clog_request *rq, int to_wire)
+{
+	int i, end;
+	int64_t *pi64;
+	uint64_t *pu64;
+	uint32_t rq_type = rq->u_rq.request_type & ~DM_CLOG_RESPONSE;
+	
+	if (rq->u_rq.request_type & DM_CLOG_RESPONSE) {
+		switch (rq_type) {
+		case DM_CLOG_CTR:
+		case DM_CLOG_DTR:
+			LOG_ERROR("Invalid response type in endian switch");
+			exit(EXIT_FAILURE);
+
+		case DM_CLOG_PRESUSPEND:
+		case DM_CLOG_POSTSUSPEND:
+		case DM_CLOG_RESUME:
+		case DM_CLOG_FLUSH:
+		case DM_CLOG_MARK_REGION:
+		case DM_CLOG_CLEAR_REGION:
+		case DM_CLOG_SET_REGION_SYNC:
+		case DM_CLOG_CHECKPOINT_READY:
+		case DM_CLOG_MEMBER_JOIN:
+		case DM_CLOG_STATUS_INFO:
+		case DM_CLOG_STATUS_TABLE:
+			/* No outbound data */
+			break;
+
+		case DM_CLOG_GET_REGION_SIZE:
+		case DM_CLOG_GET_SYNC_COUNT:
+			pu64 = (uint64_t *)rq->u_rq.data;
+			*pu64 = switch_64(*pu64, to_wire);
+			break;
+		case DM_CLOG_IS_CLEAN:
+		case DM_CLOG_IN_SYNC:
+			pi64 = (int64_t *)rq->u_rq.data;
+			*pi64 = switch_64(*pi64, to_wire);
+			break;
+		case DM_CLOG_GET_RESYNC_WORK:
+		case DM_CLOG_IS_REMOTE_RECOVERING:
+			pi64 = (int64_t *)rq->u_rq.data;
+			pu64 = ((uint64_t *)rq->u_rq.data) + 1;
+			*pi64 = switch_64(*pi64, to_wire);
+			*pu64 = switch_64(*pu64, to_wire);
+			break;
+		default:
+			LOG_ERROR("Unknown request type, %u", rq_type);
+			return;
+		}
+	} else {
+		switch (rq_type) {
+		case DM_CLOG_CTR:
+		case DM_CLOG_DTR:
+			LOG_ERROR("Invalid request type in endian switch");
+			exit(EXIT_FAILURE);
+
+		case DM_CLOG_PRESUSPEND:
+		case DM_CLOG_POSTSUSPEND:
+		case DM_CLOG_RESUME:
+		case DM_CLOG_GET_REGION_SIZE:
+		case DM_CLOG_FLUSH:
+		case DM_CLOG_GET_RESYNC_WORK:
+		case DM_CLOG_GET_SYNC_COUNT:
+		case DM_CLOG_STATUS_INFO:
+		case DM_CLOG_STATUS_TABLE:
+		case DM_CLOG_CHECKPOINT_READY:
+		case DM_CLOG_MEMBER_JOIN:
+			/* No incoming data */
+			break;
+		case DM_CLOG_IS_CLEAN:
+		case DM_CLOG_IN_SYNC:
+		case DM_CLOG_IS_REMOTE_RECOVERING:
+			pu64 = (uint64_t *)rq->u_rq.data;
+			*pu64 = switch_64(*pu64, to_wire);
+			break;
+		case DM_CLOG_MARK_REGION:
+		case DM_CLOG_CLEAR_REGION:
+			end = rq->u_rq.data_size/sizeof(uint64_t);
+
+			pu64 = (uint64_t *)rq->u_rq.data;
+			for (i = 0; i < end; i++)
+				pu64[i] = switch_64(pu64[i], to_wire);
+			break;
+		case DM_CLOG_SET_REGION_SYNC:
+			pu64 = (uint64_t *)rq->u_rq.data;
+			pi64 = ((int64_t *)rq->u_rq.data) + 1;
+			*pu64 = switch_64(*pu64, to_wire);
+			*pi64 = switch_64(*pi64, to_wire);
+			break;
+		default:
+			LOG_ERROR("Unknown request type, %u", rq_type);
+			exit(EXIT_FAILURE);
+		}
+	}
+}
+
+int v5_endian_to_wire(struct clog_request *rq)
+{
+	int size;
+	struct dm_ulog_request *u_rq = &rq->u_rq;
+
+	size = sizeof(*rq) + u_rq->data_size;
+
+	u_rq->error = cpu_to_le32(u_rq->error);
+	u_rq->seq = cpu_to_le32(u_rq->seq);
+	u_rq->request_type = cpu_to_le32(u_rq->request_type);
+	u_rq->data_size = cpu_to_le64(u_rq->data_size);
+
+	rq->originator = cpu_to_le32(rq->originator);
+
+	v5_data_endian_switch(rq, 1);
+
+	return size;
+}
+
 int add_compatibility_layer(void *from, void **compat_version,
 			    unsigned from_version)
 {
@@ -357,6 +476,8 @@ int add_compatibility_layer(void *from, void **compat_version,
 	case 4:
 		from_size = sizeof(*v4) + v4->data_size;
 		break;
+	case 5:
+		return v5_endian_to_wire(from);
 	default:
 		LOG_ERROR("Invalid 'from_version'");
 		return -EINVAL;
@@ -396,16 +517,196 @@ static int v5_to_v3(struct clog_request *rq, struct clog_tfr_v3 *v3)
 	return -EINVAL;
 }
 
+static int v5_to_v4_copy_data(struct clog_request *rq, struct clog_tfr_v4 *v4)
+{
+	int data_size = 0;
+	struct dm_ulog_request *u_rq = &rq->u_rq;
+	uint32_t rq_type = le32_to_cpu(u_rq->request_type) & ~DM_CLOG_RESPONSE;
+
+	if (le32_to_cpu(u_rq->request_type) & DM_CLOG_RESPONSE) {
+		switch (rq_type) {
+		case DM_CLOG_CTR:
+		case DM_CLOG_DTR:
+		case DM_CLOG_PRESUSPEND:
+		case DM_CLOG_POSTSUSPEND:
+		case DM_CLOG_RESUME:
+		case DM_CLOG_FLUSH:
+		case DM_CLOG_MARK_REGION:
+		case DM_CLOG_CLEAR_REGION:
+		case DM_CLOG_SET_REGION_SYNC:
+		case DM_CLOG_CHECKPOINT_READY:
+		case DM_CLOG_MEMBER_JOIN:
+			/* No outbound data */
+			break;
+
+		case DM_CLOG_GET_REGION_SIZE:
+			data_size = sizeof(uint64_t);
+			if (v4) {
+				uint64_t *a64, *b64;
+
+				a64 = (uint64_t *)rq->u_rq.data;
+				b64 = (uint64_t *)v4->data;
+				*b64 = le64_to_cpu(*a64);
+			}
+			break;
+		case DM_CLOG_IS_CLEAN:
+		case DM_CLOG_IN_SYNC:
+			data_size = sizeof(int);
+			if (v4) {
+				int *p;
+				int64_t *p64;
+
+				p = (int *)v4->data;
+				p64 = (int64_t *)rq->u_rq.data;
+				*p = (int)(le64_to_cpu(*p64));
+			}
+			break;
+		case DM_CLOG_GET_RESYNC_WORK:
+			data_size = sizeof(int32_t) +
+				sizeof(uint32_t) + sizeof(uint64_t);
+			if (v4) {
+				int32_t *pi32;
+				int64_t *pi64;
+				uint64_t *pu64, u64;
+
+				pi32 = (int32_t *)v4->data;
+				pu64 = ((uint64_t *)v4->data) + 1;
+
+				pi64 = (int64_t *)rq->u_rq.data;
+				u64 = ((uint64_t *)rq->u_rq.data)[1];
+
+				*pi32 = (int32_t)(le64_to_cpu(*pi64));
+				*pu64 = (uint64_t)le64_to_cpu(u64);
+			}
+			break;
+		case DM_CLOG_GET_SYNC_COUNT:
+			data_size = sizeof(uint64_t);
+			if (v4) {
+				uint64_t *a64, *b64;
+
+				a64 = (uint64_t *)rq->u_rq.data;
+				b64 = (uint64_t *)v4->data;
+				*b64 = le64_to_cpu(*a64);
+			}
+			break;			
+		case DM_CLOG_STATUS_INFO:
+		case DM_CLOG_STATUS_TABLE:
+			data_size = u_rq->data_size;
+			if (v4)
+				memcpy(v4->data, rq->u_rq.data, data_size);
+			break;
+		case DM_CLOG_IS_REMOTE_RECOVERING:
+			data_size = sizeof(int32_t) +
+				sizeof(uint32_t) + sizeof(uint64_t);
+			if (v4) {
+				int32_t *pi32;
+				uint64_t *pu64, u64;
+				int64_t i64;
+
+				i64 = ((int64_t *)rq->u_rq.data)[0];
+				u64 = ((uint64_t *)rq->u_rq.data)[1];
+
+				pi32 = (int32_t *)v4->data;
+				pu64 = ((uint64_t *)v4->data) + 1;
+
+				*pi32 = (int32_t)(le64_to_cpu(i64));
+				*pu64 = le64_to_cpu(u64);
+			}
+			break;
+		default:
+			LOG_ERROR("Unknown request type, %u", rq_type);
+			return -EINVAL;
+		}
+	} else {
+		switch (rq_type) {
+		case DM_CLOG_CTR:
+		case DM_CLOG_DTR:
+		case DM_CLOG_PRESUSPEND:
+		case DM_CLOG_POSTSUSPEND:
+		case DM_CLOG_RESUME:
+		case DM_CLOG_GET_REGION_SIZE:
+		case DM_CLOG_FLUSH:
+		case DM_CLOG_GET_RESYNC_WORK:
+		case DM_CLOG_GET_SYNC_COUNT:
+		case DM_CLOG_STATUS_INFO:
+		case DM_CLOG_STATUS_TABLE:
+		case DM_CLOG_CHECKPOINT_READY:
+		case DM_CLOG_MEMBER_JOIN:
+			/* No incoming data */
+			break;
+		case DM_CLOG_IS_CLEAN:
+		case DM_CLOG_IN_SYNC:
+			data_size = sizeof(uint64_t);
+			if (v4) {
+				uint64_t *a64, *b64;
+
+				a64 = (uint64_t *)rq->u_rq.data;
+				b64 = (uint64_t *)v4->data;
+				*b64 = le64_to_cpu(*a64);
+			}
+			break;
+		case DM_CLOG_MARK_REGION:
+		case DM_CLOG_CLEAR_REGION:
+			data_size = le32_to_cpu(u_rq->data_size);
+			if (v4) {
+				int i, end = data_size/sizeof(uint64_t);
+				uint64_t *a64, *b64;
+
+				a64 = (uint64_t *)rq->u_rq.data;
+				b64 = (uint64_t *)v4->data;
+				for (i = 0; i < end; i++)
+					b64[i] = le64_to_cpu(a64[i]);
+			}
+			break;
+		case DM_CLOG_SET_REGION_SYNC:
+			data_size = sizeof(uint64_t) +
+				sizeof(uint32_t) + sizeof(int32_t);
+			if (v4) {
+				uint64_t u64, *pu64;
+				int64_t i64;
+				int32_t *pi32;
+
+				pu64 = (uint64_t *)v4->data;
+				pi32 = ((int32_t *)v4->data) + 3;
+
+				u64 = ((uint64_t *)rq->u_rq.data)[0];
+				i64 = ((int64_t *)rq->u_rq.data)[1];
+
+				*pu64 = le64_to_cpu(u64);
+				*pi32 = (uint32_t)(le64_to_cpu(i64));
+			}
+			break;
+		case DM_CLOG_IS_REMOTE_RECOVERING:
+			data_size = sizeof(uint64_t);
+			if (v4) {
+				uint64_t *a64, *b64;
+
+				a64 = (uint64_t *)rq->u_rq.data;
+				b64 = (uint64_t *)v4->data;
+				*b64 = le64_to_cpu(*a64);
+			}
+			break;
+		default:
+			LOG_ERROR("Unknown request type, %u", rq_type);
+			return -EINVAL;
+		}
+	}
+
+	return data_size;
+}
+
 static int v5_to_v4(struct clog_request *rq, struct clog_tfr_v4 *v4)
 {
+	int size;
 	struct dm_ulog_request *u_rq = &rq->u_rq;
 
-	if ((sizeof(*v4) + u_rq->data_size) > (COMPAT_SIZE - COMPAT_OFFSET)) {
+	size = sizeof(*v4) + v5_to_v4_copy_data(rq, NULL);
+
+	if (size > (COMPAT_SIZE - COMPAT_OFFSET)) {
 		LOG_ERROR("Not enough space for compatibility data (v5->v4)");
 		return -EINVAL;
 	}
 
-	LOG_ERROR("Stripping compatibility layer (v5->v4)");
 	v4->uuid_instance = (uint32_t)u_rq->luid;
 
 	memcpy(v4->uuid, u_rq->uuid, DM_UUID_LEN);
@@ -416,11 +717,30 @@ static int v5_to_v4(struct clog_request *rq, struct clog_tfr_v4 *v4)
 
 	v4->originator = rq->originator;
 
-	memcpy(v4->data, u_rq->data, u_rq->data_size);
+	v5_to_v4_copy_data(rq, v4);
 
 	return 0;
 }
 
+int v5_endian_from_wire(struct clog_request *rq)
+{
+	int size;
+	struct dm_ulog_request *u_rq = &rq->u_rq;
+
+	u_rq->error = le32_to_cpu(u_rq->error);
+	u_rq->seq = le32_to_cpu(u_rq->seq);
+	u_rq->request_type = le32_to_cpu(u_rq->request_type);
+	u_rq->data_size = le64_to_cpu(u_rq->data_size);
+
+	rq->originator = le32_to_cpu(rq->originator);
+
+	size = sizeof(*rq) + u_rq->data_size;
+
+	v5_data_endian_switch(rq, 0);
+
+	return size;
+}
+
 int strip_compatibility_layer(void *from, void **to,
 			      unsigned to_version)
 {
@@ -462,6 +782,8 @@ int strip_compatibility_layer(void *from, void **to,
 			return v5_to_v3(from, (void *)buffer);
 		case 4:
 			return v5_to_v4(from, (void *)buffer);
+		case 5:
+			return v5_endian_from_wire(from);
 		}
 		return -EINVAL;
 	}		
@@ -473,7 +795,6 @@ int strip_compatibility_layer(void *from, void **to,
 	 *
 	 * IOW, assume (version == to_version)
 	 */
-
 	if (report) {
 		LOG_ERROR("Unknown version for communication struct - forced to assume version %d", to_version);
 		report = 0;


More information about the cluster-commits mailing list