Re: Realtime Preemption, 2.6.12, Beginners Guide?

From: Ingo Molnar
Date: Sat Jul 09 2005 - 08:08:26 EST



> (gdb) ####################################
> (gdb) # c02de0f3, stack size: 572 bytes #
> (gdb) ####################################
> (gdb) 0xc02de0f3 is in ip_setsockopt (net/ipv4/ip_sockglue.c:385).

----
this patch reduces ip_setsockopt's stack footprint from 572 bytes to 164
bytes. (Note: needs review and testing as i could not excercise this
multicast codepath.)

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>

Index: linux/net/ipv4/ip_sockglue.c
===================================================================
--- linux.orig/net/ipv4/ip_sockglue.c
+++ linux/net/ipv4/ip_sockglue.c
@@ -691,52 +691,65 @@ int ip_setsockopt(struct sock *sk, int l
case MCAST_JOIN_GROUP:
case MCAST_LEAVE_GROUP:
{
- struct group_req greq;
+ struct group_req *greq;
struct sockaddr_in *psin;
struct ip_mreqn mreq;

+ err = -ENOMEM;
+ greq = kmalloc(sizeof(*greq), GFP_KERNEL);
+ if (!greq)
+ break;
if (optlen < sizeof(struct group_req))
- goto e_inval;
+ goto free_greq_e_inval;
err = -EFAULT;
- if(copy_from_user(&greq, optval, sizeof(greq)))
- break;
- psin = (struct sockaddr_in *)&greq.gr_group;
+ if(copy_from_user(greq, optval, sizeof(*greq)))
+ goto free_greq_break;
+ psin = (struct sockaddr_in *)&greq->gr_group;
if (psin->sin_family != AF_INET)
- goto e_inval;
+ goto free_greq_e_inval;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr = psin->sin_addr;
- mreq.imr_ifindex = greq.gr_interface;
+ mreq.imr_ifindex = greq->gr_interface;

if (optname == MCAST_JOIN_GROUP)
err = ip_mc_join_group(sk, &mreq);
else
err = ip_mc_leave_group(sk, &mreq);
+free_greq_break:
+ kfree(greq);
break;
+free_greq_e_inval:
+ kfree(greq);
+ goto e_inval;
}
case MCAST_JOIN_SOURCE_GROUP:
case MCAST_LEAVE_SOURCE_GROUP:
case MCAST_BLOCK_SOURCE:
case MCAST_UNBLOCK_SOURCE:
{
- struct group_source_req greqs;
+ struct group_source_req *greqs;
struct ip_mreq_source mreqs;
struct sockaddr_in *psin;
int omode, add;

+ err = -ENOMEM;
+ greqs = kmalloc(sizeof(*greqs), GFP_KERNEL);
+ if (!greqs)
+ break;
if (optlen != sizeof(struct group_source_req))
- goto e_inval;
- if (copy_from_user(&greqs, optval, sizeof(greqs))) {
+ goto free_greqs_e_inval;
+ if (copy_from_user(&greqs, optval, sizeof(*greqs))) {
err = -EFAULT;
- break;
+ goto free_greqs_break;
}
- if (greqs.gsr_group.ss_family != AF_INET ||
- greqs.gsr_source.ss_family != AF_INET) {
+ if (greqs->gsr_group.ss_family != AF_INET ||
+ greqs->gsr_source.ss_family != AF_INET) {
err = -EADDRNOTAVAIL;
- break;
+ goto free_greqs_break;
}
- psin = (struct sockaddr_in *)&greqs.gsr_group;
+ psin = (struct sockaddr_in *)&greqs->gsr_group;
mreqs.imr_multiaddr = psin->sin_addr.s_addr;
- psin = (struct sockaddr_in *)&greqs.gsr_source;
+ psin = (struct sockaddr_in *)&greqs->gsr_source;
mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
mreqs.imr_interface = 0; /* use index for mc_source */

@@ -749,14 +762,14 @@ int ip_setsockopt(struct sock *sk, int l
} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
struct ip_mreqn mreq;

- psin = (struct sockaddr_in *)&greqs.gsr_group;
+ psin = (struct sockaddr_in *)&greqs->gsr_group;
mreq.imr_multiaddr = psin->sin_addr;
mreq.imr_address.s_addr = 0;
- mreq.imr_ifindex = greqs.gsr_interface;
+ mreq.imr_ifindex = greqs->gsr_interface;
err = ip_mc_join_group(sk, &mreq);
if (err)
- break;
- greqs.gsr_interface = mreq.imr_ifindex;
+ goto free_greqs_break;
+ greqs->gsr_interface = mreq.imr_ifindex;
omode = MCAST_INCLUDE;
add = 1;
} else /* MCAST_LEAVE_SOURCE_GROUP */ {
@@ -764,8 +777,13 @@ int ip_setsockopt(struct sock *sk, int l
add = 0;
}
err = ip_mc_source(add, omode, sk, &mreqs,
- greqs.gsr_interface);
- break;
+ greqs->gsr_interface);
+free_greqs_break:
+ kfree(greqs);
+ break;
+free_greqs_e_inval:
+ kfree(greqs);
+ goto e_inval;
}
case MCAST_MSFILTER:
{
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/