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=3d5629d32b8b4b9dd1830d33e5a6cc6420f17098;hpb=7e71ab66e9a164359c0a5f1d6a20bb2efc15500f;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 3d5629d3..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,51 +306,54 @@ err: return err; } -static void do_destroy_dp(struct datapath *dp) +static void destroy_dp_rcu(struct rcu_head *rcu) { - struct vport *p, *n; + struct datapath *dp = container_of(rcu, struct datapath, rcu); int i; - 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]); + + tbl_destroy((struct tbl __force *)dp->table, flow_free_tbl); free_percpu(dp->stats_percpu); kobject_put(&dp->ifobj); - module_put(THIS_MODULE); } static int destroy_dp(int dp_idx) { struct datapath *dp; - int err; + int err = 0; + struct vport *p, *n; rtnl_lock(); mutex_lock(&dp_mutex); dp = get_dp(dp_idx); - err = -ENODEV; - if (!dp) - goto err_unlock; + if (!dp) { + err = -ENODEV; + goto out; + } - do_destroy_dp(dp); - err = 0; + mutex_lock(&dp->mutex); -err_unlock: + 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)); + + mutex_unlock(&dp->mutex); + call_rcu(&dp->rcu, destroy_dp_rcu); + module_put(THIS_MODULE); + +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; @@ -823,6 +826,7 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, struct tbl_node *flow_node; struct sw_flow *flow; struct tbl *table; + struct sw_flow_actions *acts = NULL; int error; u32 hash; @@ -831,8 +835,6 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, flow_node = tbl_lookup(table, &uf->flow.key, hash, flow_cmp); if (!flow_node) { /* No such flow. */ - struct sw_flow_actions *acts; - error = -ENOENT; if (!(uf->flags & ODPPF_CREATE)) goto error; @@ -906,7 +908,7 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, return 0; error_free_flow_acts: - kfree(flow->sf_acts); + kfree(acts); error_free_flow: flow->sf_acts = NULL; flow_put(flow); @@ -1992,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,