Page MenuHomeFreeBSD

D26542.id.diff
No OneTemporary

D26542.id.diff

Index: sbin/ggate/ggatec/ggatec.8
===================================================================
--- sbin/ggate/ggatec/ggatec.8
+++ sbin/ggate/ggatec/ggatec.8
@@ -33,6 +33,7 @@
.Sh SYNOPSIS
.Nm
.Cm create
+.Op Fl 0 | Fl 1
.Op Fl n
.Op Fl v
.Op Fl o Cm ro | wo | rw
@@ -47,6 +48,7 @@
.Ar path
.Nm
.Cm rescue
+.Op Fl 0 | Fl 1
.Op Fl n
.Op Fl v
.Op Fl o Cm ro | wo | rw
@@ -102,6 +104,19 @@
.Pp
Available options:
.Bl -tag -width ".Fl s Cm ro | wo | rw"
+.It Fl 0
+Use
+.Nm ggate
+protocol version 0 only.
+Protocol version 0 appeared in FreeBSD 5.3-RELEASE.
+.It Fl 1
+Use
+.Nm ggate
+protocol version 1 only.
+Protocol version 1 appeared in FreeBSD 13.0-RELEASE to simplify
+.Nm ggate
+connection negotiation.
+The default is to try version 1 and then to retry with version 0.
.It Fl f
Forcibly destroy
.Nm ggate
Index: sbin/ggate/ggatec/ggatec.c
===================================================================
--- sbin/ggate/ggatec/ggatec.c
+++ sbin/ggate/ggatec/ggatec.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
@@ -75,14 +76,20 @@
static pthread_t sendtd, recvtd;
static int reconnect;
+/* bitmask of protocol versions to attempt connecting. */
+static int try_version = (1 << GGATE_VERSION_1) | (1 << GGATE_VERSION_0);
+
+static bool g_gatec_connect_v0(void);
+static bool g_gatec_connect_v1(void);
+
static void
usage(void)
{
-
- fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] [-p port] "
+ fprintf(stderr, "geom gate protocol version %d\n", G_GATE_VERSION);
+ fprintf(stderr, "usage: %s create [-0|-1] [-nv] [-o <ro|wo|rw>] [-p port] "
"[-q queue_size] [-R rcvbuf] [-S sndbuf] [-s sectorsize] "
"[-t timeout] [-u unit] <host> <path>\n", getprogname());
- fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] [-p port] "
+ fprintf(stderr, " %s rescue [-0|-1] [-nv] [-o <ro|wo|rw>] [-p port] "
"[-R rcvbuf] [-S sndbuf] <-u unit> <host> <path>\n", getprogname());
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname());
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname());
@@ -283,10 +290,11 @@
/*
* Create and send version packet.
*/
- g_gate_log(LOG_DEBUG, "Sending version packet.");
assert(strlen(GGATE_MAGIC) == sizeof(ver.gv_magic));
bcopy(GGATE_MAGIC, ver.gv_magic, sizeof(ver.gv_magic));
- ver.gv_version = GGATE_VERSION;
+ ver.gv_version = dir ? GGATE_VERSION_0 : GGATE_VERSION_1;
+ g_gate_log(LOG_DEBUG, "Sending version %u packet.",
+ ver.gv_version);
ver.gv_error = 0;
g_gate_swap2n_version(&ver);
if (g_gate_send(sfd, &ver, sizeof(ver), MSG_NOSIGNAL) == -1) {
@@ -370,8 +378,8 @@
err(EXIT_FAILURE, "Cannot daemonize");
}
-static int
-g_gatec_connect(void)
+static bool
+g_gatec_connect_v0(void)
{
token = arc4random();
@@ -381,17 +389,48 @@
*/
recvfd = handshake(GGATE_FLAG_SEND);
if (recvfd == -1)
- return (0);
+ return (false);
/*
* Our send descriptor is connected to the receive descriptor on the
* server side.
*/
sendfd = handshake(GGATE_FLAG_RECV);
if (sendfd == -1)
- return (0);
- return (1);
+ return (false);
+ return (true);
}
+static bool
+g_gatec_connect_v1(void)
+{
+
+ token = arc4random();
+ recvfd = sendfd = handshake(0);
+ if (sendfd == -1)
+ return (false);
+ return (true);
+}
+
+static bool
+g_gatec_connect(void)
+{
+
+ if (try_version & (1 << GGATE_VERSION_1)) {
+ if (g_gatec_connect_v1()) {
+ try_version = 1 << GGATE_VERSION_1;
+ return (true);
+ }
+ }
+ if (try_version & (1 << GGATE_VERSION_0)) {
+ if (g_gatec_connect_v0()) {
+ try_version = 1 << GGATE_VERSION_0;
+ return (true);
+ }
+ }
+ try_version = 0;
+ return (false);
+}
+
static void
g_gatec_start(void)
{
@@ -408,7 +447,8 @@
send_thread(NULL);
/* Disconnected. */
close(sendfd);
- close(recvfd);
+ if (sendfd != recvfd)
+ close(recvfd);
}
static void
@@ -510,10 +550,14 @@
for (;;) {
int ch;
- ch = getopt(argc, argv, "fno:p:q:R:S:s:t:u:v");
+ ch = getopt(argc, argv, "01fno:p:q:R:S:s:t:u:v");
if (ch == -1)
break;
switch (ch) {
+ case '0':
+ case '1':
+ try_version = (1 << (ch - '0'));
+ break;
case 'f':
if (action != DESTROY)
usage();
Index: sbin/ggate/ggated/ggated.c
===================================================================
--- sbin/ggate/ggated/ggated.c
+++ sbin/ggate/ggated/ggated.c
@@ -51,6 +51,7 @@
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -64,6 +65,7 @@
#define GGATED_EXPORT_FILE "/etc/gg.exports"
struct ggd_connection {
+ int c_version;
off_t c_mediasize;
unsigned c_sectorsize;
unsigned c_flags; /* flags (RO/RW) */
@@ -111,6 +113,8 @@
static void *disk_thread(void *arg);
static void *send_thread(void *arg);
+static void connection_remove(struct ggd_connection *conn);
+
static void
usage(void)
{
@@ -415,17 +419,8 @@
time(&now);
LIST_FOREACH_SAFE(conn, &connections, c_next, tconn) {
- if (now - conn->c_birthtime > 10) {
- LIST_REMOVE(conn, c_next);
- g_gate_log(LOG_NOTICE,
- "Connection from %s [%s] removed.",
- ip2str(conn->c_srcip), conn->c_path);
- close(conn->c_diskfd);
- close(conn->c_sendfd);
- close(conn->c_recvfd);
- free(conn->c_path);
- free(conn);
- }
+ if (now - conn->c_birthtime > 10)
+ connection_remove(conn);
}
}
@@ -442,7 +437,7 @@
}
static struct ggd_connection *
-connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd)
+connection_new(int ver, struct g_gate_cinit *cinit, struct sockaddr *s, int sfd)
{
struct ggd_connection *conn;
in_addr_t ip;
@@ -458,6 +453,7 @@
conn = malloc(sizeof(*conn));
if (conn == NULL)
return (NULL);
+ conn->c_version = ver;
conn->c_path = strdup(cinit->gc_path);
if (conn->c_path == NULL) {
free(conn);
@@ -467,15 +463,20 @@
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr);
conn->c_srcip = ip;
conn->c_diskfd = conn->c_sendfd = conn->c_recvfd = -1;
- if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0)
- conn->c_sendfd = sfd;
- else
- conn->c_recvfd = sfd;
conn->c_mediasize = 0;
conn->c_sectorsize = 0;
time(&conn->c_birthtime);
conn->c_flags = cinit->gc_flags;
- LIST_INSERT_HEAD(&connections, conn, c_next);
+ if (conn->c_version == GGATE_VERSION_1) {
+ conn->c_sendfd = sfd;
+ conn->c_recvfd = sfd;
+ } else if (conn->c_version == GGATE_VERSION_0) {
+ if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0)
+ conn->c_sendfd = sfd;
+ else
+ conn->c_recvfd = sfd;
+ LIST_INSERT_HEAD(&connections, conn, c_next);
+ }
g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(ip),
conn->c_path);
return (conn);
@@ -518,14 +519,15 @@
connection_remove(struct ggd_connection *conn)
{
- LIST_REMOVE(conn, c_next);
+ if (conn->c_version == GGATE_VERSION_0)
+ LIST_REMOVE(conn, c_next);
g_gate_log(LOG_DEBUG, "Connection removed [%s %s].",
ip2str(conn->c_srcip), conn->c_path);
if (conn->c_diskfd != -1)
close(conn->c_diskfd);
if (conn->c_sendfd != -1)
close(conn->c_sendfd);
- if (conn->c_recvfd != -1)
+ if (conn->c_recvfd != -1 && conn->c_sendfd != conn->c_recvfd)
close(conn->c_recvfd);
free(conn->c_path);
free(conn);
@@ -845,7 +847,11 @@
g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(ip));
}
-static int
+/*
+ * handshake() returns true if sfd is closed; otherwise false so that caller
+ * has to close the sfd.
+ */
+static bool
handshake(struct sockaddr *from, int sfd)
{
struct g_gate_version ver;
@@ -864,17 +870,23 @@
g_gate_swap2h_version(&ver);
if (data != sizeof(ver)) {
g_gate_log(LOG_WARNING, "Malformed version packet.");
- return (0);
+ return (false);
}
g_gate_log(LOG_DEBUG, "Version packet received.");
if (memcmp(ver.gv_magic, GGATE_MAGIC, strlen(GGATE_MAGIC)) != 0) {
g_gate_log(LOG_WARNING, "Invalid magic field.");
- return (0);
+ return (false);
}
- if (ver.gv_version != GGATE_VERSION) {
- g_gate_log(LOG_WARNING, "Version %u is not supported.",
+ switch (ver.gv_version) {
+ case GGATE_VERSION_0:
+ case GGATE_VERSION_1:
+ g_gate_log(LOG_DEBUG, "Received version %" PRIu16,
ver.gv_version);
- return (0);
+ break;
+ default:
+ g_gate_log(LOG_WARNING, "Version %u protocol is not supported.",
+ ver.gv_version);
+ return (false);
}
ver.gv_error = 0;
g_gate_swap2n_version(&ver);
@@ -883,7 +895,7 @@
if (data == -1) {
sendfail(sfd, errno, "Error while sending version packet: %s.",
strerror(errno));
- return (0);
+ return (false);
}
/*
@@ -897,7 +909,18 @@
return (0);
}
g_gate_log(LOG_DEBUG, "Initial packet received.");
- conn = connection_find(&cinit);
+ switch (ver.gv_version) {
+ case GGATE_VERSION_0:
+ conn = connection_find(&cinit);
+ break;
+ case GGATE_VERSION_1:
+ conn = NULL;
+ break;
+ default:
+ g_gate_log(LOG_WARNING, "Version %u is not supported.",
+ ver.gv_version);
+ return (false);
+ }
if (conn != NULL) {
/*
* Connection should already exists.
@@ -906,17 +929,17 @@
(unsigned long)conn->c_token);
if (connection_add(conn, &cinit, from, sfd) == -1) {
connection_remove(conn);
- return (0);
+ return (false);
}
} else {
/*
* New connection, allocate space.
*/
- conn = connection_new(&cinit, from, sfd);
+ conn = connection_new(ver.gv_version, &cinit, from, sfd);
if (conn == NULL) {
sendfail(sfd, ENOMEM,
"Cannot allocate new connection.");
- return (0);
+ return (false);
}
g_gate_log(LOG_DEBUG, "New connection created (token=%lu).",
(unsigned long)conn->c_token);
@@ -926,7 +949,7 @@
if (ex == NULL) {
sendfail(sfd, errno, NULL);
connection_remove(conn);
- return (0);
+ return (false);
}
if (conn->c_mediasize == 0) {
conn->c_mediasize = g_gate_mediasize(conn->c_diskfd);
@@ -944,14 +967,23 @@
if (data == -1) {
sendfail(sfd, errno, "Error while sending initial packet: %s.",
strerror(errno));
- return (0);
+ return (false);
}
- if (connection_ready(conn)) {
+ switch (conn->c_version) {
+ case GGATE_VERSION_0:
+ if (connection_ready(conn)) {
+ connection_launch(conn);
+ connection_remove(conn);
+ }
+ return (true);
+ case GGATE_VERSION_1:
connection_launch(conn);
connection_remove(conn);
+ return (true);
+ default:
+ return (false);
}
- return (1);
}
static void
Index: sbin/ggate/shared/ggate.h
===================================================================
--- sbin/ggate/shared/ggate.h
+++ sbin/ggate/shared/ggate.h
@@ -42,11 +42,25 @@
#define G_GATE_TIMEOUT 0
#define GGATE_MAGIC "GEOM_GATE "
-#define GGATE_VERSION 0
+#define GGATE_VERSION_0 0
+#define GGATE_VERSION_1 1
+#define GGATE_VERSION GGATE_VERSION_1
+/*
+ * Protocol version 0 uses 2 TCP connections.
+ * ggatec initiates 2 handshakes for a single session and establishes
+ * 2 TCP connections. ggated waits for the 2nd handshake to complete before
+ * forking.
+ *
+ * Protocol version 1 uses 1 TCP connection.
+ * ggatec only initiates 1 handshake and ggated immediately forks. A parent
+ * ggated process does not cache connections for connection negotiations.
+ */
#define GGATE_FLAG_RDONLY 0x0001
#define GGATE_FLAG_WRONLY 0x0002
/*
+ * Protocol version 0 only.
+ *
* If neither the GGATE_FLAG_SEND nor the GGATE_FLAG_RECV flag is
* set - this is initial connection.
* If GGATE_FLAG_SEND flag is set - this is socket to send data.

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 28, 1:21 AM (5 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30451784
Default Alt Text
D26542.id.diff (11 KB)

Event Timeline