@@ -36,6 +36,7 @@ struct nf_acct {
atomic_t refcnt;
char name[NFACCT_NAME_MAX];
struct rcu_head rcu_head;
+ spinlock_t lock;
};
static int
@@ -66,8 +67,10 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
if (matching) {
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
/* reset counters if you request a replacement. */
+ spin_lock_bh(&matching->lock);
atomic64_set(&matching->pkts, 0);
atomic64_set(&matching->bytes, 0);
+ spin_unlock_bh(&matching->lock);
return 0;
}
return -EBUSY;
@@ -88,6 +91,7 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
}
atomic_set(&nfacct->refcnt, 1);
+ spin_lock_init(&nfacct->lock);
list_add_tail_rcu(&nfacct->head, &nfnl_acct_list);
return 0;
}
@@ -114,6 +118,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
if (nla_put_string(skb, NFACCT_NAME, acct->name))
goto nla_put_failure;
+ spin_lock_bh(&acct->lock);
if (type == NFNL_MSG_ACCT_GET_CTRZERO) {
pkts = atomic64_xchg(&acct->pkts, 0);
bytes = atomic64_xchg(&acct->bytes, 0);
@@ -121,6 +126,8 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
pkts = atomic64_read(&acct->pkts);
bytes = atomic64_read(&acct->bytes);
}
+ spin_unlock_bh(&acct->lock);
+
if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts)) ||
nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes)) ||
nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))))
@@ -331,8 +338,10 @@ EXPORT_SYMBOL_GPL(nfnl_acct_put);
void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct)
{
+ spin_lock_bh(&nfacct->lock);
atomic64_inc(&nfacct->pkts);
atomic64_add(skb->len, &nfacct->bytes);
+ spin_unlock_bh(&nfacct->lock);
}
EXPORT_SYMBOL_GPL(nfnl_acct_update);