diff mbox

iproute2: Fix memory hog of ip batched command.

Message ID 1342142466-28270-1-git-send-email-pshelar@nicira.com
State Changes Requested, archived
Delegated to: stephen hemminger
Headers show

Commit Message

Pravin B Shelar July 13, 2012, 1:21 a.m. UTC
ipaddr_list_or_flush() builds list of all device at start of
every flush or list operation, but does not free memory at end.
This can hog lot of memory for large batched command.
Following patch fixes it.

Reported-by: Justin Pettit <jpettit@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
 ip/ipaddress.c |   26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

Comments

stephen hemminger July 13, 2012, 4:26 p.m. UTC | #1
On Thu, 12 Jul 2012 18:21:06 -0700
Pravin B Shelar <pshelar@nicira.com> wrote:

> ipaddr_list_or_flush() builds list of all device at start of
> every flush or list operation, but does not free memory at end.
> This can hog lot of memory for large batched command.
> Following patch fixes it.
> 
> Reported-by: Justin Pettit <jpettit@nicira.com>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>

The list of addresses (ainfo) also leaks here.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 1db7fd0..3ce3706 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -775,6 +775,8 @@  static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 	struct nlmsg_list *l, *n;
 	char *filter_dev = NULL;
 	int no_link = 0;
+	int rc = 0;
+	int print_info = 0;
 
 	ipaddr_reset_filter(oneline);
 	filter.showqueue = 1;
@@ -877,7 +879,8 @@  static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 		filter.ifindex = ll_name_to_index(filter_dev);
 		if (filter.ifindex <= 0) {
 			fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev);
-			return -1;
+			rc = -1;
+			goto out;
 		}
 	}
 
@@ -922,11 +925,14 @@  flush_done:
 						printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":"");
 				}
 				fflush(stdout);
-				return 0;
+				rc = 0;
+				goto out;
 			}
 			round++;
-			if (flush_update() < 0)
-				return 1;
+			if (flush_update() < 0) {
+				rc = 1;
+				goto out;
+			}
 
 			if (show_stats) {
 				printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed);
@@ -943,7 +949,8 @@  flush_done:
 		}
 		fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", max_flush_loops);
 		fflush(stderr);
-		return 1;
+		rc = 1;
+		goto out;
 	}
 
 	if (filter.family != AF_PACKET) {
@@ -1018,18 +1025,21 @@  flush_done:
 		}
 	}
 
+	print_info = 1;
+out:
 	for (l = linfo.head; l; l = n) {
 		n = l->next;
-		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
+		if (print_info &&
+		    (no_link || print_linkinfo(NULL, &l->h, stdout) == 0)) {
 			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
 			if (filter.family != AF_PACKET)
 				print_selected_addrinfo(ifi->ifi_index, ainfo.head, stdout);
+			fflush(stdout);
 		}
-		fflush(stdout);
 		free(l);
 	}
 
-	return 0;
+	return rc;
 }
 
 int ipaddr_list_link(int argc, char **argv)