diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-14 10:15:23 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-06-14 10:15:23 -0400 |
commit | f5c5440d40a24c5dc8030cde0a03debe87de4afb (patch) | |
tree | 2dacda8f2134860488dad9783dbcc7ef970f2985 /net/netfilter | |
parent | bed1be20867d17a3eb2fb5e1613ebdc50c83b8aa (diff) |
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>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 8ec23ec568e7..fb86a51bb65a 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) | |||
109 | 109 | ||
110 | rcu_read_lock_bh(); | 110 | rcu_read_lock_bh(); |
111 | inst = __instance_lookup(group_num); | 111 | inst = __instance_lookup(group_num); |
112 | if (inst) | 112 | if (inst && !atomic_inc_not_zero(&inst->use)) |
113 | instance_get(inst); | 113 | inst = NULL; |
114 | rcu_read_unlock_bh(); | 114 | rcu_read_unlock_bh(); |
115 | 115 | ||
116 | return inst; | 116 | return inst; |
@@ -171,7 +171,7 @@ instance_create(u_int16_t group_num, int pid) | |||
171 | inst->copy_mode = NFULNL_COPY_PACKET; | 171 | inst->copy_mode = NFULNL_COPY_PACKET; |
172 | inst->copy_range = NFULNL_COPY_RANGE_MAX; | 172 | inst->copy_range = NFULNL_COPY_RANGE_MAX; |
173 | 173 | ||
174 | hlist_add_head(&inst->hlist, | 174 | hlist_add_head_rcu(&inst->hlist, |
175 | &instance_table[instance_hashfn(group_num)]); | 175 | &instance_table[instance_hashfn(group_num)]); |
176 | 176 | ||
177 | spin_unlock_bh(&instances_lock); | 177 | spin_unlock_bh(&instances_lock); |
@@ -185,18 +185,23 @@ out_unlock: | |||
185 | 185 | ||
186 | static void __nfulnl_flush(struct nfulnl_instance *inst); | 186 | static void __nfulnl_flush(struct nfulnl_instance *inst); |
187 | 187 | ||
188 | /* called with BH disabled */ | ||
188 | static void | 189 | static void |
189 | __instance_destroy(struct nfulnl_instance *inst) | 190 | __instance_destroy(struct nfulnl_instance *inst) |
190 | { | 191 | { |
191 | /* first pull it out of the global list */ | 192 | /* first pull it out of the global list */ |
192 | hlist_del(&inst->hlist); | 193 | hlist_del_rcu(&inst->hlist); |
193 | 194 | ||
194 | /* then flush all pending packets from skb */ | 195 | /* then flush all pending packets from skb */ |
195 | 196 | ||
196 | spin_lock_bh(&inst->lock); | 197 | spin_lock(&inst->lock); |
198 | |||
199 | /* lockless readers wont be able to use us */ | ||
200 | inst->copy_mode = NFULNL_COPY_DISABLED; | ||
201 | |||
197 | if (inst->skb) | 202 | if (inst->skb) |
198 | __nfulnl_flush(inst); | 203 | __nfulnl_flush(inst); |
199 | spin_unlock_bh(&inst->lock); | 204 | spin_unlock(&inst->lock); |
200 | 205 | ||
201 | /* and finally put the refcount */ | 206 | /* and finally put the refcount */ |
202 | instance_put(inst); | 207 | instance_put(inst); |
@@ -624,6 +629,7 @@ nfulnl_log_packet(u_int8_t pf, | |||
624 | size += nla_total_size(data_len); | 629 | size += nla_total_size(data_len); |
625 | break; | 630 | break; |
626 | 631 | ||
632 | case NFULNL_COPY_DISABLED: | ||
627 | default: | 633 | default: |
628 | goto unlock_and_release; | 634 | goto unlock_and_release; |
629 | } | 635 | } |