datapath: Get rid of compat.h, compat26.h in favor of modern approach.
[openvswitch] / datapath / datapath.c
index 87b2a0588cbaf7c16e7999e0935c75b4f0083c07..f9af82998a0d8e49ffc12f69b871344605dd1993 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
@@ -53,8 +53,6 @@
 #include "table.h"
 #include "vport-internal_dev.h"
 
-#include "compat.h"
-
 int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
 EXPORT_SYMBOL(dp_ioctl_hook);
 
@@ -94,14 +92,13 @@ static struct datapath *get_dp_locked(int dp_idx)
        return dp;
 }
 
-static struct tbl *get_table_protected(const struct datapath *dp)
+static struct tbl *get_table_protected(struct datapath *dp)
 {
        return rcu_dereference_protected(dp->table,
                                         lockdep_is_held(&dp->mutex));
 }
 
-static struct vport *get_vport_protected(const struct datapath *dp,
-                                        u16 port_no)
+static struct vport *get_vport_protected(struct datapath *dp, u16 port_no)
 {
        return rcu_dereference_protected(dp->ports[port_no],
                                         lockdep_is_held(&dp->mutex));
@@ -128,7 +125,7 @@ static int dp_fill_ifinfo(struct sk_buff *skb,
                          const struct vport *port,
                          int event, unsigned int flags)
 {
-       const struct datapath *dp = port->dp;
+       struct datapath *dp = port->dp;
        int ifindex = vport_get_ifindex(port);
        int iflink = vport_get_iflink(port);
        struct ifinfomsg *hdr;
@@ -248,6 +245,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
                goto err_put_module;
        INIT_LIST_HEAD(&dp->port_list);
        mutex_init(&dp->mutex);
+       mutex_lock(&dp->mutex);
        dp->dp_idx = dp_idx;
        for (i = 0; i < DP_N_QUEUES; i++)
                skb_queue_head_init(&dp->queues[i]);
@@ -286,6 +284,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
        rcu_assign_pointer(dps[dp_idx], dp);
        dp_sysfs_add_dp(dp);
 
+       mutex_unlock(&dp->mutex);
        mutex_unlock(&dp_mutex);
        rtnl_unlock();
 
@@ -296,6 +295,7 @@ err_destroy_local_port:
 err_destroy_table:
        tbl_destroy(get_table_protected(dp), NULL);
 err_free_dp:
+       mutex_unlock(&dp->mutex);
        kfree(dp);
 err_put_module:
        module_put(THIS_MODULE);
@@ -306,46 +306,54 @@ err:
        return err;
 }
 
+static void destroy_dp_rcu(struct rcu_head *rcu)
+{
+       struct datapath *dp = container_of(rcu, struct datapath, rcu);
+       int i;
+
+       for (i = 0; i < DP_N_QUEUES; i++)
+               skb_queue_purge(&dp->queues[i]);
+
+       tbl_destroy((struct tbl __force *)dp->table, flow_free_tbl);
+       free_percpu(dp->stats_percpu);
+       kobject_put(&dp->ifobj);
+}
+
 static int destroy_dp(int dp_idx)
 {
        struct datapath *dp;
        int err = 0;
        struct vport *p, *n;
-       int i;
 
        rtnl_lock();
        mutex_lock(&dp_mutex);
        dp = get_dp(dp_idx);
        if (!dp) {
                err = -ENODEV;
-               goto unlock;
+               goto out;
        }
 
+       mutex_lock(&dp->mutex);
+
        list_for_each_entry_safe (p, n, &dp->port_list, node)
                if (p->port_no != ODPP_LOCAL)
                        dp_detach_port(p);
 
        dp_sysfs_del_dp(dp);
-
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
-
        dp_detach_port(get_vport_protected(dp, ODPP_LOCAL));
-       tbl_destroy(get_table_protected(dp), flow_free_tbl);
-
-       for (i = 0; i < DP_N_QUEUES; i++)
-               skb_queue_purge(&dp->queues[i]);
-       free_percpu(dp->stats_percpu);
 
-       kobject_put(&dp->ifobj);
+       mutex_unlock(&dp->mutex);
+       call_rcu(&dp->rcu, destroy_dp_rcu);
        module_put(THIS_MODULE);
 
-unlock:
+out:
        mutex_unlock(&dp_mutex);
        rtnl_unlock();
        return err;
 }
 
-/* Called with RTNL lock and dp_mutex. */
+/* Called with RTNL lock and dp->mutex. */
 static int new_vport(struct datapath *dp, struct odp_port *odp_port, int port_no)
 {
        struct vport_parms parms;
@@ -1986,6 +1994,7 @@ static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
 }
 
 static struct file_operations openvswitch_fops = {
+       .owner = THIS_MODULE,
        .read  = openvswitch_read,
        .poll  = openvswitch_poll,
        .unlocked_ioctl = openvswitch_ioctl,