tcp_probe: avoid modulus operation and wrap fix
Subsystems (3)
PATCH 1/1 tcp_probe: avoid modulus operation and wrap fix
By rounding up the buffer size to power of 2, several expensive modulus operations can be avoided. This patch also solves a bug where the gap need when ring gets full was not being accounted for.
net/ipv4/tcp_probe.c +10 -9
@@ -39,9 +39,9 @@ static int port __read_mostly = 0;MODULE_PARM_DESC (port,"Port to match (0=all)" );module_param (port, int,0 ); -static int bufsize__read_mostly =4096 ; +static unsigned int bufsize__read_mostly =4096 ;MODULE_PARM_DESC (bufsize,"Log buffer size in packets (4096)" ); -module_param (bufsize, int,0 ); +module_param (bufsize, uint,0 );static int full__read_mostly ;MODULE_PARM_DESC (full,"Full log (1=every ack packet received, 0=only cwnd changes)" );
@@ -75,12 +75,12 @@ static struct {static inline int tcp_probe_used (void ) { -return (tcp_probe.head - tcp_probe.tail) % bufsize; +return (tcp_probe.head - tcp_probe.tail) & (bufsize -1 ); }static inline int tcp_probe_avail (void ) { -return bufsize -tcp_probe_used (); +return bufsize -tcp_probe_used () -1 ; }/*
@@ -116,7 +116,7 @@ static int jtcp_rcv_established(struct s p->ssthresh =tcp_current_ssthresh (sk); p->srtt = tp->srtt >>3 ; - tcp_probe.head = (tcp_probe.head +1 ) % bufsize; + tcp_probe.head = (tcp_probe.head +1 ) & (bufsize -1 ); } tcp_probe.lastcwnd = tp->snd_cwnd;spin_unlock (&tcp_probe.lock);
@@ -149,7 +149,7 @@ static int tcpprobe_open(struct inode *static int tcpprobe_sprint (char *tbuf,int n) {const struct tcp_log *p - = tcp_probe.log + tcp_probe.tail % bufsize; + = tcp_probe.log + tcp_probe.tail;struct timespec tv =ktime_to_timespec (ktime_sub (p->tstamp, tcp_probe.start));
@@ -192,7 +192,7 @@ static ssize_t tcpprobe_read(struct file width =tcpprobe_sprint (tbuf,sizeof (tbuf));if (cnt + width < len) - tcp_probe.tail = (tcp_probe.tail +1 ) % bufsize; + tcp_probe.tail = (tcp_probe.tail +1 ) & (bufsize -1 );spin_unlock_bh (&tcp_probe.lock);
@@ -222,9 +222,10 @@ static __init int tcpprobe_init(void)init_waitqueue_head (&tcp_probe.wait);spin_lock_init (&tcp_probe.lock); -if (bufsize <0 ) +if (bufsize ==0 )return -EINVAL ; + bufsize =roundup_pow_of_two (bufsize); tcp_probe.log =kcalloc (bufsize,sizeof (struct tcp_log ),GFP_KERNEL );if (!tcp_probe.log) goto err0;
@@ -236,7 +237,7 @@ static __init int tcpprobe_init(void)if (ret) goto err1; -pr_info ("TCP probe registered (port=%d)\n" , port); +pr_info ("TCP probe registered (port=%d) bufsize=%u\n" , port, bufsize);return 0 ; err1:proc_net_remove (&init_net, procname);
David Miller
maintainerFrom: Stephen Hemminger <[email protected]>
Date: Sun, 24 Jan 2010 21:50:01 -0800
Quoted 5 lines
net/ipv4/tcp_probe.c +0
-1@@ -75,12 +75,12 @@ static struct {static inline int tcp_probe_used (void ) { -return (tcp_probe.head - tcp_probe.tail) % bufsize;
net/ipv4/tcp_probe.c static struct { · line 86
Quoted 10 lines
net/ipv4/tcp_probe.c +2
-1+return (tcp_probe.head - tcp_probe.tail) & (bufsize -1 ); }static inline int tcp_probe_avail (void ) { -return bufsize -tcp_probe_used (); +return bufsize -tcp_probe_used () -1 ; }/*
Hmmm... When the ring is full head==tail, which means tcp_probe_used() returns 0. Which would now make tcp_probe_avail() return "bufsize - 0 - 1".
Is that right?
Quoted 17 lines · On Sun, 24 Jan 2010 22:41:22 -0800 (PST) David Miller <[email protected]>…
From: Stephen Hemminger <[email protected]>
Date: Sun, 24 Jan 2010 21:50:01 -0800Quoted 14 lines
net/ipv4/tcp_probe.c +2
-2@@ -75,12 +75,12 @@ static struct {static inline int tcp_probe_used (void ) { -return (tcp_probe.head - tcp_probe.tail) % bufsize; +return (tcp_probe.head - tcp_probe.tail) & (bufsize -1 ); }static inline int tcp_probe_avail (void ) { -return bufsize -tcp_probe_used (); +return bufsize -tcp_probe_used () -1 ; }
Quoted 7 lines
Review static struct { · line 86
Quoted 1 line
(quoted diff) +0
-0/*Hmmm... When the ring is full head==tail, which means
tcp_probe_used()returns 0. Which would now maketcp_probe_avail()return "bufsize - 0 - 1".Is that right?
Yes. in this ring; empty is head == tail, and full needs to be tail == head - 1.
From: Stephen Hemminger <[email protected]>
Date: Mon, 25 Jan 2010 08:30:06 -0800
Quoted 26 lines
Quoted 23 lines · On Sun, 24 Jan 2010 22:41:22 -0800 (PST) David Miller <[email protected]>…
From: Stephen Hemminger <[email protected]>
Date: Sun, 24 Jan 2010 21:50:01 -0800Quoted 5 lines
net/ipv4/tcp_probe.c +0
-1@@ -75,12 +75,12 @@ static struct {static inline int tcp_probe_used (void ) { -return (tcp_probe.head - tcp_probe.tail) % bufsize;net/ipv4/tcp_probe.c static struct { · line 86
Quoted 10 lines
net/ipv4/tcp_probe.c +2
-1+return (tcp_probe.head - tcp_probe.tail) & (bufsize -1 ); }static inline int tcp_probe_avail (void ) { -return bufsize -tcp_probe_used (); +return bufsize -tcp_probe_used () -1 ; }/* Hmmm... When the ring is full head==tail, which means
tcp_probe_used()returns 0. Which would now maketcp_probe_avail()return "bufsize - 0 - 1".
Quoted 4 lines
Quoted 1 line
Is that right?
Yes. in this ring; empty is head == tail, and full needs to be tail == head - 1.
Ok, that makes sense, thanks for explaining.
Applied, thanks Stephen.