Re: [patch] Real-Time Preemption, -VP-2.6.9-rc4-mm1-U1

From: Ingo Molnar
Date: Thu Oct 14 2004 - 15:16:05 EST



* Daniel Walker <dwalker@xxxxxxxxxx> wrote:

> This was during NFS startup in init.
>
> using smp_processor_id() in preemptible [00000001] code:
> rpc.rquotad/2158
> caller is ipt_do_table+0x7b/0x3a0
> [<c011aa15>] smp_processor_id+0x95/0xa0
> [<c038cbfb>] ipt_do_table+0x7b/0x3a0

ugh, this is a nasty one - if you look at the TABLE_OFFSET trickery in
ipt_do_table it's basically an open-coded per-CPU variable in essence.
(probably predating percpu.h so it's fair.) Could you try the quick hack
below? (it compiles but is otherwise untested)

The proper solution would be to change the code to use per-cpu variables
(and get that patch accepted upstream) and then trivially convert it to
get_cpu_var_locked().

Ingo

--- linux/net/ipv4/netfilter/ip_tables.c.orig
+++ linux/net/ipv4/netfilter/ip_tables.c
@@ -287,10 +287,14 @@ ipt_do_table(struct sk_buff **pskb,
* match it. */
offset = ntohs(ip->frag_off) & IP_OFFSET;

+#ifdef CONFIG_PREEMPT_REALTIME
+ write_lock_bh(&table->lock);
+#else
read_lock_bh(&table->lock);
+#endif
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
table_base = (void *)table->private->entries
- + TABLE_OFFSET(table->private, smp_processor_id());
+ + TABLE_OFFSET(table->private, _smp_processor_id());
e = get_entry(table_base, table->private->hook_entry[hook]);

#ifdef CONFIG_NETFILTER_DEBUG
@@ -397,7 +401,11 @@ ipt_do_table(struct sk_buff **pskb,
#ifdef CONFIG_NETFILTER_DEBUG
((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
#endif
+#ifdef CONFIG_PREEMPT_REALTIME
+ write_unlock_bh(&table->lock);
+#else
read_unlock_bh(&table->lock);
+#endif

#ifdef DEBUG_ALLOW_ALL
return NF_ACCEPT;
-
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/