aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-06-14 10:15:23 -0400
committerPatrick McHardy <kaber@trash.net>2010-06-14 10:15:23 -0400
commitf5c5440d40a24c5dc8030cde0a03debe87de4afb (patch)
tree2dacda8f2134860488dad9783dbcc7ef970f2985 /net
parentbed1be20867d17a3eb2fb5e1613ebdc50c83b8aa (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')
-rw-r--r--net/netfilter/nfnetlink_log.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 8ec23ec568e..fb86a51bb65 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
186static void __nfulnl_flush(struct nfulnl_instance *inst); 186static void __nfulnl_flush(struct nfulnl_instance *inst);
187 187
188/* called with BH disabled */
188static void 189static 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 }