]> err.no Git - linux-2.6/blobdiff - net/netfilter/nfnetlink.c
[NETFILTER]: nfnetlink: use mutex instead of semaphore
[linux-2.6] / net / netfilter / nfnetlink.c
index ec9f0efea6bb58e18bb7bcf9dbab66b333029fac..7865a47c981e8610fedaec1cc174fab36a88dff6 100644 (file)
  * of the GNU General Public License, incorporated herein by reference.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -30,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <net/sock.h>
+#include <net/netlink.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
@@ -53,16 +52,28 @@ static char __initdata nfversion[] = "0.30";
 
 static struct sock *nfnl = NULL;
 static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
-DECLARE_MUTEX(nfnl_sem);
+static DEFINE_MUTEX(nfnl_mutex);
 
-void nfnl_lock(void)
+static void nfnl_lock(void)
 {
-       nfnl_shlock();
+       mutex_lock(&nfnl_mutex);
 }
 
-void nfnl_unlock(void)
+static int nfnl_trylock(void)
 {
-       nfnl_shunlock();
+       return !mutex_trylock(&nfnl_mutex);
+}
+
+static void __nfnl_unlock(void)
+{
+       mutex_unlock(&nfnl_mutex);
+}
+
+static void nfnl_unlock(void)
+{
+       mutex_unlock(&nfnl_mutex);
+       if (nfnl->sk_receive_queue.qlen)
+               nfnl->sk_data_ready(nfnl, 0);
 }
 
 int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
@@ -106,7 +117,7 @@ static inline struct nfnl_callback *
 nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
 {
        u_int8_t cb_id = NFNL_MSG_TYPE(type);
-       
+
        if (cb_id >= ss->cb_count) {
                DEBUGP("msgtype %u >= %u, returning\n", type, ss->cb_count);
                return NULL;
@@ -188,7 +199,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
        /* implicit: if nlmsg_len == min_len, we return 0, and an empty
         * (zeroed) cda[] array. The message is valid, but empty. */
 
-        return 0;
+       return 0;
 }
 
 int nfnetlink_has_listeners(unsigned int group)
@@ -199,13 +210,12 @@ EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
 
 int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
 {
-       gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
        int err = 0;
 
        NETLINK_CB(skb).dst_group = group;
        if (echo)
                atomic_inc(&skb->users);
-       netlink_broadcast(nfnl, skb, pid, group, allocation);
+       netlink_broadcast(nfnl, skb, pid, group, gfp_any());
        if (echo)
                err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
 
@@ -251,11 +261,11 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb,
        ss = nfnetlink_get_subsys(type);
        if (!ss) {
 #ifdef CONFIG_KMOD
-               /* don't call nfnl_shunlock, since it would reenter
+               /* don't call nfnl_unlock, since it would reenter
                 * with further packet processing */
-               up(&nfnl_sem);
+               __nfnl_unlock();
                request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
-               nfnl_shlock();
+               nfnl_lock();
                ss = nfnetlink_get_subsys(type);
                if (!ss)
 #endif
@@ -269,12 +279,12 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb,
        }
 
        {
-               u_int16_t attr_count = 
+               u_int16_t attr_count =
                        ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
                struct nfattr *cda[attr_count];
 
                memset(cda, 0, sizeof(struct nfattr *) * attr_count);
-               
+
                err = nfnetlink_check_attributes(ss, nlh, cda);
                if (err < 0)
                        goto err_inval;
@@ -325,7 +335,7 @@ static void nfnetlink_rcv(struct sock *sk, int len)
        do {
                struct sk_buff *skb;
 
-               if (nfnl_shlock_nowait())
+               if (nfnl_trylock())
                        return;
 
                while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
@@ -340,9 +350,9 @@ static void nfnetlink_rcv(struct sock *sk, int len)
                        kfree_skb(skb);
                }
 
-               /* don't call nfnl_shunlock, since it would reenter
+               /* don't call nfnl_unlock, since it would reenter
                 * with further packet processing */
-               up(&nfnl_sem);
+               __nfnl_unlock();
        } while(nfnl && nfnl->sk_receive_queue.qlen);
 }
 
@@ -358,7 +368,7 @@ static int __init nfnetlink_init(void)
        printk("Netfilter messages via NETLINK v%s.\n", nfversion);
 
        nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
-                                    nfnetlink_rcv, THIS_MODULE);
+                                    nfnetlink_rcv, THIS_MODULE);
        if (!nfnl) {
                printk(KERN_ERR "cannot initialize nfnetlink!\n");
                return -1;