[DRBD-cvs] r1418 - in trunk/drbd: . linux
drbd-user@lists.linbit.com
drbd-user@lists.linbit.com
Tue, 13 Jul 2004 12:05:25 +0200 (CEST)
Author: phil
Date: 2004-07-13 12:05:24 +0200 (Tue, 13 Jul 2004)
New Revision: 1418
Modified:
trunk/drbd/drbd_int.h
trunk/drbd/drbd_main.c
trunk/drbd/drbd_receiver.c
trunk/drbd/linux/drbd_config.h
Log:
[patch by LGE]
Implemented the handshake packet. -> In order to allow rolling
updates with further protocol changes...
Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h 2004-07-13 09:50:11 UTC (rev 1417)
+++ trunk/drbd/drbd_int.h 2004-07-13 10:05:24 UTC (rev 1418)
@@ -358,10 +358,15 @@
MAX_CMD,
MayIgnore = 0x100, // Flag only to test if (cmd > MayIgnore) ...
MAX_OPT_CMD,
+
+ HandShake = 0xfffe // FIXED for the next century!
} Drbd_Packet_Cmd;
static inline const char* cmdname(Drbd_Packet_Cmd cmd)
{
+ /* THINK may need to become several global tables
+ * when we want to support more than
+ * one PRO_VERSION */
static const char *cmdnames[] = {
[Data] = "Data",
[DataReply] = "DataReply",
@@ -385,7 +390,8 @@
[BarrierAck] = "BarrierAck"
};
- if(cmd < 0 || cmd > MAX_CMD) return "Unknown";
+ if (cmd == HandShake) return "HandShake";
+ if (Data > cmd || cmd >= MAX_CMD) return "Unknown";
return cmdnames[cmd];
}
@@ -406,6 +412,7 @@
u16 length; // bytes of data after this header
char payload[0];
} Drbd_Header __attribute((packed));
+// 8 bytes. packet FIXED for the next century!
/*
* short commands, packets without payload, plain Drbd_Header:
@@ -450,12 +457,27 @@
/*
* commands with their own struct for additional fields:
+ * HandShake
* Barrier
* BarrierAck
* SyncParam
* ReportParams
*/
+
typedef struct {
+ Drbd_Header head; // 8 bytes
+ u32 protocol_version;
+ u32 feature_flags;
+
+ /* should be more than enough for future enhancements
+ * for now, feature_flags and the reserverd array shall be zero.
+ */
+
+ u64 reserverd[8];
+} Drbd_HandShake_Packet __attribute((packed));
+// 80 bytes, FIXED for the next century
+
+typedef struct {
Drbd_Header head;
u32 barrier; // may be 0 or a barrier number
u32 pad; //make sure packet is a multiple of 8 Byte
@@ -505,6 +527,7 @@
typedef union {
Drbd_Header head;
+ Drbd_HandShake_Packet HandShake;
Drbd_Data_Packet Data;
Drbd_BlockAck_Packet BlockAck;
Drbd_Barrier_Packet Barrier;
@@ -782,6 +805,9 @@
extern int drbd_send(drbd_dev *mdev, struct socket *sock,
void* buf, size_t size, unsigned msg_flags);
extern int drbd_send_param(drbd_dev *mdev, int flags);
+extern int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+ Drbd_Packet_Cmd cmd, Drbd_Header *h,
+ size_t size, unsigned msg_flags);
extern int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
Drbd_Packet_Cmd cmd, Drbd_Header *h, size_t size);
extern int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc);
@@ -1348,6 +1374,10 @@
char *sockname = sock == mdev->meta.socket ? "meta" : "data";
int cmd = (recv == 2) ? p->head.command : be16_to_cpu(p->head.command);
switch (cmd) {
+ case HandShake:
+ INFOP("%s (%u)\n", be32_to_cpu(p->HandShake.protocol_version));
+ break;
+
case Ping:
case PingAck:
case BecomeSyncTarget:
Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c 2004-07-13 09:50:11 UTC (rev 1417)
+++ trunk/drbd/drbd_main.c 2004-07-13 10:05:24 UTC (rev 1418)
@@ -600,7 +600,7 @@
UNLOCK_SIGMASK(current,flags);
}
-STATIC int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
Drbd_Packet_Cmd cmd, Drbd_Header *h,
size_t size, unsigned msg_flags)
{
@@ -1617,6 +1617,7 @@
SZO(wait_queue_head_t);
SZO(spinlock_t);
SZO(Drbd_Header);
+ SZO(Drbd_HandShake_Packet);
SZO(Drbd_Barrier_Packet);
SZO(Drbd_BarrierAck_Packet);
SZO(Drbd_SyncParam_Packet);
@@ -1628,6 +1629,12 @@
return -EBUSY;
#endif
+ if (sizeof(Drbd_HandShake_Packet) != 80) {
+ printk(KERN_ERR DEVICE_NAME
+ ": never change the size or layout of the HandShake packet.\n");
+ return -EINVAL;
+ }
+
if (1 > minor_count||minor_count > 255) {
printk(KERN_ERR DEVICE_NAME
": invalid minor_count (%d)\n",minor_count);
Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c 2004-07-13 09:50:11 UTC (rev 1417)
+++ trunk/drbd/drbd_receiver.c 2004-07-13 10:05:24 UTC (rev 1418)
@@ -600,7 +600,6 @@
return rv;
}
-
STATIC struct socket *drbd_try_connect(drbd_dev *mdev)
{
int err;
@@ -656,6 +655,8 @@
return sock;
}
+STATIC int drbd_do_handshake(drbd_dev *mdev);
+
int drbd_connect(drbd_dev *mdev)
{
struct socket *sock,*msock;
@@ -712,8 +713,12 @@
// FIXME fold to limits. should be done in drbd_ioctl
sock->sk->SK_(sndbuf) = mdev->conf.sndbuf_size;
sock->sk->SK_(rcvbuf) = mdev->conf.sndbuf_size;
- sock->sk->SK_(sndtimeo) = mdev->conf.timeout*HZ/20;
- sock->sk->SK_(rcvtimeo) = MAX_SCHEDULE_TIMEOUT;
+ /* NOT YET ...
+ * sock->sk->SK_(sndtimeo) = mdev->conf.timeout*HZ/20;
+ * sock->sk->SK_(rcvtimeo) = MAX_SCHEDULE_TIMEOUT;
+ * THINK HandShake timeout, hardcoded for now: */
+ sock->sk->SK_(sndtimeo) =
+ sock->sk->SK_(rcvtimeo) = 2*HZ;
sock->sk->SK_(userlocks) |= SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK;
msock->sk->SK_(priority)=TC_PRIO_INTERACTIVE;
@@ -728,9 +733,15 @@
mdev->last_received = jiffies;
set_cstate(mdev,WFReportParams);
-
D_ASSERT(mdev->asender.task == NULL);
+ if (!drbd_do_handshake(mdev)) {
+ return 0;
+ }
+
+ sock->sk->SK_(sndtimeo) = mdev->conf.timeout*HZ/20;
+ sock->sk->SK_(rcvtimeo) = MAX_SCHEDULE_TIMEOUT;
+
drbd_thread_start(&mdev->asender);
drbd_send_param(mdev,0);
@@ -1811,6 +1822,85 @@
INFO("Connection lost.\n");
}
+/*
+ * we hereby assure that we always support the drbd dialects
+ * PRO_VERSION and (PRO_VERSION -1), allowing for rolling upgrades
+ *
+ * feature flags and the reserved array should be enough room for future
+ * enhancements of the handshake protocol, and possible plugins...
+ *
+ * for now, they are expected to be zero, but ignored.
+ */
+int drbd_send_handshake(drbd_dev *mdev)
+{
+ // ASSERT current == mdev->receiver ...
+ Drbd_HandShake_Packet *p = &mdev->data.sbuf.HandShake;
+ int ok;
+
+ down(&mdev->data.mutex);
+ memset(p,0,sizeof(*p));
+ p->protocol_version = cpu_to_be32(PRO_VERSION);
+ ok = _drbd_send_cmd( mdev, mdev->data.socket, HandShake,
+ (Drbd_Header *)p, sizeof(*p), 0 );
+ up(&mdev->data.mutex);
+ return ok;
+}
+
+STATIC int drbd_do_handshake(drbd_dev *mdev)
+{
+ // ASSERT current == mdev->receiver ...
+ Drbd_HandShake_Packet *p = &mdev->data.rbuf.HandShake;
+ const int expect = sizeof(Drbd_HandShake_Packet)-sizeof(Drbd_Header);
+ int rv;
+
+ rv = drbd_send_handshake(mdev);
+ if (!rv) return 0;
+
+ rv = drbd_recv_header(mdev,&p->head);
+ if (!rv) return 0;
+
+ if (p->head.command == ReportParams) {
+ ERR("expected HandShake packet, received ReportParams...\n");
+ ERR("peer probaly runs some incompatible 0.7 -preX version\n");
+ return 0;
+ } else if (p->head.command != HandShake) {
+ ERR( "expected HandShake packet, received: %s (0x%04x)\n",
+ cmdname(p->head.command), p->head.command );
+ return 0;
+ }
+
+ if (p->head.length != expect) {
+ ERR( "expected HandShake length: %u, received: %u\n",
+ expect, p->head.length );
+ return 0;
+ }
+
+ rv = drbd_recv(mdev, &p->head.payload, expect);
+
+ if (rv != expect) {
+ ERR("short read receiving handshake packet: l=%u\n", rv);
+ return 0;
+ }
+
+ dump_packet(mdev,mdev->data.socket,2,&mdev->data.rbuf, __FILE__, __LINE__);
+
+ p->protocol_version = be32_to_cpu(p->protocol_version);
+
+ if ( p->protocol_version == PRO_VERSION ) {
+ INFO( "Handshake successful: DRBD Protocol version %u\n",
+ p->protocol_version );
+ } /* else if ( p->protocol_version == (PRO_VERSION-1) ) {
+ // not yet; but next time :)
+ } */ else {
+ ERR( "incompatible DRBD dialects: "
+ "I support %u, peer wants %u\n",
+ PRO_VERSION, p->protocol_version );
+ return 0;
+ }
+
+ return 1;
+}
+
int drbdd_init(struct Drbd_thread *thi)
{
drbd_dev *mdev = thi->mdev;
@@ -1823,6 +1913,12 @@
while (TRUE) {
if (!drbd_connect(mdev)) {
WARN("Discarding network configuration.\n");
+ /* FIXME DISKLESS StandAlone
+ * does not make much sense...
+ * drbd_disconnect should set cstate properly...
+ */
+ drbd_disconnect(mdev);
+ set_cstate(mdev,StandAlone);
break;
}
if (get_t_state(thi) == Exiting) break;
Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h 2004-07-13 09:50:11 UTC (rev 1417)
+++ trunk/drbd/linux/drbd_config.h 2004-07-13 10:05:24 UTC (rev 1418)
@@ -22,9 +22,7 @@
#define REL_VERSION "0.7-pre10 cvs $Date: 2004/07/09 18:29:24 $"
#define API_VERSION 74
-#define PRO_VERSION 73 /* actually already 74, but I expect some more
- * protocol changes, maybe even an additional packet
- * soonish... */
+#define PRO_VERSION 74
//#define DBG_ALL_SYMBOLS // no static functs, improves quality of OOPS traces