X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=datapath%2Fdatapath.c;h=f9af82998a0d8e49ffc12f69b871344605dd1993;hb=f632c8fc817ff5597007a795b51574bddd32563a;hp=87b2a0588cbaf7c16e7999e0935c75b4f0083c07;hpb=8f843b6f0fc45fdba373024aaa759785938858fc;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 87b2a058..f9af8299 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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,