/* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ static inline void __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) { if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) && ecache->events) atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, ecache->ct); ecache->events = 0; nf_ct_put(ecache->ct); ecache->ct = NULL; }
/* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ void nf_ct_deliver_cached_events(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); unsigned long events, missed; struct nf_ct_event_notifier *notify; struct nf_conntrack_ecache *e; struct nf_ct_event item; int ret; rcu_read_lock(); notify = rcu_dereference(net->ct.nf_conntrack_event_cb); if (notify == NULL) goto out_unlock; e = nf_ct_ecache_find(ct); if (e == NULL) goto out_unlock; events = xchg(&e->cache, 0); if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events) goto out_unlock; /* We make a copy of the missed event cache without taking * the lock, thus we may send missed events twice. However, * this does not harm and it happens very rarely. */ missed = e->missed; if (!((events | missed) & e->ctmask)) goto out_unlock; item.ct = ct; item.portid = 0; item.report = 0; ret = notify->fcn(events | missed, &item); if (likely(ret >= 0 && !missed)) goto out_unlock; spin_lock_bh(&ct->lock); if (ret < 0) e->missed |= events; else e->missed &= ~missed; spin_unlock_bh(&ct->lock); out_unlock: rcu_read_unlock(); }
void nf_ct_deliver_cached_events(struct nf_conn *ct) { unsigned long events, missed; struct nf_conntrack_ecache *e; struct nf_ct_event item; int ret = 0; e = nf_ct_ecache_find(ct); if (e == NULL) return; events = xchg(&e->cache, 0); if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events) return; /* We make a copy of the missed event cache without taking * the lock, thus we may send missed events twice. However, * this does not harm and it happens very rarely. */ missed = e->missed; if (!((events | missed) & e->ctmask)) return; item.ct = ct; item.pid = 0; item.report = 0; atomic_notifier_call_chain(&nf_conntrack_chain, events | missed, &item); if (likely(ret >= 0 && !missed)) return; spin_lock_bh(&ct->lock); if (ret < 0) e->missed |= events; else e->missed &= ~missed; spin_unlock_bh(&ct->lock); }