diff --git a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c index c7d7fa4fc369bb0b22a7f904d8aabc942d0fbc7f..41327bb990932bd8f95fe5b357fac4c0134866e9 100644 --- a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c @@ -147,15 +147,17 @@ static struct notifier_block masq_inet_notifier = { .notifier_call = masq_inet_event, }; -static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0); +static int masq_refcnt; +static DEFINE_MUTEX(masq_mutex); int nf_nat_masquerade_ipv4_register_notifier(void) { - int ret; + int ret = 0; + mutex_lock(&masq_mutex); /* check if the notifier was already set */ - if (atomic_inc_return(&masquerade_notifier_refcount) > 1) - return 0; + if (++masq_refcnt > 1) + goto out_unlock; /* Register for device down reports */ ret = register_netdevice_notifier(&masq_dev_notifier); @@ -166,22 +168,29 @@ int nf_nat_masquerade_ipv4_register_notifier(void) if (ret) goto err_unregister; + mutex_unlock(&masq_mutex); return ret; + err_unregister: unregister_netdevice_notifier(&masq_dev_notifier); err_dec: - atomic_dec(&masquerade_notifier_refcount); + masq_refcnt--; +out_unlock: + mutex_unlock(&masq_mutex); return ret; } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_register_notifier); void nf_nat_masquerade_ipv4_unregister_notifier(void) { + mutex_lock(&masq_mutex); /* check if the notifier still has clients */ - if (atomic_dec_return(&masquerade_notifier_refcount) > 0) - return; + if (--masq_refcnt > 0) + goto out_unlock; unregister_netdevice_notifier(&masq_dev_notifier); unregister_inetaddr_notifier(&masq_inet_notifier); +out_unlock: + mutex_unlock(&masq_mutex); } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_unregister_notifier); diff --git a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c index 7afd1e63d2dbaef4c1068f78b783dd2177c96c35..0ad0da5a260026ccddd96a4becbec9fa3a975e67 100644 --- a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c @@ -175,15 +175,17 @@ static struct notifier_block masq_inet6_notifier = { .notifier_call = masq_inet6_event, }; -static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0); +static int masq_refcnt; +static DEFINE_MUTEX(masq_mutex); int nf_nat_masquerade_ipv6_register_notifier(void) { - int ret; + int ret = 0; + mutex_lock(&masq_mutex); /* check if the notifier is already set */ - if (atomic_inc_return(&masquerade_notifier_refcount) > 1) - return 0; + if (++masq_refcnt > 1) + goto out_unlock; ret = register_netdevice_notifier(&masq_dev_notifier); if (ret) @@ -193,22 +195,29 @@ int nf_nat_masquerade_ipv6_register_notifier(void) if (ret) goto err_unregister; + mutex_unlock(&masq_mutex); return ret; + err_unregister: unregister_netdevice_notifier(&masq_dev_notifier); err_dec: - atomic_dec(&masquerade_notifier_refcount); + masq_refcnt--; +out_unlock: + mutex_unlock(&masq_mutex); return ret; } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier); void nf_nat_masquerade_ipv6_unregister_notifier(void) { + mutex_lock(&masq_mutex); /* check if the notifier still has clients */ - if (atomic_dec_return(&masquerade_notifier_refcount) > 0) - return; + if (--masq_refcnt > 0) + goto out_unlock; unregister_inet6addr_notifier(&masq_inet6_notifier); unregister_netdevice_notifier(&masq_dev_notifier); +out_unlock: + mutex_unlock(&masq_mutex); } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);