diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
| -rw-r--r-- | net/openvswitch/datapath.c | 45 |
1 files changed, 43 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 | ||
| 2197 | static void __net_exit ovs_exit_net(struct net *net) | 2197 | static 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 | |||
| 2223 | static 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); |
