diff options
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/datapath.c | 218 |
1 files changed, 110 insertions, 108 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index cb5d64a5c759..f3bcdac80bda 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -1164,23 +1164,9 @@ error: | |||
1164 | return -EMSGSIZE; | 1164 | return -EMSGSIZE; |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | /* Must be called with ovs_mutex. */ | 1167 | static struct sk_buff *ovs_dp_cmd_alloc_info(struct genl_info *info) |
1168 | static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, | ||
1169 | struct genl_info *info, u8 cmd) | ||
1170 | { | 1168 | { |
1171 | struct sk_buff *skb; | 1169 | return genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL); |
1172 | int retval; | ||
1173 | |||
1174 | skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL); | ||
1175 | if (!skb) | ||
1176 | return ERR_PTR(-ENOMEM); | ||
1177 | |||
1178 | retval = ovs_dp_cmd_fill_info(dp, skb, info->snd_portid, info->snd_seq, 0, cmd); | ||
1179 | if (retval < 0) { | ||
1180 | kfree_skb(skb); | ||
1181 | return ERR_PTR(retval); | ||
1182 | } | ||
1183 | return skb; | ||
1184 | } | 1170 | } |
1185 | 1171 | ||
1186 | /* Called with rcu_read_lock or ovs_mutex. */ | 1172 | /* Called with rcu_read_lock or ovs_mutex. */ |
@@ -1233,12 +1219,14 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1233 | if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID]) | 1219 | if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID]) |
1234 | goto err; | 1220 | goto err; |
1235 | 1221 | ||
1236 | ovs_lock(); | 1222 | reply = ovs_dp_cmd_alloc_info(info); |
1223 | if (!reply) | ||
1224 | return -ENOMEM; | ||
1237 | 1225 | ||
1238 | err = -ENOMEM; | 1226 | err = -ENOMEM; |
1239 | dp = kzalloc(sizeof(*dp), GFP_KERNEL); | 1227 | dp = kzalloc(sizeof(*dp), GFP_KERNEL); |
1240 | if (dp == NULL) | 1228 | if (dp == NULL) |
1241 | goto err_unlock_ovs; | 1229 | goto err_free_reply; |
1242 | 1230 | ||
1243 | ovs_dp_set_net(dp, hold_net(sock_net(skb->sk))); | 1231 | ovs_dp_set_net(dp, hold_net(sock_net(skb->sk))); |
1244 | 1232 | ||
@@ -1273,6 +1261,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1273 | 1261 | ||
1274 | ovs_dp_change(dp, a); | 1262 | ovs_dp_change(dp, a); |
1275 | 1263 | ||
1264 | /* So far only local changes have been made, now need the lock. */ | ||
1265 | ovs_lock(); | ||
1266 | |||
1276 | vport = new_vport(&parms); | 1267 | vport = new_vport(&parms); |
1277 | if (IS_ERR(vport)) { | 1268 | if (IS_ERR(vport)) { |
1278 | err = PTR_ERR(vport); | 1269 | err = PTR_ERR(vport); |
@@ -1291,10 +1282,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1291 | goto err_destroy_ports_array; | 1282 | goto err_destroy_ports_array; |
1292 | } | 1283 | } |
1293 | 1284 | ||
1294 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); | 1285 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, |
1295 | err = PTR_ERR(reply); | 1286 | info->snd_seq, 0, OVS_DP_CMD_NEW); |
1296 | if (IS_ERR(reply)) | 1287 | BUG_ON(err < 0); |
1297 | goto err_destroy_local_port; | ||
1298 | 1288 | ||
1299 | ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); | 1289 | ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); |
1300 | list_add_tail_rcu(&dp->list_node, &ovs_net->dps); | 1290 | list_add_tail_rcu(&dp->list_node, &ovs_net->dps); |
@@ -1304,9 +1294,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1304 | ovs_notify(&dp_datapath_genl_family, reply, info); | 1294 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1305 | return 0; | 1295 | return 0; |
1306 | 1296 | ||
1307 | err_destroy_local_port: | ||
1308 | ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); | ||
1309 | err_destroy_ports_array: | 1297 | err_destroy_ports_array: |
1298 | ovs_unlock(); | ||
1310 | kfree(dp->ports); | 1299 | kfree(dp->ports); |
1311 | err_destroy_percpu: | 1300 | err_destroy_percpu: |
1312 | free_percpu(dp->stats_percpu); | 1301 | free_percpu(dp->stats_percpu); |
@@ -1315,8 +1304,8 @@ err_destroy_table: | |||
1315 | err_free_dp: | 1304 | err_free_dp: |
1316 | release_net(ovs_dp_get_net(dp)); | 1305 | release_net(ovs_dp_get_net(dp)); |
1317 | kfree(dp); | 1306 | kfree(dp); |
1318 | err_unlock_ovs: | 1307 | err_free_reply: |
1319 | ovs_unlock(); | 1308 | kfree_skb(reply); |
1320 | err: | 1309 | err: |
1321 | return err; | 1310 | return err; |
1322 | } | 1311 | } |
@@ -1354,16 +1343,19 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1354 | struct datapath *dp; | 1343 | struct datapath *dp; |
1355 | int err; | 1344 | int err; |
1356 | 1345 | ||
1346 | reply = ovs_dp_cmd_alloc_info(info); | ||
1347 | if (!reply) | ||
1348 | return -ENOMEM; | ||
1349 | |||
1357 | ovs_lock(); | 1350 | ovs_lock(); |
1358 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | 1351 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); |
1359 | err = PTR_ERR(dp); | 1352 | err = PTR_ERR(dp); |
1360 | if (IS_ERR(dp)) | 1353 | if (IS_ERR(dp)) |
1361 | goto unlock; | 1354 | goto err_unlock_free; |
1362 | 1355 | ||
1363 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL); | 1356 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, |
1364 | err = PTR_ERR(reply); | 1357 | info->snd_seq, 0, OVS_DP_CMD_DEL); |
1365 | if (IS_ERR(reply)) | 1358 | BUG_ON(err < 0); |
1366 | goto unlock; | ||
1367 | 1359 | ||
1368 | __dp_destroy(dp); | 1360 | __dp_destroy(dp); |
1369 | ovs_unlock(); | 1361 | ovs_unlock(); |
@@ -1371,8 +1363,10 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1371 | ovs_notify(&dp_datapath_genl_family, reply, info); | 1363 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1372 | 1364 | ||
1373 | return 0; | 1365 | return 0; |
1374 | unlock: | 1366 | |
1367 | err_unlock_free: | ||
1375 | ovs_unlock(); | 1368 | ovs_unlock(); |
1369 | kfree_skb(reply); | ||
1376 | return err; | 1370 | return err; |
1377 | } | 1371 | } |
1378 | 1372 | ||
@@ -1382,29 +1376,30 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1382 | struct datapath *dp; | 1376 | struct datapath *dp; |
1383 | int err; | 1377 | int err; |
1384 | 1378 | ||
1379 | reply = ovs_dp_cmd_alloc_info(info); | ||
1380 | if (!reply) | ||
1381 | return -ENOMEM; | ||
1382 | |||
1385 | ovs_lock(); | 1383 | ovs_lock(); |
1386 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | 1384 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); |
1387 | err = PTR_ERR(dp); | 1385 | err = PTR_ERR(dp); |
1388 | if (IS_ERR(dp)) | 1386 | if (IS_ERR(dp)) |
1389 | goto unlock; | 1387 | goto err_unlock_free; |
1390 | 1388 | ||
1391 | ovs_dp_change(dp, info->attrs); | 1389 | ovs_dp_change(dp, info->attrs); |
1392 | 1390 | ||
1393 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); | 1391 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, |
1394 | if (IS_ERR(reply)) { | 1392 | info->snd_seq, 0, OVS_DP_CMD_NEW); |
1395 | err = PTR_ERR(reply); | 1393 | BUG_ON(err < 0); |
1396 | genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0, | ||
1397 | 0, err); | ||
1398 | err = 0; | ||
1399 | goto unlock; | ||
1400 | } | ||
1401 | 1394 | ||
1402 | ovs_unlock(); | 1395 | ovs_unlock(); |
1403 | ovs_notify(&dp_datapath_genl_family, reply, info); | 1396 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1404 | 1397 | ||
1405 | return 0; | 1398 | return 0; |
1406 | unlock: | 1399 | |
1400 | err_unlock_free: | ||
1407 | ovs_unlock(); | 1401 | ovs_unlock(); |
1402 | kfree_skb(reply); | ||
1408 | return err; | 1403 | return err; |
1409 | } | 1404 | } |
1410 | 1405 | ||
@@ -1414,24 +1409,26 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1414 | struct datapath *dp; | 1409 | struct datapath *dp; |
1415 | int err; | 1410 | int err; |
1416 | 1411 | ||
1417 | ovs_lock(); | 1412 | reply = ovs_dp_cmd_alloc_info(info); |
1413 | if (!reply) | ||
1414 | return -ENOMEM; | ||
1415 | |||
1416 | rcu_read_lock(); | ||
1418 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | 1417 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); |
1419 | if (IS_ERR(dp)) { | 1418 | if (IS_ERR(dp)) { |
1420 | err = PTR_ERR(dp); | 1419 | err = PTR_ERR(dp); |
1421 | goto unlock; | 1420 | goto err_unlock_free; |
1422 | } | ||
1423 | |||
1424 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); | ||
1425 | if (IS_ERR(reply)) { | ||
1426 | err = PTR_ERR(reply); | ||
1427 | goto unlock; | ||
1428 | } | 1421 | } |
1422 | err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, | ||
1423 | info->snd_seq, 0, OVS_DP_CMD_NEW); | ||
1424 | BUG_ON(err < 0); | ||
1425 | rcu_read_unlock(); | ||
1429 | 1426 | ||
1430 | ovs_unlock(); | ||
1431 | return genlmsg_reply(reply, info); | 1427 | return genlmsg_reply(reply, info); |
1432 | 1428 | ||
1433 | unlock: | 1429 | err_unlock_free: |
1434 | ovs_unlock(); | 1430 | rcu_read_unlock(); |
1431 | kfree_skb(reply); | ||
1435 | return err; | 1432 | return err; |
1436 | } | 1433 | } |
1437 | 1434 | ||
@@ -1544,7 +1541,12 @@ error: | |||
1544 | return err; | 1541 | return err; |
1545 | } | 1542 | } |
1546 | 1543 | ||
1547 | /* Called with ovs_mutex or RCU read lock. */ | 1544 | static struct sk_buff *ovs_vport_cmd_alloc_info(void) |
1545 | { | ||
1546 | return nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1547 | } | ||
1548 | |||
1549 | /* Called with ovs_mutex, only via ovs_dp_notify_wq(). */ | ||
1548 | struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid, | 1550 | struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid, |
1549 | u32 seq, u8 cmd) | 1551 | u32 seq, u8 cmd) |
1550 | { | 1552 | { |
@@ -1606,33 +1608,35 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1606 | u32 port_no; | 1608 | u32 port_no; |
1607 | int err; | 1609 | int err; |
1608 | 1610 | ||
1609 | err = -EINVAL; | ||
1610 | if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] || | 1611 | if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] || |
1611 | !a[OVS_VPORT_ATTR_UPCALL_PID]) | 1612 | !a[OVS_VPORT_ATTR_UPCALL_PID]) |
1612 | goto exit; | 1613 | return -EINVAL; |
1614 | |||
1615 | port_no = a[OVS_VPORT_ATTR_PORT_NO] | ||
1616 | ? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0; | ||
1617 | if (port_no >= DP_MAX_PORTS) | ||
1618 | return -EFBIG; | ||
1619 | |||
1620 | reply = ovs_vport_cmd_alloc_info(); | ||
1621 | if (!reply) | ||
1622 | return -ENOMEM; | ||
1613 | 1623 | ||
1614 | ovs_lock(); | 1624 | ovs_lock(); |
1615 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); | 1625 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); |
1616 | err = -ENODEV; | 1626 | err = -ENODEV; |
1617 | if (!dp) | 1627 | if (!dp) |
1618 | goto exit_unlock; | 1628 | goto exit_unlock_free; |
1619 | |||
1620 | if (a[OVS_VPORT_ATTR_PORT_NO]) { | ||
1621 | port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]); | ||
1622 | |||
1623 | err = -EFBIG; | ||
1624 | if (port_no >= DP_MAX_PORTS) | ||
1625 | goto exit_unlock; | ||
1626 | 1629 | ||
1630 | if (port_no) { | ||
1627 | vport = ovs_vport_ovsl(dp, port_no); | 1631 | vport = ovs_vport_ovsl(dp, port_no); |
1628 | err = -EBUSY; | 1632 | err = -EBUSY; |
1629 | if (vport) | 1633 | if (vport) |
1630 | goto exit_unlock; | 1634 | goto exit_unlock_free; |
1631 | } else { | 1635 | } else { |
1632 | for (port_no = 1; ; port_no++) { | 1636 | for (port_no = 1; ; port_no++) { |
1633 | if (port_no >= DP_MAX_PORTS) { | 1637 | if (port_no >= DP_MAX_PORTS) { |
1634 | err = -EFBIG; | 1638 | err = -EFBIG; |
1635 | goto exit_unlock; | 1639 | goto exit_unlock_free; |
1636 | } | 1640 | } |
1637 | vport = ovs_vport_ovsl(dp, port_no); | 1641 | vport = ovs_vport_ovsl(dp, port_no); |
1638 | if (!vport) | 1642 | if (!vport) |
@@ -1650,22 +1654,19 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1650 | vport = new_vport(&parms); | 1654 | vport = new_vport(&parms); |
1651 | err = PTR_ERR(vport); | 1655 | err = PTR_ERR(vport); |
1652 | if (IS_ERR(vport)) | 1656 | if (IS_ERR(vport)) |
1653 | goto exit_unlock; | 1657 | goto exit_unlock_free; |
1654 | 1658 | ||
1655 | err = 0; | 1659 | err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, |
1656 | reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq, | 1660 | info->snd_seq, 0, OVS_VPORT_CMD_NEW); |
1657 | OVS_VPORT_CMD_NEW); | 1661 | BUG_ON(err < 0); |
1658 | if (IS_ERR(reply)) { | 1662 | ovs_unlock(); |
1659 | err = PTR_ERR(reply); | ||
1660 | ovs_dp_detach_port(vport); | ||
1661 | goto exit_unlock; | ||
1662 | } | ||
1663 | 1663 | ||
1664 | ovs_notify(&dp_vport_genl_family, reply, info); | 1664 | ovs_notify(&dp_vport_genl_family, reply, info); |
1665 | return 0; | ||
1665 | 1666 | ||
1666 | exit_unlock: | 1667 | exit_unlock_free: |
1667 | ovs_unlock(); | 1668 | ovs_unlock(); |
1668 | exit: | 1669 | kfree_skb(reply); |
1669 | return err; | 1670 | return err; |
1670 | } | 1671 | } |
1671 | 1672 | ||
@@ -1676,28 +1677,26 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1676 | struct vport *vport; | 1677 | struct vport *vport; |
1677 | int err; | 1678 | int err; |
1678 | 1679 | ||
1680 | reply = ovs_vport_cmd_alloc_info(); | ||
1681 | if (!reply) | ||
1682 | return -ENOMEM; | ||
1683 | |||
1679 | ovs_lock(); | 1684 | ovs_lock(); |
1680 | vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); | 1685 | vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); |
1681 | err = PTR_ERR(vport); | 1686 | err = PTR_ERR(vport); |
1682 | if (IS_ERR(vport)) | 1687 | if (IS_ERR(vport)) |
1683 | goto exit_unlock; | 1688 | goto exit_unlock_free; |
1684 | 1689 | ||
1685 | if (a[OVS_VPORT_ATTR_TYPE] && | 1690 | if (a[OVS_VPORT_ATTR_TYPE] && |
1686 | nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) { | 1691 | nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) { |
1687 | err = -EINVAL; | 1692 | err = -EINVAL; |
1688 | goto exit_unlock; | 1693 | goto exit_unlock_free; |
1689 | } | ||
1690 | |||
1691 | reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1692 | if (!reply) { | ||
1693 | err = -ENOMEM; | ||
1694 | goto exit_unlock; | ||
1695 | } | 1694 | } |
1696 | 1695 | ||
1697 | if (a[OVS_VPORT_ATTR_OPTIONS]) { | 1696 | if (a[OVS_VPORT_ATTR_OPTIONS]) { |
1698 | err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); | 1697 | err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); |
1699 | if (err) | 1698 | if (err) |
1700 | goto exit_free; | 1699 | goto exit_unlock_free; |
1701 | } | 1700 | } |
1702 | 1701 | ||
1703 | if (a[OVS_VPORT_ATTR_UPCALL_PID]) | 1702 | if (a[OVS_VPORT_ATTR_UPCALL_PID]) |
@@ -1711,10 +1710,9 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1711 | ovs_notify(&dp_vport_genl_family, reply, info); | 1710 | ovs_notify(&dp_vport_genl_family, reply, info); |
1712 | return 0; | 1711 | return 0; |
1713 | 1712 | ||
1714 | exit_free: | 1713 | exit_unlock_free: |
1715 | kfree_skb(reply); | ||
1716 | exit_unlock: | ||
1717 | ovs_unlock(); | 1714 | ovs_unlock(); |
1715 | kfree_skb(reply); | ||
1718 | return err; | 1716 | return err; |
1719 | } | 1717 | } |
1720 | 1718 | ||
@@ -1725,30 +1723,33 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1725 | struct vport *vport; | 1723 | struct vport *vport; |
1726 | int err; | 1724 | int err; |
1727 | 1725 | ||
1726 | reply = ovs_vport_cmd_alloc_info(); | ||
1727 | if (!reply) | ||
1728 | return -ENOMEM; | ||
1729 | |||
1728 | ovs_lock(); | 1730 | ovs_lock(); |
1729 | vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); | 1731 | vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); |
1730 | err = PTR_ERR(vport); | 1732 | err = PTR_ERR(vport); |
1731 | if (IS_ERR(vport)) | 1733 | if (IS_ERR(vport)) |
1732 | goto exit_unlock; | 1734 | goto exit_unlock_free; |
1733 | 1735 | ||
1734 | if (vport->port_no == OVSP_LOCAL) { | 1736 | if (vport->port_no == OVSP_LOCAL) { |
1735 | err = -EINVAL; | 1737 | err = -EINVAL; |
1736 | goto exit_unlock; | 1738 | goto exit_unlock_free; |
1737 | } | 1739 | } |
1738 | 1740 | ||
1739 | reply = ovs_vport_cmd_build_info(vport, info->snd_portid, | 1741 | err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, |
1740 | info->snd_seq, OVS_VPORT_CMD_DEL); | 1742 | info->snd_seq, 0, OVS_VPORT_CMD_DEL); |
1741 | err = PTR_ERR(reply); | 1743 | BUG_ON(err < 0); |
1742 | if (IS_ERR(reply)) | ||
1743 | goto exit_unlock; | ||
1744 | |||
1745 | err = 0; | ||
1746 | ovs_dp_detach_port(vport); | 1744 | ovs_dp_detach_port(vport); |
1745 | ovs_unlock(); | ||
1747 | 1746 | ||
1748 | ovs_notify(&dp_vport_genl_family, reply, info); | 1747 | ovs_notify(&dp_vport_genl_family, reply, info); |
1748 | return 0; | ||
1749 | 1749 | ||
1750 | exit_unlock: | 1750 | exit_unlock_free: |
1751 | ovs_unlock(); | 1751 | ovs_unlock(); |
1752 | kfree_skb(reply); | ||
1752 | return err; | 1753 | return err; |
1753 | } | 1754 | } |
1754 | 1755 | ||
@@ -1760,24 +1761,25 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1760 | struct vport *vport; | 1761 | struct vport *vport; |
1761 | int err; | 1762 | int err; |
1762 | 1763 | ||
1764 | reply = ovs_vport_cmd_alloc_info(); | ||
1765 | if (!reply) | ||
1766 | return -ENOMEM; | ||
1767 | |||
1763 | rcu_read_lock(); | 1768 | rcu_read_lock(); |
1764 | vport = lookup_vport(sock_net(skb->sk), ovs_header, a); | 1769 | vport = lookup_vport(sock_net(skb->sk), ovs_header, a); |
1765 | err = PTR_ERR(vport); | 1770 | err = PTR_ERR(vport); |
1766 | if (IS_ERR(vport)) | 1771 | if (IS_ERR(vport)) |
1767 | goto exit_unlock; | 1772 | goto exit_unlock_free; |
1768 | 1773 | err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, | |
1769 | reply = ovs_vport_cmd_build_info(vport, info->snd_portid, | 1774 | info->snd_seq, 0, OVS_VPORT_CMD_NEW); |
1770 | info->snd_seq, OVS_VPORT_CMD_NEW); | 1775 | BUG_ON(err < 0); |
1771 | err = PTR_ERR(reply); | ||
1772 | if (IS_ERR(reply)) | ||
1773 | goto exit_unlock; | ||
1774 | |||
1775 | rcu_read_unlock(); | 1776 | rcu_read_unlock(); |
1776 | 1777 | ||
1777 | return genlmsg_reply(reply, info); | 1778 | return genlmsg_reply(reply, info); |
1778 | 1779 | ||
1779 | exit_unlock: | 1780 | exit_unlock_free: |
1780 | rcu_read_unlock(); | 1781 | rcu_read_unlock(); |
1782 | kfree_skb(reply); | ||
1781 | return err; | 1783 | return err; |
1782 | } | 1784 | } |
1783 | 1785 | ||