[git commit] networking/interface.c: get rid of global data

Denys Vlasenko vda.linux at googlemail.com
Mon Mar 5 17:30:33 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=d51ba0b5ab13aa09ab0482bd2dc63f39e8b40fad
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

These were data/bss:

static.proc_read                                       1       -      -1
int_list                                               4       -      -4
int_last                                               4       -      -4

We never call display_interfaces() twice, thus code to not scan /proc twice
never triggers.

function                                             old     new   delta
do_if_print                                            -    1998   +1998
display_interfaces                                   145     249    +104
static.proc_read                                       1       -      -1
add_interface                                        104     103      -1
int_list                                               4       -      -4
int_last                                               4       -      -4
if_readlist_proc                                     560     542     -18
if_readconf                                          141       -    -141
do_if_fetch                                          643       -    -643
ife_print                                           1296       -   -1296
------------------------------------------------------------------------------
(add/remove: 1/6 grow/shrink: 1/2 up/down: 2102/-2108)         Total: -6 bytes
   text	   data	    bss	    dec	    hex	filename
 933084	    473	   6844	 940401	  e5971	busybox_old
 933087	    473	   6836	 940396	  e596c	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/interface.c | 121 +++++++++++++++----------------------------------
 1 file changed, 36 insertions(+), 85 deletions(-)

diff --git a/networking/interface.c b/networking/interface.c
index ff99c2981..e5e55d8d4 100644
--- a/networking/interface.c
+++ b/networking/interface.c
@@ -341,8 +341,9 @@ struct interface {
 #endif
 };
 
-
-static struct interface *int_list, *int_last;
+struct iface_list {
+	struct interface *int_list, *int_last;
+};
 
 
 #if 0
@@ -373,11 +374,11 @@ static int nstrcmp(const char *a, const char *b)
 }
 #endif
 
-static struct interface *add_interface(char *name)
+static struct interface *add_interface(struct iface_list *ilist, char *name)
 {
 	struct interface *ife, **nextp, *new;
 
-	for (ife = int_last; ife; ife = ife->prev) {
+	for (ife = ilist->int_last; ife; ife = ife->prev) {
 		int n = /*n*/strcmp(ife->name, name);
 
 		if (n == 0)
@@ -388,13 +389,14 @@ static struct interface *add_interface(char *name)
 
 	new = xzalloc(sizeof(*new));
 	strncpy_IFNAMSIZ(new->name, name);
-	nextp = ife ? &ife->next : &int_list;
+
+	nextp = ife ? &ife->next : &ilist->int_list;
 	new->prev = ife;
 	new->next = *nextp;
 	if (new->next)
 		new->next->prev = new;
 	else
-		int_last = new;
+		ilist->int_last = new;
 	*nextp = new;
 	return new;
 }
@@ -500,12 +502,12 @@ static int procnetdev_version(char *buf)
 	return 0;
 }
 
-static int if_readconf(void)
+static void if_readconf(struct iface_list *ilist)
 {
 	int numreqs = 30;
 	struct ifconf ifc;
 	struct ifreq *ifr;
-	int n, err;
+	int n;
 	int skfd;
 
 	ifc.ifc_buf = NULL;
@@ -518,10 +520,7 @@ static int if_readconf(void)
 		ifc.ifc_len = sizeof(struct ifreq) * numreqs;
 		ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
 
-		err = ioctl_or_warn(skfd, SIOCGIFCONF, &ifc);
-		if (err < 0) {
-			goto out;
-		}
+		xioctl(skfd, SIOCGIFCONF, &ifc);
 		if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) {
 			/* assume it overflowed and try again */
 			numreqs += 10;
@@ -532,71 +531,54 @@ static int if_readconf(void)
 
 	ifr = ifc.ifc_req;
 	for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
-		add_interface(ifr->ifr_name);
+		add_interface(ilist, ifr->ifr_name);
 		ifr++;
 	}
-	err = 0;
 
- out:
 	close(skfd);
 	free(ifc.ifc_buf);
-	return err;
 }
 
-static int if_readlist_proc(char *target)
+static int if_readlist_proc(struct iface_list *ilist, char *ifname)
 {
-	static smallint proc_read;
-
 	FILE *fh;
 	char buf[512];
 	struct interface *ife;
-	int err, procnetdev_vsn;
-
-	if (proc_read)
-		return 0;
-	if (!target)
-		proc_read = 1;
+	int procnetdev_vsn;
+	int ret;
 
 	fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");
 	if (!fh) {
-		return if_readconf();
+		return 0; /* "not found" */
 	}
 	fgets(buf, sizeof buf, fh);	/* eat line */
 	fgets(buf, sizeof buf, fh);
 
 	procnetdev_vsn = procnetdev_version(buf);
 
-	err = 0;
+	ret = 0;
 	while (fgets(buf, sizeof buf, fh)) {
 		char *s, name[IFNAMSIZ];
 
 		s = get_name(name, buf);
-		ife = add_interface(name);
+		ife = add_interface(ilist, name);
 		get_dev_fields(s, ife, procnetdev_vsn);
 		ife->statistics_valid = 1;
-		if (target && strcmp(target, name) == 0)
+		if (ifname && strcmp(ifname, name) == 0) {
+			ret = 1; /* found */
 			break;
+		}
 	}
-
-#if 0 /* we trust kernel to not be buggy, /proc/net/dev reads never fail */
-	if (ferror(fh)) {
-		bb_perror_msg(_PATH_PROCNET_DEV);
-		err = -1;
-		proc_read = 0;
-	}
-#endif
-
 	fclose(fh);
-	return err;
+	return ret;
 }
 
-static int if_readlist(void)
+static void if_readlist(struct iface_list *ilist, char *ifname)
 {
-	int err = if_readlist_proc(NULL);
+	int found = if_readlist_proc(ilist, ifname);
 	/* Needed in order to get ethN:M aliases */
-	if (!err)
-		err = if_readconf();
-	return err;
+	if (!found)
+		if_readconf(ilist);
 }
 
 /* Fetch the interface configuration from the kernel. */
@@ -1096,50 +1078,21 @@ static int do_if_print(struct interface *ife, int show_downed_too)
 	return res;
 }
 
-static struct interface *lookup_interface(char *name)
-{
-	struct interface *ife = NULL;
-
-	if (if_readlist_proc(name) < 0)
-		return NULL;
-	ife = add_interface(name);
-	return ife;
-}
-
-#ifdef UNUSED
-static int for_all_interfaces(int (*doit) (struct interface *, void *),
-							void *cookie)
-{
-	struct interface *ife;
-
-	if (!int_list) {
-		int err = if_readlist();
-		if (err < 0)
-			return err;
-	}
-	for (ife = int_list; ife; ife = ife->next) {
-		int err = doit(ife, cookie);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-#endif
-
 int FAST_FUNC display_interfaces(char *ifname)
 {
 	struct interface *ife;
 	int res;
+	struct iface_list ilist;
+
+	ilist.int_list = NULL;
+	ilist.int_last = NULL;
+	if_readlist(&ilist, ifname != IFNAME_SHOW_DOWNED_TOO ? ifname : NULL);
 
 	if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) {
-		/*res = for_all_interfaces(do_if_print, &interface_opt_a);*/
-		if (!int_list) {
-			res = if_readlist();
-			if (res < 0)
-				goto ret;
-		}
-		for (ife = int_list; ife; ife = ife->next) {
+		for (ife = ilist.int_list; ife; ife = ife->next) {
+
 			BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1);
+
 			res = do_if_print(ife, (int)(intptr_t)ifname);
 			if (res < 0)
 				goto ret;
@@ -1147,10 +1100,8 @@ int FAST_FUNC display_interfaces(char *ifname)
 		return 0;
 	}
 
-	ife = lookup_interface(ifname);
-	res = do_if_fetch(ife);
-	if (res >= 0)
-		ife_print(ife);
+	ife = add_interface(&ilist, ifname);
+	res = do_if_print(ife, /*show_downed_too:*/ 1);
  ret:
 	return (res < 0); /* status < 0 == 1 -- error */
 }


More information about the busybox-cvs mailing list