From: Maxim Uvarov <muvarov@ru.mvista.com>
To: drbd-dev@lists.linbit.com
Subject: [Drbd-dev] [DRBD][PATCH] drbd_bitfild_endian.patch
Date: Mon, 26 Nov 2007 16:32:44 +0000 [thread overview]
Message-ID: <474AF52C.6090409@ru.mvista.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 605 bytes --]
Hello all,
We have found that drbd state is passed incorrectly between machines
with different endianness.
Attached patch fixes this problem by converting bitfild to int.
Replacing all bitfileds (both in kernel and userland) isn't safe way
(there are
about hundred lines to replace). Maybe adding converter from bitfield to
int32
is appropriate solution ? Then sending state we do
"drbd_state_to_int(state)"
and then receive we restore state by "int_to_drbd_state(i)". only 9 lines of
kernel code was changed (No need to change userspace). Additional
overhead is
neglible.
Best regards,
Maxim.
[-- Attachment #2: drbd_bitfild_endian.patch --]
[-- Type: text/plain, Size: 5829 bytes --]
Source: MontaVista Software, Inc.
MR: 26056
Type: Defect Fix
Disposition: needs submitting to DRBD maintainer
Signed-off-by: Maxim Uvarov <muvarov@ru.mvista.com>
Signed-off-by: Maxim Syrchin <msyrchin@ru.mvista.com>
Description:
DRBD uses bitfield to store its state. Since bitfields are not
cross-architecture safe - it causes error then archs of peers are
different. The simplest way to solve this is to convert biitfild
to cross-arch safe int32. This change makes new protocol incompatile
with old one - so PRO_VERSION is increased from 86 up to 88.
Index: linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_int.h
===================================================================
--- linux-2.6.21_mvlcge500.orig/drivers/block/drbd/drbd_int.h
+++ linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_int.h
@@ -1446,6 +1446,64 @@ void drbd_bcast_state(drbd_dev *mdev);
D,({drbd_state_t ns; ns.i = D->state.i; ns.T1 = (S1); \
ns.T2 = (S2); ns.T3 = (S3); ns;})
+/*
+ * Using bitfields is no cross-architecture safe.
+ * Use shifts to convert bitfield to cross-safe int
+ */
+
+#define ROLE_OFF 0
+#define PEER_OFF 2
+#define CONN_OFF 4
+#define DISK_OFF 9
+#define PDSK_OFF 13
+#define SUSP_OFF 17
+#define AISP_OFF 18
+#define PISP_OFF 19
+#define UISP_OFF 20
+
+#define ROLE_MASK (unsigned int)0x03
+#define PEER_MASK (unsigned int)0x03
+#define CONN_MASK (unsigned int)0x1f
+#define DISK_MASK (unsigned int)0x0f
+#define PDSK_MASK (unsigned int)0x0f
+#define SUSP_MASK (unsigned int)0x01
+#define AISP_MASK (unsigned int)0x01
+#define PISP_MASK (unsigned int)0x01
+#define UISP_MASK (unsigned int)0x01
+
+static inline unsigned int drbd_state_to_int (unsigned int state_i)
+{
+ unsigned int i = 0;
+ drbd_state_t state;
+ state.i = state_i;
+ i = ((unsigned int)state.role)<<ROLE_OFF;
+ i |= ((unsigned int)state.peer)<<PEER_OFF;
+ i |= ((unsigned int)state.conn)<<CONN_OFF;
+ i |= ((unsigned int)state.disk)<<DISK_OFF;
+ i |= ((unsigned int)state.pdsk)<<PDSK_OFF;
+ i |= ((unsigned int)state.susp)<<SUSP_OFF;
+ i |= ((unsigned int)state.aftr_isp)<<AISP_OFF;
+ i |= ((unsigned int)state.peer_isp)<<PISP_OFF;
+ i |= ((unsigned int)state.user_isp)<<UISP_OFF;
+ return i;
+}
+
+static inline unsigned int int_to_drbd_state (unsigned int i)
+{
+ drbd_state_t state;
+ state.i = 0;
+ state.role = (i>>ROLE_OFF)&ROLE_MASK;
+ state.peer = (i>>PEER_OFF)&PEER_MASK;
+ state.conn = (i>>CONN_OFF)&CONN_MASK;
+ state.disk = (i>>DISK_OFF)&DISK_MASK;
+ state.pdsk = (i>>PDSK_OFF)&PDSK_MASK;
+ state.susp = (i>>SUSP_OFF)&SUSP_MASK;
+ state.aftr_isp = (i>>AISP_OFF)&AISP_MASK;
+ state.peer_isp = (i>>PISP_OFF)&PISP_MASK;
+ state.user_isp = (i>>UISP_OFF)&UISP_MASK;
+ return state.i;
+}
+
static inline void drbd_state_lock(drbd_dev *mdev)
{
wait_event(mdev->misc_wait,
Index: linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_main.c
===================================================================
--- linux-2.6.21_mvlcge500.orig/drivers/block/drbd/drbd_main.c
+++ linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_main.c
@@ -1366,7 +1366,7 @@ int drbd_send_state(drbd_dev *mdev)
{
Drbd_State_Packet p;
- p.state = cpu_to_be32(mdev->state.i);
+ p.state = cpu_to_be32(drbd_state_to_int(mdev->state.i));
return drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportState,
(Drbd_Header*)&p,sizeof(p));
@@ -1376,8 +1376,8 @@ STATIC int drbd_send_state_req(drbd_dev
{
Drbd_Req_State_Packet p;
- p.mask = cpu_to_be32(mask.i);
- p.val = cpu_to_be32(val.i);
+ p.mask = cpu_to_be32(drbd_state_to_int(mask.i));
+ p.val = cpu_to_be32(drbd_state_to_int(val.i));
return drbd_send_cmd(mdev,USE_DATA_SOCKET,StateChgRequest,
(Drbd_Header*)&p,sizeof(p));
@@ -3179,15 +3179,15 @@ _dump_packet(drbd_dev *mdev, struct sock
break;
case ReportState:
- v.i = be32_to_cpu(p->State.state);
+ v.i = int_to_drbd_state(be32_to_cpu(p->State.state));
m.i = 0xffffffff;
dump_st(tmp,sizeof(tmp),m,v);
INFOP("%s (s %x {%s})\n", cmdname(cmd), v.i, tmp);
break;
case StateChgRequest:
- m.i = be32_to_cpu(p->ReqState.mask);
- v.i = be32_to_cpu(p->ReqState.val);
+ m.i = int_to_drbd_state(be32_to_cpu(p->ReqState.mask));
+ v.i = int_to_drbd_state(be32_to_cpu(p->ReqState.val));
dump_st(tmp,sizeof(tmp),m,v);
INFOP("%s (m %x v %x {%s})\n", cmdname(cmd), m.i, v.i, tmp);
break;
Index: linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_receiver.c
===================================================================
--- linux-2.6.21_mvlcge500.orig/drivers/block/drbd/drbd_receiver.c
+++ linux-2.6.21_mvlcge500/drivers/block/drbd/drbd_receiver.c
@@ -2369,8 +2369,8 @@ STATIC int receive_req_state(drbd_dev *m
if (drbd_recv(mdev, h->payload, h->length) != h->length)
return FALSE;
- mask.i = be32_to_cpu(p->mask);
- val.i = be32_to_cpu(p->val);
+ mask.i = int_to_drbd_state(be32_to_cpu(p->mask));
+ val.i = int_to_drbd_state(be32_to_cpu(p->val));
if (test_bit(DISCARD_CONCURRENT,&mdev->flags)) drbd_state_lock(mdev);
@@ -2401,7 +2401,7 @@ STATIC int receive_state(drbd_dev *mdev,
nconn = mdev->state.conn;
if (nconn == WFReportParams ) nconn = Connected;
- peer_state.i = be32_to_cpu(p->state);
+ peer_state.i = int_to_drbd_state(be32_to_cpu(p->state));
if (mdev->p_uuid && mdev->state.conn <= Connected &&
inc_local_if_state(mdev,Negotiating) &&
Index: linux-2.6.21_mvlcge500/include/linux/drbd_config.h
===================================================================
--- linux-2.6.21_mvlcge500.orig/include/linux/drbd_config.h
+++ linux-2.6.21_mvlcge500/include/linux/drbd_config.h
@@ -24,7 +24,7 @@ extern const char * drbd_buildtag(void);
#define REL_VERSION "8.0.3"
#define API_VERSION 86
-#define PRO_VERSION 86
+#define PRO_VERSION 88
// undef if you need the workaround in drbd_receiver
#define HAVE_UML_TO_VIRT 1
next reply other threads:[~2007-11-26 13:55 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-26 16:32 Maxim Uvarov [this message]
2007-11-26 15:06 ` [Drbd-dev] [DRBD][PATCH] drbd_bitfild_endian.patch Lars Ellenberg
2007-11-26 19:28 ` Maxim Uvarov
[not found] ` <474C12E0.6020306@ru.mvista.com>
2007-11-27 10:55 ` Lars Ellenberg
2007-12-03 16:52 ` Philipp Reisner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=474AF52C.6090409@ru.mvista.com \
--to=muvarov@ru.mvista.com \
--cc=drbd-dev@lists.linbit.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox