[Cluster-devel] [PATCH dlm-tool] dlm_controld: improve netlink ENOBUFS error handling

Alexander Aring aahringo at redhat.com
Thu Sep 10 12:22:50 UTC 2020


This patch improves the handling for ENOBUFS for newer kernels by
setting the NETLINK_NO_ENOBUFS netlink socket option which should avoid
ENOBUFS errors regardless of the receive buffer size. If this fails
we switch to increasing the socket buffer size.
---
 dlm_controld/main.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index a82fc9c2..b3c258b5 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -765,8 +765,7 @@ static void process_uevent(int ci)
 static int setup_uevent(void)
 {
 	struct sockaddr_nl snl;
-	int rcvbuf;
-	int s, rv;
+	int s, rv, val;
 
 	s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
 	if (s < 0) {
@@ -783,14 +782,31 @@ static int setup_uevent(void)
 	 * the  application  to  detect  when  this happens (via the ENOBUFS error
 	 * returned by recvmsg(2)) and resynchronize.
 	 *
-	 * To prevent ENOBUFS errors we just set the receive buffer to two
-	 * megabyte as other applications do it. This will not ensure that we never
-	 * receive ENOBUFS but it's more unlikely. May it's worth to handle ENOBUFS
-	 * errors on a different way in future.
+	 * To avoid ENOBUFS errors we set the netlink socket to realiable
+	 * transmission mode which can be turned on by NETLINK_NO_ENOBUFS
+	 * option. This option is available since kernel 2.6.30. If this setting
+	 * fails we fallback to increase the netlink socket receive buffer.
 	 */
-	rcvbuf = DEFAULT_NETLINK_RCVBUF;
-	setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
-	setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf));
+	val = 1;
+	rv = setsockopt(s, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val));
+	if (rv == -1) {
+		/* Fallback handling if NETLINK_NO_ENOBUFS fails to set.
+		 *
+		 * To prevent ENOBUFS errors we just set the receive buffer to
+		 * two megabyte as other applications do it. This will not
+		 * ensure that we never receive ENOBUFS but it's more unlikely.
+		 */
+		val = DEFAULT_NETLINK_RCVBUF;
+		log_error("uevent netlink NETLINK_NO_ENOBUFS errno %d, will set rcvbuf to %d bytes", errno, val);
+
+		rv = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val));
+		if (rv == -1)
+			log_error("uevent netlink SO_RCVBUF errno %d", errno);
+
+		rv = setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &val, sizeof(val));
+		if (rv == -1)
+			log_error("uevent netlink SO_RCVBUFFORCE errno %d", errno);
+	}
 
 	memset(&snl, 0, sizeof(snl));
 	snl.nl_family = AF_NETLINK;
-- 
2.26.2




More information about the Cluster-devel mailing list