The bridge code doesn't need a separate ioctl, mutex it can just
use the existing RTNL mechanism.  This avoids some races and deadlocks
on shutdown.

This is for 2.4; a similar mechanism has been in 2.6 for some time.

diff -Nru a/net/bridge/br.c b/net/bridge/br.c
--- a/net/bridge/br.c   2004-06-21 07:46:49 -07:00
+++ b/net/bridge/br.c   2004-06-21 07:46:49 -07:00
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/if_bridge.h>
 #include <linux/brlock.h>
+#include <linux/rtnetlink.h>
 #include <asm/uaccess.h>
 #include "br_private.h"
 
@@ -54,15 +55,13 @@
        return 0;
 }
 
-static void __br_clear_ioctl_hook(void)
-{
-       br_ioctl_hook = NULL;
-}
-
 static void __exit br_deinit(void)
 {
        unregister_netdevice_notifier(&br_device_notifier);
-       br_call_ioctl_atomic(__br_clear_ioctl_hook);
+
+       rtnl_lock();
+       br_ioctl_hook = NULL;
+       rtnl_unlock();
 
        br_write_lock_bh(BR_NETPROTO_LOCK);
        br_handle_frame_hook = NULL;
diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
--- a/net/bridge/br_ioctl.c     2004-06-21 07:46:49 -07:00
+++ b/net/bridge/br_ioctl.c     2004-06-21 07:46:49 -07:00
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/if_bridge.h>
 #include <linux/inetdevice.h>
+#include <linux/rtnetlink.h>
 #include <asm/uaccess.h>
 #include "br_private.h"
 
@@ -230,11 +231,8 @@
        return -EOPNOTSUPP;
 }
 
-static DECLARE_MUTEX(ioctl_mutex);
-
 int br_ioctl_deviceless_stub(unsigned long arg)
 {
-       int err;
        unsigned long i[3];
 
        if (!capable(CAP_NET_ADMIN))
@@ -243,11 +241,8 @@
        if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
                return -EFAULT;
 
-       down(&ioctl_mutex);
-       err = br_ioctl_deviceless(i[0], i[1], i[2]);
-       up(&ioctl_mutex);
-
-       return err;
+       ASSERT_RTNL();
+       return  br_ioctl_deviceless(i[0], i[1], i[2]);
 }
 
 int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned 
long arg1, unsigned long arg2)
@@ -257,18 +252,9 @@
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
-       down(&ioctl_mutex);
+       ASSERT_RTNL();
        err = br_ioctl_deviceless(cmd, arg0, arg1);
        if (err == -EOPNOTSUPP)
                err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
-       up(&ioctl_mutex);
-
        return err;
-}
-
-void br_call_ioctl_atomic(void (*fn)(void))
-{
-       down(&ioctl_mutex);
-       fn();
-       up(&ioctl_mutex);
 }
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h   2004-06-21 07:46:49 -07:00
+++ b/net/bridge/br_private.h   2004-06-21 07:46:49 -07:00
@@ -169,7 +169,6 @@
 extern void br_handle_frame(struct sk_buff *skb);
 
 /* br_ioctl.c */
-extern void br_call_ioctl_atomic(void (*fn)(void));
 extern int br_ioctl(struct net_bridge *br,
             unsigned int cmd,
             unsigned long arg0,
_______________________________________________
Bridge mailing list
[EMAIL PROTECTED]
http://lists.osdl.org/mailman/listinfo/bridge

Reply via email to