Skip to content

Commit dd74b94

Browse files
committed
MDEV-15505 Fix wsrep XID seqno byte order
The problem is that the seqno part of wsrep XID is always stored in host byte order. This may cause issues when a physical backup is restored on a host with different architecture, the seqno part with XID may have incorrect value. In order to fix this, wsrep XID seqno is always written into XID data buffer in little endian byte order using int8store() and read from data buffer using sint8korr(). For backwards compatibility the seqno is read from TRX_SYS page in host byte order during upgrade. This patch implements byte ordering in wsrep_xid_init(), wsrep_xid_seqno(), and exposes functions to read wsrep XID uuid and seqno in wsrep_service_st. Backwards compatibility for upgrade is provided in trx_rseg_init_wsrep_xid().
1 parent 09c5c33 commit dd74b94

File tree

5 files changed

+45
-35
lines changed

5 files changed

+45
-35
lines changed

extra/mariabackup/wsrep.cc

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,7 @@ wsrep_seqno_t wsrep_xid_seqno(
119119
const XID* xid)
120120
{
121121
if (wsrep_is_wsrep_xid(xid)) {
122-
wsrep_seqno_t seqno;
123-
memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET,
124-
sizeof(wsrep_seqno_t));
125-
126-
return(seqno);
122+
return sint8korr(xid->data + WSREP_XID_SEQNO_OFFSET);
127123
} else {
128124
return(WSREP_SEQNO_UNDEFINED);
129125
}

include/mysql/service_wsrep.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ struct xid_t;
7070
struct wsrep;
7171
struct wsrep_ws_handle;
7272
struct wsrep_buf;
73+
/* must match to typedef in wsrep/wsrep_api.h */
74+
typedef int64_t wsrep_seqno_t;
7375

7476
extern struct wsrep_service_st {
7577
struct wsrep * (*get_wsrep_func)();
@@ -84,6 +86,8 @@ extern struct wsrep_service_st {
8486
void (*wsrep_aborting_thd_enqueue_func)(THD *thd);
8587
bool (*wsrep_consistency_check_func)(THD *thd);
8688
int (*wsrep_is_wsrep_xid_func)(const struct xid_t *xid);
89+
wsrep_seqno_t (*wsrep_xid_seqno_func)(const struct xid_t *xid);
90+
const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid);
8791
void (*wsrep_lock_rollback_func)();
8892
int (*wsrep_on_func)(MYSQL_THD);
8993
void (*wsrep_post_commit_func)(THD* thd, bool all);
@@ -125,6 +129,8 @@ extern struct wsrep_service_st {
125129
#define wsrep_aborting_thd_enqueue(T) wsrep_service->wsrep_aborting_thd_enqueue_func(T)
126130
#define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T)
127131
#define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X)
132+
#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X)
133+
#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X)
128134
#define wsrep_lock_rollback() wsrep_service->wsrep_lock_rollback_func()
129135
#define wsrep_on(X) wsrep_service->wsrep_on_func(X)
130136
#define wsrep_post_commit(T,A) wsrep_service->wsrep_post_commit_func(T,A)
@@ -182,6 +188,8 @@ enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
182188
enum wsrep_query_state wsrep_thd_query_state(THD *thd);
183189
enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, bool all);
184190
int wsrep_is_wsrep_xid(const struct xid_t* xid);
191+
wsrep_seqno_t wsrep_xid_seqno(const struct xid_t* xid);
192+
const unsigned char* wsrep_xid_uuid(const struct xid_t* xid);
185193
int wsrep_on(MYSQL_THD thd);
186194
int wsrep_thd_retry_counter(THD *thd);
187195
int wsrep_trx_is_aborting(MYSQL_THD thd);

sql/sql_plugin_services.ic

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ static struct wsrep_service_st wsrep_handler = {
154154
wsrep_aborting_thd_enqueue,
155155
wsrep_consistency_check,
156156
wsrep_is_wsrep_xid,
157+
wsrep_xid_seqno,
158+
wsrep_xid_uuid,
157159
wsrep_lock_rollback,
158160
wsrep_on,
159161
wsrep_post_commit,

sql/wsrep_xid.cc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
3939
memset(xid->data, 0, sizeof(xid->data));
4040
memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN);
4141
memcpy(xid->data + WSREP_XID_UUID_OFFSET, &uuid, sizeof(wsrep_uuid_t));
42-
memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t));
42+
int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno);
4343
}
4444

4545
int wsrep_is_wsrep_xid(const XID* xid)
@@ -59,20 +59,30 @@ const wsrep_uuid_t* wsrep_xid_uuid(const XID& xid)
5959
return &WSREP_UUID_UNDEFINED;
6060
}
6161

62+
const unsigned char* wsrep_xid_uuid(const xid_t* xid)
63+
{
64+
DBUG_ASSERT(xid);
65+
return wsrep_xid_uuid(*xid)->data;
66+
}
67+
6268
wsrep_seqno_t wsrep_xid_seqno(const XID& xid)
6369
{
6470
if (wsrep_is_wsrep_xid(&xid))
6571
{
66-
wsrep_seqno_t seqno;
67-
memcpy(&seqno, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t));
68-
return seqno;
72+
return sint8korr(xid.data + WSREP_XID_SEQNO_OFFSET);
6973
}
7074
else
7175
{
7276
return WSREP_SEQNO_UNDEFINED;
7377
}
7478
}
7579

80+
wsrep_seqno_t wsrep_xid_seqno(const xid_t* xid)
81+
{
82+
DBUG_ASSERT(xid);
83+
return wsrep_xid_seqno(*xid);
84+
}
85+
7686
static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
7787
{
7888
XID* xid= static_cast<XID*>(arg);

storage/innobase/trx/trx0rseg.cc

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,32 +35,15 @@ Created 3/26/1996 Heikki Tuuri
3535
#include <algorithm>
3636

3737
#ifdef WITH_WSREP
38+
#include <mysql/service_wsrep.h>
3839

3940
#ifdef UNIV_DEBUG
4041
/** The latest known WSREP XID sequence number */
41-
static long long wsrep_seqno = -1;
42+
static wsrep_seqno_t wsrep_seqno = -1;
4243
#endif /* UNIV_DEBUG */
4344
/** The latest known WSREP XID UUID */
4445
static unsigned char wsrep_uuid[16];
4546

46-
/** Read WSREP XID UUID.
47-
@param[in] xid WSREP XID
48-
@return Pointer to the first byte of the UUID.
49-
*/
50-
51-
static inline const byte* read_wsrep_xid_uuid(const XID* xid)
52-
{
53-
return reinterpret_cast<const byte*>(xid->data + 8);
54-
}
55-
56-
/** Read WSREP XID seqno */
57-
static inline long long read_wsrep_xid_seqno(const XID* xid)
58-
{
59-
long long seqno;
60-
memcpy(&seqno, xid->data + 24, sizeof(long long));
61-
return seqno;
62-
}
63-
6447
/** Update the WSREP XID information in rollback segment header.
6548
@param[in,out] rseg_header rollback segment header
6649
@param[in] xid WSREP XID
@@ -71,12 +54,12 @@ trx_rseg_update_wsrep_checkpoint(
7154
const XID* xid,
7255
mtr_t* mtr)
7356
{
74-
ut_ad(xid->formatID == 1);
57+
ut_ad(wsrep_is_wsrep_xid(xid));
7558

7659
#ifdef UNIV_DEBUG
7760
/* Check that seqno is monotonically increasing */
78-
long long xid_seqno = read_wsrep_xid_seqno(xid);
79-
const byte* xid_uuid = read_wsrep_xid_uuid(xid);
61+
wsrep_seqno_t xid_seqno = wsrep_xid_seqno(xid);
62+
const byte* xid_uuid = wsrep_xid_uuid(xid);
8063

8164
if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) {
8265
ut_ad(xid_seqno > wsrep_seqno);
@@ -125,7 +108,7 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
125108

126109
trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr);
127110

128-
const byte* xid_uuid = read_wsrep_xid_uuid(xid);
111+
const byte* xid_uuid = wsrep_xid_uuid(xid);
129112
if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) {
130113
memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid);
131114

@@ -203,6 +186,17 @@ static bool trx_rseg_init_wsrep_xid(const page_t* page, XID& xid)
203186
memcpy(xid.data,
204187
TRX_SYS + TRX_SYS_WSREP_XID_INFO
205188
+ TRX_SYS_WSREP_XID_DATA + page, XIDDATASIZE);
189+
190+
/* Wsrep XID seqno part in TRX_SYS page was written in host byte
191+
order. However, in the XID which gets written to the rollback
192+
segment header the byte order is little endian. On big endian
193+
machines swap the seqno part byte order. */
194+
#ifdef WORDS_BIGENDIAN
195+
wsrep_seqno_t seqno;
196+
memcpy(&seqno, xid.data + 24, sizeof seqno);
197+
mach_swap_byte_order(xid.data + 24, &seqno, sizeof seqno);
198+
#endif /* WORDS_BIGENDIAN */
199+
206200
return true;
207201
}
208202

@@ -239,14 +233,14 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
239233
}
240234

241235
XID tmp_xid;
242-
long long tmp_seqno = 0;
236+
wsrep_seqno_t tmp_seqno = 0;
243237
if (trx_rseg_read_wsrep_checkpoint(rseg_header, tmp_xid)
244-
&& (tmp_seqno = read_wsrep_xid_seqno(&tmp_xid))
238+
&& (tmp_seqno = wsrep_xid_seqno(&tmp_xid))
245239
> max_xid_seqno) {
246240
found = true;
247241
max_xid_seqno = tmp_seqno;
248242
xid = tmp_xid;
249-
memcpy(wsrep_uuid, read_wsrep_xid_uuid(&tmp_xid),
243+
memcpy(wsrep_uuid, wsrep_xid_uuid(&tmp_xid),
250244
sizeof wsrep_uuid);
251245
}
252246
}

0 commit comments

Comments
 (0)