X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=4117ba9d8c7d7ea9ad8d3266f7644f034809b915;hb=7867b760c2924c36521cb5a8c287dc5fe725529a;hp=1bf052061367f723db7865e8b01d3da2492fb56d;hpb=b0fb95ac4b36de9b03405dfb0883e69cee8d2fb3;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 1bf05206..4117ba9d 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -94,14 +94,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 +127,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 +247,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 +286,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 +297,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,12 +308,24 @@ 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); @@ -328,18 +342,11 @@ static int destroy_dp(int dp_idx) 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); mutex_unlock(&dp->mutex); - kobject_put(&dp->ifobj); + call_rcu(&dp->rcu, destroy_dp_rcu); module_put(THIS_MODULE); out: @@ -348,7 +355,7 @@ out: 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; @@ -1989,6 +1996,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,