summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/datapath.c45
-rw-r--r--net/openvswitch/vport.h2
2 files changed, 45 insertions, 2 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index ae5e77cdc0ca..5bae7243c577 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -2194,14 +2194,55 @@ static int __net_init ovs_init_net(struct net *net)
2194 return 0; 2194 return 0;
2195} 2195}
2196 2196
2197static void __net_exit ovs_exit_net(struct net *net) 2197static void __net_exit list_vports_from_net(struct net *net, struct net *dnet,
2198 struct list_head *head)
2198{ 2199{
2199 struct datapath *dp, *dp_next;
2200 struct ovs_net *ovs_net = net_generic(net, ovs_net_id); 2200 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
2201 struct datapath *dp;
2202
2203 list_for_each_entry(dp, &ovs_net->dps, list_node) {
2204 int i;
2205
2206 for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
2207 struct vport *vport;
2208
2209 hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) {
2210 struct netdev_vport *netdev_vport;
2211
2212 if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL)
2213 continue;
2214
2215 netdev_vport = netdev_vport_priv(vport);
2216 if (dev_net(netdev_vport->dev) == dnet)
2217 list_add(&vport->detach_list, head);
2218 }
2219 }
2220 }
2221}
2222
2223static void __net_exit ovs_exit_net(struct net *dnet)
2224{
2225 struct datapath *dp, *dp_next;
2226 struct ovs_net *ovs_net = net_generic(dnet, ovs_net_id);
2227 struct vport *vport, *vport_next;
2228 struct net *net;
2229 LIST_HEAD(head);
2201 2230
2202 ovs_lock(); 2231 ovs_lock();
2203 list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node) 2232 list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
2204 __dp_destroy(dp); 2233 __dp_destroy(dp);
2234
2235 rtnl_lock();
2236 for_each_net(net)
2237 list_vports_from_net(net, dnet, &head);
2238 rtnl_unlock();
2239
2240 /* Detach all vports from given namespace. */
2241 list_for_each_entry_safe(vport, vport_next, &head, detach_list) {
2242 list_del(&vport->detach_list);
2243 ovs_dp_detach_port(vport);
2244 }
2245
2205 ovs_unlock(); 2246 ovs_unlock();
2206 2247
2207 cancel_work_sync(&ovs_net->dp_notify_work); 2248 cancel_work_sync(&ovs_net->dp_notify_work);
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index f8ae295fb001..bc85331a6c60 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -103,6 +103,7 @@ struct vport_portids {
103 * @ops: Class structure. 103 * @ops: Class structure.
104 * @percpu_stats: Points to per-CPU statistics used and maintained by vport 104 * @percpu_stats: Points to per-CPU statistics used and maintained by vport
105 * @err_stats: Points to error statistics used and maintained by vport 105 * @err_stats: Points to error statistics used and maintained by vport
106 * @detach_list: list used for detaching vport in net-exit call.
106 */ 107 */
107struct vport { 108struct vport {
108 struct rcu_head rcu; 109 struct rcu_head rcu;
@@ -117,6 +118,7 @@ struct vport {
117 struct pcpu_sw_netstats __percpu *percpu_stats; 118 struct pcpu_sw_netstats __percpu *percpu_stats;
118 119
119 struct vport_err_stats err_stats; 120 struct vport_err_stats err_stats;
121 struct list_head detach_list;
120}; 122};
121 123
122/** 124/**