changeset 10377:596c39d50e2a

6752302 in.mpathd needs non-blocking ICMP probe sockets
author George Shepherd <George.Shepherd@Sun.COM>
date Tue, 25 Aug 2009 08:25:56 -0700
parents 803e1af65252
children bca9668e9ba5
files usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_probe.c usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_tables.c
diffstat 2 files changed, 46 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_probe.c	Tue Aug 25 09:49:46 2009 +0800
+++ b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_probe.c	Tue Aug 25 08:25:56 2009 -0700
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -221,7 +220,8 @@
 	struct sockaddr_storage targ;	/* target address */
 	uint_t	targaddrlen;		/* targed address length */
 	int	pr_ndx;			/* probe index in pii->pii_probes[] */
-	boolean_t sent = _B_TRUE;
+	boolean_t sent = _B_FALSE;
+	int	rval;
 
 	if (debug & D_TARGET) {
 		logdebug("probe(%s %s %d %lld)\n", AF_STR(pii->pii_af),
@@ -297,10 +297,19 @@
 	 */
 	sent_hrtime = gethrtime();
 	(void) gettimeofday(&sent_tv, NULL);
-	if (sendto(pii->pii_probe_sock, &probe_pkt, sizeof (probe_pkt), 0,
-	    (struct sockaddr *)&targ, targaddrlen) != sizeof (probe_pkt)) {
+	rval = sendto(pii->pii_probe_sock, &probe_pkt, sizeof (probe_pkt), 0,
+	    (struct sockaddr *)&targ, targaddrlen);
+	/*
+	 * If the send would block, this may either be transient or a hang in a
+	 * lower layer. We pretend the probe was actually sent, the daemon will
+	 * not see a reply to the probe and will fail the interface if normal
+	 * failure detection criteria are met.
+	 */
+	if (rval == sizeof (probe_pkt) ||
+	    (rval == -1 && errno == EWOULDBLOCK)) {
+		sent = _B_TRUE;
+	} else {
 		logperror_pii(pii, "probe: probe sendto");
-		sent = _B_FALSE;
 	}
 
 	/*
--- a/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_tables.c	Tue Aug 25 09:49:46 2009 +0800
+++ b/usr/src/cmd/cmd-inet/usr.lib/in.mpathd/mpd_tables.c	Tue Aug 25 08:25:56 2009 -0700
@@ -863,6 +863,7 @@
 	int off = 0;
 	int on = 1;
 	struct	sockaddr_in6	testaddr;
+	int flags;
 
 	/*
 	 * Open a raw socket with ICMPv6 protocol.
@@ -881,6 +882,21 @@
 		return (_B_FALSE);
 	}
 
+	/*
+	 * Probes must not block in case of lower layer issues.
+	 */
+	if ((flags = fcntl(pii->pii_probe_sock, F_GETFL, 0)) == -1) {
+		logperror_pii(pii, "phyint_inst_v6_sockinit: fcntl"
+		    " F_GETFL");
+		return (_B_FALSE);
+	}
+	if (fcntl(pii->pii_probe_sock, F_SETFL,
+	    flags | O_NONBLOCK) == -1) {
+		logperror_pii(pii, "phyint_inst_v6_sockinit: fcntl"
+		    " F_SETFL O_NONBLOCK");
+		return (_B_FALSE);
+	}
+
 	bzero(&testaddr, sizeof (testaddr));
 	testaddr.sin6_family = AF_INET6;
 	testaddr.sin6_port = 0;
@@ -971,6 +987,7 @@
 	int	ttl = 1;
 	char	char_ttl = 1;
 	int	on = 1;
+	int	flags;
 
 	/*
 	 * Open a raw socket with ICMPv4 protocol.
@@ -988,6 +1005,21 @@
 		return (_B_FALSE);
 	}
 
+	/*
+	 * Probes must not block in case of lower layer issues.
+	 */
+	if ((flags = fcntl(pii->pii_probe_sock, F_GETFL, 0)) == -1) {
+		logperror_pii(pii, "phyint_inst_v4_sockinit: fcntl"
+		    " F_GETFL");
+		return (_B_FALSE);
+	}
+	if (fcntl(pii->pii_probe_sock, F_SETFL,
+	    flags | O_NONBLOCK) == -1) {
+		logperror_pii(pii, "phyint_inst_v4_sockinit: fcntl"
+		    " F_SETFL O_NONBLOCK");
+		return (_B_FALSE);
+	}
+
 	bzero(&testaddr, sizeof (testaddr));
 	testaddr.sin_family = AF_INET;
 	testaddr.sin_port = 0;