summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c46
-rw-r--r--sys/cam/ctl/ctl_ha.c35
-rw-r--r--sys/cam/ctl/ctl_ha.h1
-rw-r--r--sys/cam/ctl/ctl_io.h24
4 files changed, 99 insertions, 7 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 3dee0aa..c172afb 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -717,8 +717,20 @@ ctl_isc_ha_link_up(struct ctl_softc *softc)
{
struct ctl_port *port;
struct ctl_lun *lun;
+ union ctl_ha_msg msg;
int i;
+ /* Announce this node parameters to peer for validation. */
+ msg.login.msg_type = CTL_MSG_LOGIN;
+ msg.login.version = CTL_HA_VERSION;
+ msg.login.ha_mode = softc->ha_mode;
+ msg.login.ha_id = softc->ha_id;
+ msg.login.max_luns = CTL_MAX_LUNS;
+ msg.login.max_ports = CTL_MAX_PORTS;
+ msg.login.max_init_per_port = CTL_MAX_INIT_PER_PORT;
+ ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg.login, sizeof(msg.login),
+ M_WAITOK);
+
STAILQ_FOREACH(port, &softc->port_list, links) {
ctl_isc_announce_port(port);
for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) {
@@ -1001,6 +1013,36 @@ ctl_isc_iid_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
port->wwpn_iid[iid].name = NULL;
}
+static void
+ctl_isc_login(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
+{
+
+ if (msg->login.version != CTL_HA_VERSION) {
+ printf("CTL HA peers have different versions %d != %d\n",
+ msg->login.version, CTL_HA_VERSION);
+ ctl_ha_msg_abort(CTL_HA_CHAN_CTL);
+ return;
+ }
+ if (msg->login.ha_mode != softc->ha_mode) {
+ printf("CTL HA peers have different ha_mode %d != %d\n",
+ msg->login.ha_mode, softc->ha_mode);
+ ctl_ha_msg_abort(CTL_HA_CHAN_CTL);
+ return;
+ }
+ if (msg->login.ha_id == softc->ha_id) {
+ printf("CTL HA peers have same ha_id %d\n", msg->login.ha_id);
+ ctl_ha_msg_abort(CTL_HA_CHAN_CTL);
+ return;
+ }
+ if (msg->login.max_luns != CTL_MAX_LUNS ||
+ msg->login.max_ports != CTL_MAX_PORTS ||
+ msg->login.max_init_per_port != CTL_MAX_INIT_PER_PORT) {
+ printf("CTL HA peers have different limits\n");
+ ctl_ha_msg_abort(CTL_HA_CHAN_CTL);
+ return;
+ }
+}
+
/*
* ISC (Inter Shelf Communication) event handler. Events from the HA
* subsystem come in here.
@@ -1277,9 +1319,13 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
case CTL_MSG_IID_SYNC:
ctl_isc_iid_sync(softc, msg, param);
break;
+ case CTL_MSG_LOGIN:
+ ctl_isc_login(softc, msg, param);
+ break;
default:
printf("Received HA message of unknown type %d\n",
msg->hdr.msg_type);
+ ctl_ha_msg_abort(CTL_HA_CHAN_CTL);
break;
}
if (msg != &msgbuf)
diff --git a/sys/cam/ctl/ctl_ha.c b/sys/cam/ctl/ctl_ha.c
index 13cb2e1..03401ae 100644
--- a/sys/cam/ctl/ctl_ha.c
+++ b/sys/cam/ctl/ctl_ha.c
@@ -283,8 +283,9 @@ ctl_ha_rx_thread(void *arg)
else
next = sizeof(wire_hdr);
SOCKBUF_LOCK(&so->so_rcv);
- while (sbavail(&so->so_rcv) < next) {
- if (softc->ha_connected == 0 || so->so_error ||
+ while (sbavail(&so->so_rcv) < next || softc->ha_disconnect) {
+ if (softc->ha_connected == 0 || softc->ha_disconnect ||
+ so->so_error ||
(so->so_rcv.sb_state & SBS_CANTRCVMORE)) {
goto errout;
}
@@ -541,6 +542,18 @@ ctl_ha_listen(struct ha_softc *softc)
printf("%s: REUSEADDR setting failed %d\n",
__func__, error);
}
+ bzero(&opt, sizeof(struct sockopt));
+ opt.sopt_dir = SOPT_SET;
+ opt.sopt_level = SOL_SOCKET;
+ opt.sopt_name = SO_REUSEPORT;
+ opt.sopt_val = &val;
+ opt.sopt_valsize = sizeof(val);
+ val = 1;
+ error = sosetopt(softc->ha_lso, &opt);
+ if (error) {
+ printf("%s: REUSEPORT setting failed %d\n",
+ __func__, error);
+ }
SOCKBUF_LOCK(&softc->ha_lso->so_rcv);
soupcall_set(softc->ha_lso, SO_RCV, ctl_ha_lupcall, softc);
SOCKBUF_UNLOCK(&softc->ha_lso->so_rcv);
@@ -572,7 +585,8 @@ ctl_ha_conn_thread(void *arg)
while (1) {
if (softc->ha_disconnect || softc->ha_shutdown) {
ctl_ha_close(softc);
- ctl_ha_lclose(softc);
+ if (softc->ha_disconnect == 2 || softc->ha_shutdown)
+ ctl_ha_lclose(softc);
softc->ha_disconnect = 0;
if (softc->ha_shutdown)
break;
@@ -666,7 +680,7 @@ ctl_ha_peer_sysctl(SYSCTL_HANDLER_ARGS)
sa->sin_addr.s_addr =
htonl((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
}
- softc->ha_disconnect = 1;
+ softc->ha_disconnect = 2;
softc->ha_wakeup = 1;
mtx_unlock(&softc->ha_lock);
wakeup(&softc->ha_wakeup);
@@ -811,6 +825,19 @@ ctl_ha_msg_send(ctl_ha_channel channel, const void *addr, size_t len,
return (ctl_ha_msg_send2(channel, addr, len, NULL, 0, wait));
}
+ctl_ha_status
+ctl_ha_msg_abort(ctl_ha_channel channel)
+{
+ struct ha_softc *softc = &ha_softc;
+
+ mtx_lock(&softc->ha_lock);
+ softc->ha_disconnect = 1;
+ softc->ha_wakeup = 1;
+ mtx_unlock(&softc->ha_lock);
+ wakeup(&softc->ha_wakeup);
+ return (CTL_HA_STATUS_SUCCESS);
+}
+
/*
* Allocate a data transfer request structure.
*/
diff --git a/sys/cam/ctl/ctl_ha.h b/sys/cam/ctl/ctl_ha.h
index 0d2c011..f38f640 100644
--- a/sys/cam/ctl/ctl_ha.h
+++ b/sys/cam/ctl/ctl_ha.h
@@ -125,6 +125,7 @@ ctl_ha_status ctl_ha_msg_send(ctl_ha_channel channel, const void *addr,
size_t len, int wait);
ctl_ha_status ctl_ha_msg_send2(ctl_ha_channel channel, const void *addr,
size_t len, const void *addr2, size_t len2, int wait);
+ctl_ha_status ctl_ha_msg_abort(ctl_ha_channel channel);
ctl_ha_status ctl_ha_msg_deregister(ctl_ha_channel channel);
struct ctl_ha_dt_req * ctl_dt_req_alloc(void);
diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h
index 805a4ce..a9ed1d0 100644
--- a/sys/cam/ctl/ctl_io.h
+++ b/sys/cam/ctl/ctl_io.h
@@ -197,6 +197,7 @@ typedef enum {
CTL_MSG_PORT_SYNC, /* Information about port. */
CTL_MSG_LUN_SYNC, /* Information about LUN. */
CTL_MSG_IID_SYNC, /* Information about initiator. */
+ CTL_MSG_LOGIN, /* Information about HA peer. */
CTL_MSG_FAILOVER /* Fake, never sent though the wire */
} ctl_msg_type;
@@ -358,6 +359,25 @@ struct ctl_taskio {
uint8_t task_resp[3];/* Response information */
};
+
+/*
+ * HA link messages.
+ */
+#define CTL_HA_VERSION 1
+
+/*
+ * Used for CTL_MSG_LOGIN.
+ */
+struct ctl_ha_msg_login {
+ ctl_msg_type msg_type;
+ int version;
+ int ha_mode;
+ int ha_id;
+ int max_luns;
+ int max_ports;
+ int max_init_per_port;
+};
+
typedef enum {
CTL_PR_REG_KEY,
CTL_PR_UNREG_KEY,
@@ -523,16 +543,14 @@ union ctl_ha_msg {
struct ctl_ha_msg_port port;
struct ctl_ha_msg_lun lun;
struct ctl_ha_msg_iid iid;
+ struct ctl_ha_msg_login login;
};
-
struct ctl_prio {
struct ctl_io_hdr io_hdr;
struct ctl_ha_msg_pr pr_msg;
};
-
-
union ctl_io {
struct ctl_io_hdr io_hdr; /* common to all I/O types */
struct ctl_scsiio scsiio; /* Normal SCSI commands */
OpenPOWER on IntegriCloud