Blame SOURCES/0001-fcoemon-netlink-buffer-resize-fix.patch

b7e464
From 3b4ca6b87dae6b11da137b6afb4cf8275687d281 Mon Sep 17 00:00:00 2001
b7e464
From: Chris Leech <cleech@redhat.com>
b7e464
Date: Thu, 24 Jan 2019 18:16:47 -0800
b7e464
Subject: [PATCH] fcoemon: netlink buffer resize fix
b7e464
b7e464
The recv buffer resizing for netlink messages looks to have always been
b7e464
busted, it discards some of the data in the process of increasing the
b7e464
buffer size.
b7e464
b7e464
I've recently seen issues where the size of the netlink attributes in a
b7e464
GETLINK request hit the fcm_link_buf_size window and some of the network
b7e464
interfaces were ignored by fcoemon (happened mostly with recent kernels,
b7e464
2 dual-port bnx2 NICs, bonding for LAN traffic on 2 ports and FCoE on
b7e464
the other 2).  When the ignored interface happens to be the one you want
b7e464
to use for FCoE, it never gets fixed.
b7e464
b7e464
This fixes the buffer resize code to use MSG_PEEK|MSG_TRUNC to check for
b7e464
the needed buffer size first, and then resize with realloc when needed.
b7e464
This might not actually be needed, with an 8k buffer I don't think the
b7e464
kernel side will send more at once until after it sees the application
b7e464
post a larger buffer, but I did force a resize and see that it worked.
b7e464
b7e464
Signed-off-by: Chris Leech <cleech@redhat.com>
b7e464
---
b7e464
 fcoemon.c | 54 ++++++++++++++++++------------------------------------
b7e464
 1 file changed, 18 insertions(+), 36 deletions(-)
b7e464
b7e464
diff --git a/fcoemon.c b/fcoemon.c
b7e464
index 9a400c56b72..9af0f1284af 100644
b7e464
--- a/fcoemon.c
b7e464
+++ b/fcoemon.c
b7e464
@@ -328,7 +328,6 @@ static int fcm_link_socket;
b7e464
 static int fcm_link_seq;
b7e464
 static void fcm_link_recv(void *);
b7e464
 static void fcm_link_getlink(void);
b7e464
-static int fcm_link_buf_check(size_t);
b7e464
 static void clear_dcbd_info(struct fcm_netif *ff);
b7e464
 static int fcoe_vid_from_ifname(const char *ifname);
b7e464
 
b7e464
@@ -354,8 +353,7 @@ char progname[20];
b7e464
  * large enough to fit and expand it if we ever do a read that almost fills it.
b7e464
  */
b7e464
 static char *fcm_link_buf;
b7e464
-static size_t fcm_link_buf_size = 4096;	/* initial size */
b7e464
-static const size_t fcm_link_buf_fuzz = 300;	/* "almost full" remainder */
b7e464
+static size_t fcm_link_buf_size = 8192;	/* initial size */
b7e464
 
b7e464
 /*
b7e464
  * A value must be surrounded by quates, e.g. "x".
b7e464
@@ -1848,8 +1846,22 @@ static void fcm_link_recv(UNUSED void *arg)
b7e464
 	size_t plen;
b7e464
 	size_t rlen;
b7e464
 
b7e464
+	/* check to make sure our receive buffer is large enough,
b7e464
+	 * or scale it up as needed */
b7e464
+	rc = recv(fcm_link_socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
b7e464
+	if (rc > fcm_link_buf_size) {
b7e464
+		FCM_LOG_DBG("resizing link buf to %d bytes\n", rc);
b7e464
+		void *resize = realloc(fcm_link_buf, rc);
b7e464
+		if (resize) {
b7e464
+			fcm_link_buf = resize;
b7e464
+			fcm_link_buf_size = rc;
b7e464
+		} else {
b7e464
+			FCM_LOG_ERR(errno, "Failed to allocate link buffer");
b7e464
+		}
b7e464
+	}
b7e464
+
b7e464
 	buf = fcm_link_buf;
b7e464
-	rc = read(fcm_link_socket, buf, fcm_link_buf_size);
b7e464
+	rc = recv(fcm_link_socket, buf, fcm_link_buf_size, 0);
b7e464
 	if (rc <= 0) {
b7e464
 		if (rc < 0)
b7e464
 			FCM_LOG_ERR(errno, "Error reading from "
b7e464
@@ -1858,11 +1870,6 @@ static void fcm_link_recv(UNUSED void *arg)
b7e464
 		return;
b7e464
 	}
b7e464
 
b7e464
-	if (fcm_link_buf_check(rc)) {
b7e464
-		fcm_link_getlink();
b7e464
-		return;
b7e464
-	}
b7e464
-
b7e464
 	hp = (struct nlmsghdr *)buf;
b7e464
 	rlen = rc;
b7e464
 	for (hp = (struct nlmsghdr *)buf; NLMSG_OK(hp, rlen);
b7e464
@@ -1927,34 +1934,9 @@ static void fcm_link_getlink(void)
b7e464
 	msg.nl.nlmsg_pid = getpid();
b7e464
 	msg.ifi.ifi_family = AF_UNSPEC;
b7e464
 	msg.ifi.ifi_type = ARPHRD_ETHER;
b7e464
-	rc = write(fcm_link_socket, &msg, sizeof(msg));
b7e464
+	rc = send(fcm_link_socket, &msg, sizeof(msg), 0);
b7e464
 	if (rc < 0)
b7e464
-		FCM_LOG_ERR(errno, "write error");
b7e464
-}
b7e464
-
b7e464
-/*
b7e464
- * Check for whether buffer needs to grow based on amount read.
b7e464
- * Free's the old buffer so don't use that after this returns non-zero.
b7e464
- */
b7e464
-static int fcm_link_buf_check(size_t read_len)
b7e464
-{
b7e464
-	char *buf;
b7e464
-	size_t len = read_len;
b7e464
-
b7e464
-	if (len > fcm_link_buf_size - fcm_link_buf_fuzz) {
b7e464
-		len = fcm_link_buf_size;
b7e464
-		len = len + len / 2;	/* grow by 50% */
b7e464
-		buf = malloc(len);
b7e464
-		if (buf != NULL) {
b7e464
-			free(fcm_link_buf);
b7e464
-			fcm_link_buf = buf;
b7e464
-			fcm_link_buf_size = len;
b7e464
-			return 1;
b7e464
-		} else {
b7e464
-			FCM_LOG_ERR(errno, "failed to allocate link buffer");
b7e464
-		}
b7e464
-	}
b7e464
-	return 0;
b7e464
+		FCM_LOG_ERR(errno, "send error");
b7e464
 }
b7e464
 
b7e464
 static void fcm_fcoe_init(void)
b7e464
-- 
b7e464
2.21.0
b7e464