Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66944e1c authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

inetpeer: reduce stack usage



On 64bit arches, we use 752 bytes of stack when cleanup_once() is called
from inet_getpeer().

Lets share the avl stack to save ~376 bytes.

Before patch :

# objdump -d net/ipv4/inetpeer.o | scripts/checkstack.pl

0x000006c3 unlink_from_pool [inetpeer.o]:		376
0x00000721 unlink_from_pool [inetpeer.o]:		376
0x00000cb1 inet_getpeer [inetpeer.o]:			376
0x00000e6d inet_getpeer [inetpeer.o]:			376
0x0004 inet_initpeers [inetpeer.o]:			112
# size net/ipv4/inetpeer.o
   text	   data	    bss	    dec	    hex	filename
   5320	    432	     21	   5773	   168d	net/ipv4/inetpeer.o

After patch :

objdump -d net/ipv4/inetpeer.o | scripts/checkstack.pl
0x00000c11 inet_getpeer [inetpeer.o]:			376
0x00000dcd inet_getpeer [inetpeer.o]:			376
0x00000ab9 peer_check_expire [inetpeer.o]:		328
0x00000b7f peer_check_expire [inetpeer.o]:		328
0x0004 inet_initpeers [inetpeer.o]:			112
# size net/ipv4/inetpeer.o
   text	   data	    bss	    dec	    hex	filename
   5163	    432	     21	   5616	   15f0	net/ipv4/inetpeer.o

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Cc: Scot Doyle <lkml@scotdoyle.com>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Reviewed-by: default avatarHiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f8e9881c
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -354,7 +354,8 @@ static void inetpeer_free_rcu(struct rcu_head *head)
}
}


/* May be called with local BH enabled. */
/* May be called with local BH enabled. */
static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
			     struct inet_peer __rcu **stack[PEER_MAXDEPTH])
{
{
	int do_free;
	int do_free;


@@ -368,7 +369,6 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
	 * We use refcnt=-1 to alert lockless readers this entry is deleted.
	 * We use refcnt=-1 to alert lockless readers this entry is deleted.
	 */
	 */
	if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
	if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
		struct inet_peer __rcu **stack[PEER_MAXDEPTH];
		struct inet_peer __rcu ***stackptr, ***delp;
		struct inet_peer __rcu ***stackptr, ***delp;
		if (lookup(&p->daddr, stack, base) != p)
		if (lookup(&p->daddr, stack, base) != p)
			BUG();
			BUG();
@@ -422,7 +422,7 @@ static struct inet_peer_base *peer_to_base(struct inet_peer *p)
}
}


/* May be called with local BH enabled. */
/* May be called with local BH enabled. */
static int cleanup_once(unsigned long ttl)
static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
{
{
	struct inet_peer *p = NULL;
	struct inet_peer *p = NULL;


@@ -454,7 +454,7 @@ static int cleanup_once(unsigned long ttl)
		 * happen because of entry limits in route cache. */
		 * happen because of entry limits in route cache. */
		return -1;
		return -1;


	unlink_from_pool(p, peer_to_base(p));
	unlink_from_pool(p, peer_to_base(p), stack);
	return 0;
	return 0;
}
}


@@ -524,7 +524,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)


	if (base->total >= inet_peer_threshold)
	if (base->total >= inet_peer_threshold)
		/* Remove one less-recently-used entry. */
		/* Remove one less-recently-used entry. */
		cleanup_once(0);
		cleanup_once(0, stack);


	return p;
	return p;
}
}
@@ -540,6 +540,7 @@ static void peer_check_expire(unsigned long dummy)
{
{
	unsigned long now = jiffies;
	unsigned long now = jiffies;
	int ttl, total;
	int ttl, total;
	struct inet_peer __rcu **stack[PEER_MAXDEPTH];


	total = compute_total();
	total = compute_total();
	if (total >= inet_peer_threshold)
	if (total >= inet_peer_threshold)
@@ -548,7 +549,7 @@ static void peer_check_expire(unsigned long dummy)
		ttl = inet_peer_maxttl
		ttl = inet_peer_maxttl
				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
					total / inet_peer_threshold * HZ;
					total / inet_peer_threshold * HZ;
	while (!cleanup_once(ttl)) {
	while (!cleanup_once(ttl, stack)) {
		if (jiffies != now)
		if (jiffies != now)
			break;
			break;
	}
	}