* [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion
@ 2010-06-09 15:58 Eric Dumazet
2010-06-09 16:15 ` Patrick McHardy
0 siblings, 1 reply; 4+ messages in thread
From: Eric Dumazet @ 2010-06-09 15:58 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Development Mailinglist
- instances_lock becomes a spinlock
- lockless lookups
While nfnetlink_log probably not performance critical, using less
rwlocks in our code is always welcomed...
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/netfilter/nfnetlink_log.c | 49 +++++++++++++++++---------------
1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index fc9a211..8ec23ec 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -66,9 +66,10 @@ struct nfulnl_instance {
u_int16_t group_num; /* number of this queue */
u_int16_t flags;
u_int8_t copy_mode;
+ struct rcu_head rcu;
};
-static DEFINE_RWLOCK(instances_lock);
+static DEFINE_SPINLOCK(instances_lock);
static atomic_t global_seq;
#define INSTANCE_BUCKETS 16
@@ -88,7 +89,7 @@ __instance_lookup(u_int16_t group_num)
struct nfulnl_instance *inst;
head = &instance_table[instance_hashfn(group_num)];
- hlist_for_each_entry(inst, pos, head, hlist) {
+ hlist_for_each_entry_rcu(inst, pos, head, hlist) {
if (inst->group_num == group_num)
return inst;
}
@@ -106,22 +107,26 @@ instance_lookup_get(u_int16_t group_num)
{
struct nfulnl_instance *inst;
- read_lock_bh(&instances_lock);
+ rcu_read_lock_bh();
inst = __instance_lookup(group_num);
if (inst)
instance_get(inst);
- read_unlock_bh(&instances_lock);
+ rcu_read_unlock_bh();
return inst;
}
+static void nfulnl_instance_free_rcu(struct rcu_head *head)
+{
+ kfree(container_of(head, struct nfulnl_instance, rcu));
+ module_put(THIS_MODULE);
+}
+
static void
instance_put(struct nfulnl_instance *inst)
{
- if (inst && atomic_dec_and_test(&inst->use)) {
- kfree(inst);
- module_put(THIS_MODULE);
- }
+ if (inst && atomic_dec_and_test(&inst->use))
+ call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
}
static void nfulnl_timer(unsigned long data);
@@ -132,7 +137,7 @@ instance_create(u_int16_t group_num, int pid)
struct nfulnl_instance *inst;
int err;
- write_lock_bh(&instances_lock);
+ spin_lock_bh(&instances_lock);
if (__instance_lookup(group_num)) {
err = -EEXIST;
goto out_unlock;
@@ -169,12 +174,12 @@ instance_create(u_int16_t group_num, int pid)
hlist_add_head(&inst->hlist,
&instance_table[instance_hashfn(group_num)]);
- write_unlock_bh(&instances_lock);
+ spin_unlock_bh(&instances_lock);
return inst;
out_unlock:
- write_unlock_bh(&instances_lock);
+ spin_unlock_bh(&instances_lock);
return ERR_PTR(err);
}
@@ -200,9 +205,9 @@ __instance_destroy(struct nfulnl_instance *inst)
static inline void
instance_destroy(struct nfulnl_instance *inst)
{
- write_lock_bh(&instances_lock);
+ spin_lock_bh(&instances_lock);
__instance_destroy(inst);
- write_unlock_bh(&instances_lock);
+ spin_unlock_bh(&instances_lock);
}
static int
@@ -672,7 +677,7 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
int i;
/* destroy all instances for this pid */
- write_lock_bh(&instances_lock);
+ spin_lock_bh(&instances_lock);
for (i = 0; i < INSTANCE_BUCKETS; i++) {
struct hlist_node *tmp, *t2;
struct nfulnl_instance *inst;
@@ -684,7 +689,7 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
__instance_destroy(inst);
}
}
- write_unlock_bh(&instances_lock);
+ spin_unlock_bh(&instances_lock);
}
return NOTIFY_DONE;
}
@@ -861,19 +866,19 @@ static struct hlist_node *get_first(struct iter_state *st)
for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
if (!hlist_empty(&instance_table[st->bucket]))
- return instance_table[st->bucket].first;
+ return rcu_dereference_bh(instance_table[st->bucket].first);
}
return NULL;
}
static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
{
- h = h->next;
+ h = rcu_dereference_bh(h->next);
while (!h) {
if (++st->bucket >= INSTANCE_BUCKETS)
return NULL;
- h = instance_table[st->bucket].first;
+ h = rcu_dereference_bh(instance_table[st->bucket].first);
}
return h;
}
@@ -890,9 +895,9 @@ static struct hlist_node *get_idx(struct iter_state *st, loff_t pos)
}
static void *seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(instances_lock)
+ __acquires(rcu_bh)
{
- read_lock_bh(&instances_lock);
+ rcu_read_lock_bh();
return get_idx(seq->private, *pos);
}
@@ -903,9 +908,9 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
}
static void seq_stop(struct seq_file *s, void *v)
- __releases(instances_lock)
+ __releases(rcu_bh)
{
- read_unlock_bh(&instances_lock);
+ rcu_read_unlock_bh();
}
static int seq_show(struct seq_file *s, void *v)
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion
2010-06-09 15:58 [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion Eric Dumazet
@ 2010-06-09 16:15 ` Patrick McHardy
2010-06-09 18:09 ` Eric Dumazet
0 siblings, 1 reply; 4+ messages in thread
From: Patrick McHardy @ 2010-06-09 16:15 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Netfilter Development Mailinglist
Eric Dumazet wrote:
> - instances_lock becomes a spinlock
> - lockless lookups
>
> While nfnetlink_log probably not performance critical, using less
> rwlocks in our code is always welcomed...
>
Looks good to me. Applied, thanks Eric.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion
2010-06-09 16:15 ` Patrick McHardy
@ 2010-06-09 18:09 ` Eric Dumazet
2010-06-14 14:16 ` Patrick McHardy
0 siblings, 1 reply; 4+ messages in thread
From: Eric Dumazet @ 2010-06-09 18:09 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Development Mailinglist
Le mercredi 09 juin 2010 à 18:15 +0200, Patrick McHardy a écrit :
>
> Looks good to me. Applied, thanks Eric.
Well, I missed some bits ;)
Here are the fixes, sorry for previous crap !
Thanks
[PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion, part 2
- must use atomic_inc_not_zero() in instance_lookup_get()
- must use hlist_add_head_rcu() instead of hlist_add_head()
- must use hlist_del_rcu() instead of hlist_del()
- Introduce NFULNL_COPY_DISABLED to stop lockless reader from using an
instance, before we do final instance_put() on it.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netfilter/nfnetlink_log.h | 1 +
net/netfilter/nfnetlink_log.c | 18 ++++++++++++------
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index d3bab7a..1d0b84a 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -89,6 +89,7 @@ enum nfulnl_attr_config {
#define NFULNL_COPY_NONE 0x00
#define NFULNL_COPY_META 0x01
#define NFULNL_COPY_PACKET 0x02
+#define NFULNL_COPY_DISABLED 0x03
#define NFULNL_CFG_F_SEQ 0x0001
#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 8ec23ec..fb86a51 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -109,8 +109,8 @@ instance_lookup_get(u_int16_t group_num)
rcu_read_lock_bh();
inst = __instance_lookup(group_num);
- if (inst)
- instance_get(inst);
+ if (inst && !atomic_inc_not_zero(&inst->use))
+ inst = NULL;
rcu_read_unlock_bh();
return inst;
@@ -171,7 +171,7 @@ instance_create(u_int16_t group_num, int pid)
inst->copy_mode = NFULNL_COPY_PACKET;
inst->copy_range = NFULNL_COPY_RANGE_MAX;
- hlist_add_head(&inst->hlist,
+ hlist_add_head_rcu(&inst->hlist,
&instance_table[instance_hashfn(group_num)]);
spin_unlock_bh(&instances_lock);
@@ -185,18 +185,23 @@ out_unlock:
static void __nfulnl_flush(struct nfulnl_instance *inst);
+/* called with BH disabled */
static void
__instance_destroy(struct nfulnl_instance *inst)
{
/* first pull it out of the global list */
- hlist_del(&inst->hlist);
+ hlist_del_rcu(&inst->hlist);
/* then flush all pending packets from skb */
- spin_lock_bh(&inst->lock);
+ spin_lock(&inst->lock);
+
+ /* lockless readers wont be able to use us */
+ inst->copy_mode = NFULNL_COPY_DISABLED;
+
if (inst->skb)
__nfulnl_flush(inst);
- spin_unlock_bh(&inst->lock);
+ spin_unlock(&inst->lock);
/* and finally put the refcount */
instance_put(inst);
@@ -624,6 +629,7 @@ nfulnl_log_packet(u_int8_t pf,
size += nla_total_size(data_len);
break;
+ case NFULNL_COPY_DISABLED:
default:
goto unlock_and_release;
}
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion
2010-06-09 18:09 ` Eric Dumazet
@ 2010-06-14 14:16 ` Patrick McHardy
0 siblings, 0 replies; 4+ messages in thread
From: Patrick McHardy @ 2010-06-14 14:16 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Netfilter Development Mailinglist
Eric Dumazet wrote:
> [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion, part 2
>
> - must use atomic_inc_not_zero() in instance_lookup_get()
>
> - must use hlist_add_head_rcu() instead of hlist_add_head()
>
> - must use hlist_del_rcu() instead of hlist_del()
>
> - Introduce NFULNL_COPY_DISABLED to stop lockless reader from using an
> instance, before we do final instance_put() on it.
>
>
Applied, thanks Eric.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-06-14 14:16 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-09 15:58 [PATCH nf-next-2.6] netfilter: nfnetlink_log: RCU conversion Eric Dumazet
2010-06-09 16:15 ` Patrick McHardy
2010-06-09 18:09 ` Eric Dumazet
2010-06-14 14:16 ` Patrick McHardy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).