diff mbox

[v2,9/9] netfilter: Replace smp_read_barrier_depends() with lockless_dereference()

Message ID 1416582363-20661-10-git-send-email-bobby.prani@gmail.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Pranith Kumar Nov. 21, 2014, 3:06 p.m. UTC
Recently lockless_dereference() was added which can be used in place of
hard-coding smp_read_barrier_depends(). The following PATCH makes the change.

Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
---
 net/ipv4/netfilter/arp_tables.c | 3 +--
 net/ipv4/netfilter/ip_tables.c  | 3 +--
 net/ipv6/netfilter/ip6_tables.c | 3 +--
 3 files changed, 3 insertions(+), 6 deletions(-)

Comments

Eric Dumazet Nov. 21, 2014, 4:12 p.m. UTC | #1
On Fri, 2014-11-21 at 10:06 -0500, Pranith Kumar wrote:
> Recently lockless_dereference() was added which can be used in place of
> hard-coding smp_read_barrier_depends(). The following PATCH makes the change.
> 
> Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
> ---
>  net/ipv4/netfilter/arp_tables.c | 3 +--
>  net/ipv4/netfilter/ip_tables.c  | 3 +--
>  net/ipv6/netfilter/ip6_tables.c | 3 +--
>  3 files changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index f95b6f9..fc7533d 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -270,12 +270,11 @@ unsigned int arpt_do_table(struct sk_buff *skb,
>  
>  	local_bh_disable();
>  	addend = xt_write_recseq_begin();
> -	private = table->private;
>  	/*
>  	 * Ensure we load private-> members after we've fetched the base
>  	 * pointer.
>  	 */
> -	smp_read_barrier_depends();
> +	private = lockless_dereference(table->private);
>  	table_base = private->entries[smp_processor_id()];
>  


Please carefully read the code, before and after your change, then
you'll see this change broke the code.

Problem is that a bug like that can be really hard to diagnose and fix
later, so really you have to be very careful doing these mechanical
changes.

IMO, current code+comment is better than with this
lockless_dereference() which in this particular case obfuscates the
code. more than anything.

In this case we do have a lock (sort of), so lockless_dereference() is
quite misleading.


--
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
Pranith Kumar Nov. 21, 2014, 9:57 p.m. UTC | #2
On Fri, Nov 21, 2014 at 11:12 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Fri, 2014-11-21 at 10:06 -0500, Pranith Kumar wrote:
>> Recently lockless_dereference() was added which can be used in place of
>> hard-coding smp_read_barrier_depends(). The following PATCH makes the change.
>>
>> Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
>> ---
>>  net/ipv4/netfilter/arp_tables.c | 3 +--
>>  net/ipv4/netfilter/ip_tables.c  | 3 +--
>>  net/ipv6/netfilter/ip6_tables.c | 3 +--
>>  3 files changed, 3 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
>> index f95b6f9..fc7533d 100644
>> --- a/net/ipv4/netfilter/arp_tables.c
>> +++ b/net/ipv4/netfilter/arp_tables.c
>> @@ -270,12 +270,11 @@ unsigned int arpt_do_table(struct sk_buff *skb,
>>
>>       local_bh_disable();
>>       addend = xt_write_recseq_begin();
>> -     private = table->private;
>>       /*
>>        * Ensure we load private-> members after we've fetched the base
>>        * pointer.
>>        */
>> -     smp_read_barrier_depends();
>> +     private = lockless_dereference(table->private);
>>       table_base = private->entries[smp_processor_id()];
>>
>
>
> Please carefully read the code, before and after your change, then
> you'll see this change broke the code.
>
> Problem is that a bug like that can be really hard to diagnose and fix
> later, so really you have to be very careful doing these mechanical
> changes.
>
> IMO, current code+comment is better than with this
> lockless_dereference() which in this particular case obfuscates the
> code. more than anything.
>
> In this case we do have a lock (sort of), so lockless_dereference() is
> quite misleading.
>

Hi Eric,

Thanks for looking at this patch.

I've been scratching my head since morning trying to find out what was
so obviously wrong with this patch. Alas, I don't see what you do.

Could you point it out and show me how incompetent I am, please?

Thanks!
Eric Dumazet Nov. 22, 2014, 12:05 a.m. UTC | #3
On Fri, 2014-11-21 at 16:57 -0500, Pranith Kumar wrote:

> Hi Eric,
> 
> Thanks for looking at this patch.
> 
> I've been scratching my head since morning trying to find out what was
> so obviously wrong with this patch. Alas, I don't see what you do.
> 
> Could you point it out and show me how incompetent I am, please?
> 
> Thanks!

Well, even it the code is _not_ broken, I don't see any value with this
patch.

If I use git blame on current code, line containing
smp_read_barrier_depends() exactly points to the relevant commit [1]

After your change, it will point to some cleanup, which makes little
sense to me, considering you did not change the smp_wmb() in
xt_replace_table().

I, as a netfilter contributor would like to keep current code as is,
because it is how I feel safe with it.

We have a proliferation of interfaces, but this does not help to
understand the issues and code maintenance.

smp_read_barrier_depends() better documents the read barrier than 
lockless_dereference().

The point of having a lock or not is irrelevant here.

[1]
http://git.kernel.org/cgit/linux/kernel/git/davem/net.git/commit/?id=b416c144f46af1a30ddfa4e4319a8f077381ad63




--
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
Andres Freund Nov. 22, 2014, 12:24 a.m. UTC | #4
Hi,

On 2014-11-21 16:57:00 -0500, Pranith Kumar wrote:
> On Fri, Nov 21, 2014 at 11:12 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > On Fri, 2014-11-21 at 10:06 -0500, Pranith Kumar wrote:
> >> Recently lockless_dereference() was added which can be used in place of
> >> hard-coding smp_read_barrier_depends(). The following PATCH makes the change.
> >>
> >> Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
> >> ---
> >>  net/ipv4/netfilter/arp_tables.c | 3 +--
> >>  net/ipv4/netfilter/ip_tables.c  | 3 +--
> >>  net/ipv6/netfilter/ip6_tables.c | 3 +--
> >>  3 files changed, 3 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> >> index f95b6f9..fc7533d 100644
> >> --- a/net/ipv4/netfilter/arp_tables.c
> >> +++ b/net/ipv4/netfilter/arp_tables.c
> >> @@ -270,12 +270,11 @@ unsigned int arpt_do_table(struct sk_buff *skb,
> >>
> >>       local_bh_disable();
> >>       addend = xt_write_recseq_begin();
> >> -     private = table->private;
> >>       /*
> >>        * Ensure we load private-> members after we've fetched the base
> >>        * pointer.
> >>        */
> >> -     smp_read_barrier_depends();
> >> +     private = lockless_dereference(table->private);
> >>       table_base = private->entries[smp_processor_id()];
> >>
> >
> >
> > Please carefully read the code, before and after your change, then
> > you'll see this change broke the code.
> >
> > Problem is that a bug like that can be really hard to diagnose and fix
> > later, so really you have to be very careful doing these mechanical
> > changes.
> >
> > IMO, current code+comment is better than with this
> > lockless_dereference() which in this particular case obfuscates the
> > code. more than anything.
> >
> > In this case we do have a lock (sort of), so lockless_dereference() is
> > quite misleading.
> >
> 
> Hi Eric,
> 
> Thanks for looking at this patch.
> 
> I've been scratching my head since morning trying to find out what was
> so obviously wrong with this patch. Alas, I don't see what you do.

Afaics the read_barrier_depends protected the load from private->entries[x]
earlier, not the load of table->private itself.

Greetings,

Andres Freund
--
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
Pranith Kumar Nov. 22, 2014, 1:23 a.m. UTC | #5
On Fri, Nov 21, 2014 at 7:05 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> On Fri, 2014-11-21 at 16:57 -0500, Pranith Kumar wrote:
>
>> Hi Eric,
>>
>> Thanks for looking at this patch.
>>
>> I've been scratching my head since morning trying to find out what was
>> so obviously wrong with this patch. Alas, I don't see what you do.
>>
>> Could you point it out and show me how incompetent I am, please?
>>
>> Thanks!
>
> Well, even it the code is _not_ broken, I don't see any value with this
> patch.

Phew. Not being broken itself is a win :)

>
> If I use git blame on current code, line containing
> smp_read_barrier_depends() exactly points to the relevant commit [1]

And that is an opinion I will respect. I don't want to muck the git
history where it is significant.

This effort is to eventually replace the uses of
smp_read_barrier_depends() and to use either rcu or
lockless_dereference() as documented in memory-barriers.txt.

>
> After your change, it will point to some cleanup, which makes little
> sense to me, considering you did not change the smp_wmb() in
> xt_replace_table().

That does not need to change as it is fine as it is. It still pairs
with the smp_read_barrier_depends() in lockless_dereference().

>
> I, as a netfilter contributor would like to keep current code as is,
> because it is how I feel safe with it.
>
> We have a proliferation of interfaces, but this does not help to
> understand the issues and code maintenance.
>
> smp_read_barrier_depends() better documents the read barrier than
> lockless_dereference().

I think this is a matter of opinion. But in the current effort I've
seen cases where it is not clear what the barrier is actually
guaranteeing. I am glad that the current code is not one of those and
it has reasonable comments.

lockless_dereference() on the other hand makes the dependency explicit.

>
> The point of having a lock or not is irrelevant here.
>
> [1]
> http://git.kernel.org/cgit/linux/kernel/git/davem/net.git/commit/?id=b416c144f46af1a30ddfa4e4319a8f077381ad63
>
>
>
>


Thanks!
diff mbox

Patch

diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index f95b6f9..fc7533d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -270,12 +270,11 @@  unsigned int arpt_do_table(struct sk_buff *skb,
 
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
-	private = table->private;
 	/*
 	 * Ensure we load private-> members after we've fetched the base
 	 * pointer.
 	 */
-	smp_read_barrier_depends();
+	private = lockless_dereference(table->private);
 	table_base = private->entries[smp_processor_id()];
 
 	e = get_entry(table_base, private->hook_entry[hook]);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 99e810f..e0fd044 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -325,13 +325,12 @@  ipt_do_table(struct sk_buff *skb,
 	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
-	private = table->private;
 	cpu        = smp_processor_id();
 	/*
 	 * Ensure we load private-> members after we've fetched the base
 	 * pointer.
 	 */
-	smp_read_barrier_depends();
+	private = lockless_dereference(table->private);
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
 	stackptr   = per_cpu_ptr(private->stackptr, cpu);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index e080fbb..0459d6a 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -348,12 +348,11 @@  ip6t_do_table(struct sk_buff *skb,
 
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
-	private = table->private;
 	/*
 	 * Ensure we load private-> members after we've fetched the base
 	 * pointer.
 	 */
-	smp_read_barrier_depends();
+	private = lockless_dereference(table->private);
 	cpu        = smp_processor_id();
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];