2 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU Lesser General Public License v.2.1.
16 * Older versions of the log daemon communicate with different
17 * versions of the inter-machine communication structure, which
18 * varies in size and fields. The older versions append the
19 * standard upstream version of the structure to every request.
20 * COMPAT_OFFSET is where the upstream structure starts.
22 #define COMPAT_OFFSET 256
24 static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute__((unused)))
29 uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
31 if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
35 LOG_ERROR("Invalid response type in endian switch");
38 case DM_ULOG_PRESUSPEND:
39 case DM_ULOG_POSTSUSPEND:
42 case DM_ULOG_MARK_REGION:
43 case DM_ULOG_CLEAR_REGION:
44 case DM_ULOG_SET_REGION_SYNC:
45 case DM_ULOG_CHECKPOINT_READY:
46 case DM_ULOG_MEMBER_JOIN:
47 case DM_ULOG_STATUS_INFO:
48 case DM_ULOG_STATUS_TABLE:
49 /* No outbound data */
52 case DM_ULOG_GET_REGION_SIZE:
53 case DM_ULOG_GET_SYNC_COUNT:
54 pu64 = (uint64_t *)rq->u_rq.data;
55 *pu64 = xlate64(*pu64);
57 case DM_ULOG_IS_CLEAN:
59 pi64 = (int64_t *)rq->u_rq.data;
60 *pi64 = xlate64(*pi64);
62 case DM_ULOG_GET_RESYNC_WORK:
63 case DM_ULOG_IS_REMOTE_RECOVERING:
64 pi64 = (int64_t *)rq->u_rq.data;
65 pu64 = ((uint64_t *)rq->u_rq.data) + 1;
66 *pi64 = xlate64(*pi64);
67 *pu64 = xlate64(*pu64);
70 LOG_ERROR("Unknown request type, %u", rq_type);
77 LOG_ERROR("Invalid request type in endian switch");
80 case DM_ULOG_PRESUSPEND:
81 case DM_ULOG_POSTSUSPEND:
83 case DM_ULOG_GET_REGION_SIZE:
85 case DM_ULOG_GET_RESYNC_WORK:
86 case DM_ULOG_GET_SYNC_COUNT:
87 case DM_ULOG_STATUS_INFO:
88 case DM_ULOG_STATUS_TABLE:
89 case DM_ULOG_CHECKPOINT_READY:
90 case DM_ULOG_MEMBER_JOIN:
91 /* No incoming data */
93 case DM_ULOG_IS_CLEAN:
95 case DM_ULOG_IS_REMOTE_RECOVERING:
96 pu64 = (uint64_t *)rq->u_rq.data;
97 *pu64 = xlate64(*pu64);
99 case DM_ULOG_MARK_REGION:
100 case DM_ULOG_CLEAR_REGION:
101 end = rq->u_rq.data_size/sizeof(uint64_t);
103 pu64 = (uint64_t *)rq->u_rq.data;
104 for (i = 0; i < end; i++)
105 pu64[i] = xlate64(pu64[i]);
107 case DM_ULOG_SET_REGION_SYNC:
108 pu64 = (uint64_t *)rq->u_rq.data;
109 pi64 = ((int64_t *)rq->u_rq.data) + 1;
110 *pu64 = xlate64(*pu64);
111 *pi64 = xlate64(*pi64);
114 LOG_ERROR("Unknown request type, %u", rq_type);
120 static int v5_endian_to_network(struct clog_request *rq)
123 struct dm_ulog_request *u_rq = &rq->u_rq;
125 size = sizeof(*rq) + u_rq->data_size;
127 u_rq->error = xlate32(u_rq->error);
128 u_rq->seq = xlate32(u_rq->seq);
129 u_rq->request_type = xlate32(u_rq->request_type);
130 u_rq->data_size = xlate64(u_rq->data_size);
132 rq->originator = xlate32(rq->originator);
134 v5_data_endian_switch(rq, 1);
139 int clog_request_to_network(struct clog_request *rq)
143 /* FIXME: Remove this safety check */
144 if (rq->u.version[0] != xlate64(rq->u.version[1])) {
145 LOG_ERROR("Programmer error: version[0] must be LE");
150 * Are we already running in the endian mode we send
153 if (rq->u.version[0] == rq->u.version[1])
156 r = v5_endian_to_network(rq);
162 static int v5_endian_from_network(struct clog_request *rq)
165 struct dm_ulog_request *u_rq = &rq->u_rq;
167 u_rq->error = xlate32(u_rq->error);
168 u_rq->seq = xlate32(u_rq->seq);
169 u_rq->request_type = xlate32(u_rq->request_type);
170 u_rq->data_size = xlate64(u_rq->data_size);
172 rq->originator = xlate32(rq->originator);
174 size = sizeof(*rq) + u_rq->data_size;
176 v5_data_endian_switch(rq, 0);
181 int clog_request_from_network(void *data, size_t data_len)
184 uint64_t version = xlate64(vp[0]);
185 uint64_t unconverted_version = vp[1];
186 struct clog_request *rq = data;
189 case 5: /* Upstream */
190 if (version == unconverted_version)
193 case 4: /* RHEL 5.[45] */
194 case 3: /* RHEL 5.3 */
195 case 2: /* RHEL 5.2 */
196 /* FIXME: still need to account for payload */
197 if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
200 rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
203 LOG_ERROR("Unable to process cluster message: "
204 "Incompatible version");
208 v5_endian_from_network(rq);