@@ -1571,102 +1571,128 @@ static int team_nl_send_generic(struct genl_info *info, struct team *team,
1571
1571
return err ;
1572
1572
}
1573
1573
1574
+ typedef int team_nl_send_func_t (struct sk_buff * skb ,
1575
+ struct team * team , u32 pid );
1576
+
1577
+ static int team_nl_send_unicast (struct sk_buff * skb , struct team * team , u32 pid )
1578
+ {
1579
+ return genlmsg_unicast (dev_net (team -> dev ), skb , pid );
1580
+ }
1581
+
1574
1582
static int team_nl_fill_one_option_get (struct sk_buff * skb , struct team * team ,
1575
1583
struct team_option_inst * opt_inst )
1576
1584
{
1577
1585
struct nlattr * option_item ;
1578
1586
struct team_option * option = opt_inst -> option ;
1579
- struct team_option_inst_info * opt_inst_info ;
1587
+ struct team_option_inst_info * opt_inst_info = & opt_inst -> info ;
1580
1588
struct team_gsetter_ctx ctx ;
1581
1589
int err ;
1582
1590
1591
+ ctx .info = opt_inst_info ;
1592
+ err = team_option_get (team , opt_inst , & ctx );
1593
+ if (err )
1594
+ return err ;
1595
+
1583
1596
option_item = nla_nest_start (skb , TEAM_ATTR_ITEM_OPTION );
1584
1597
if (!option_item )
1585
- goto nla_put_failure ;
1586
- if (nla_put_string (skb , TEAM_ATTR_OPTION_NAME , option -> name ))
1587
- goto nla_put_failure ;
1588
- if (opt_inst -> changed ) {
1589
- if (nla_put_flag (skb , TEAM_ATTR_OPTION_CHANGED ))
1590
- goto nla_put_failure ;
1591
- opt_inst -> changed = false;
1592
- }
1593
- if (opt_inst -> removed && nla_put_flag (skb , TEAM_ATTR_OPTION_REMOVED ))
1594
- goto nla_put_failure ;
1598
+ return - EMSGSIZE ;
1595
1599
1596
- opt_inst_info = & opt_inst -> info ;
1600
+ if (nla_put_string (skb , TEAM_ATTR_OPTION_NAME , option -> name ))
1601
+ goto nest_cancel ;
1597
1602
if (opt_inst_info -> port &&
1598
1603
nla_put_u32 (skb , TEAM_ATTR_OPTION_PORT_IFINDEX ,
1599
1604
opt_inst_info -> port -> dev -> ifindex ))
1600
- goto nla_put_failure ;
1605
+ goto nest_cancel ;
1601
1606
if (opt_inst -> option -> array_size &&
1602
1607
nla_put_u32 (skb , TEAM_ATTR_OPTION_ARRAY_INDEX ,
1603
1608
opt_inst_info -> array_index ))
1604
- goto nla_put_failure ;
1605
- ctx .info = opt_inst_info ;
1609
+ goto nest_cancel ;
1606
1610
1607
1611
switch (option -> type ) {
1608
1612
case TEAM_OPTION_TYPE_U32 :
1609
1613
if (nla_put_u8 (skb , TEAM_ATTR_OPTION_TYPE , NLA_U32 ))
1610
- goto nla_put_failure ;
1611
- err = team_option_get (team , opt_inst , & ctx );
1612
- if (err )
1613
- goto errout ;
1614
+ goto nest_cancel ;
1614
1615
if (nla_put_u32 (skb , TEAM_ATTR_OPTION_DATA , ctx .data .u32_val ))
1615
- goto nla_put_failure ;
1616
+ goto nest_cancel ;
1616
1617
break ;
1617
1618
case TEAM_OPTION_TYPE_STRING :
1618
1619
if (nla_put_u8 (skb , TEAM_ATTR_OPTION_TYPE , NLA_STRING ))
1619
- goto nla_put_failure ;
1620
- err = team_option_get (team , opt_inst , & ctx );
1621
- if (err )
1622
- goto errout ;
1620
+ goto nest_cancel ;
1623
1621
if (nla_put_string (skb , TEAM_ATTR_OPTION_DATA ,
1624
1622
ctx .data .str_val ))
1625
- goto nla_put_failure ;
1623
+ goto nest_cancel ;
1626
1624
break ;
1627
1625
case TEAM_OPTION_TYPE_BINARY :
1628
1626
if (nla_put_u8 (skb , TEAM_ATTR_OPTION_TYPE , NLA_BINARY ))
1629
- goto nla_put_failure ;
1630
- err = team_option_get (team , opt_inst , & ctx );
1631
- if (err )
1632
- goto errout ;
1627
+ goto nest_cancel ;
1633
1628
if (nla_put (skb , TEAM_ATTR_OPTION_DATA , ctx .data .bin_val .len ,
1634
1629
ctx .data .bin_val .ptr ))
1635
- goto nla_put_failure ;
1630
+ goto nest_cancel ;
1636
1631
break ;
1637
1632
case TEAM_OPTION_TYPE_BOOL :
1638
1633
if (nla_put_u8 (skb , TEAM_ATTR_OPTION_TYPE , NLA_FLAG ))
1639
- goto nla_put_failure ;
1640
- err = team_option_get (team , opt_inst , & ctx );
1641
- if (err )
1642
- goto errout ;
1634
+ goto nest_cancel ;
1643
1635
if (ctx .data .bool_val &&
1644
1636
nla_put_flag (skb , TEAM_ATTR_OPTION_DATA ))
1645
- goto nla_put_failure ;
1637
+ goto nest_cancel ;
1646
1638
break ;
1647
1639
default :
1648
1640
BUG ();
1649
1641
}
1642
+ if (opt_inst -> removed && nla_put_flag (skb , TEAM_ATTR_OPTION_REMOVED ))
1643
+ goto nest_cancel ;
1644
+ if (opt_inst -> changed ) {
1645
+ if (nla_put_flag (skb , TEAM_ATTR_OPTION_CHANGED ))
1646
+ goto nest_cancel ;
1647
+ opt_inst -> changed = false;
1648
+ }
1650
1649
nla_nest_end (skb , option_item );
1651
1650
return 0 ;
1652
1651
1653
- nla_put_failure :
1654
- err = - EMSGSIZE ;
1655
- errout :
1656
- return err ;
1652
+ nest_cancel :
1653
+ nla_nest_cancel (skb , option_item );
1654
+ return - EMSGSIZE ;
1655
+ }
1656
+
1657
+ static int __send_and_alloc_skb (struct sk_buff * * pskb ,
1658
+ struct team * team , u32 pid ,
1659
+ team_nl_send_func_t * send_func )
1660
+ {
1661
+ int err ;
1662
+
1663
+ if (* pskb ) {
1664
+ err = send_func (* pskb , team , pid );
1665
+ if (err )
1666
+ return err ;
1667
+ }
1668
+ * pskb = genlmsg_new (NLMSG_DEFAULT_SIZE - GENL_HDRLEN , GFP_KERNEL );
1669
+ if (!* pskb )
1670
+ return - ENOMEM ;
1671
+ return 0 ;
1657
1672
}
1658
1673
1659
- static int team_nl_fill_options_get (struct sk_buff * skb ,
1660
- u32 pid , u32 seq , int flags ,
1661
- struct team * team ,
1674
+ static int team_nl_send_options_get (struct team * team , u32 pid , u32 seq ,
1675
+ int flags , team_nl_send_func_t * send_func ,
1662
1676
struct list_head * sel_opt_inst_list )
1663
1677
{
1664
1678
struct nlattr * option_list ;
1679
+ struct nlmsghdr * nlh ;
1665
1680
void * hdr ;
1666
1681
struct team_option_inst * opt_inst ;
1667
1682
int err ;
1683
+ struct sk_buff * skb = NULL ;
1684
+ bool incomplete ;
1685
+ int i ;
1668
1686
1669
- hdr = genlmsg_put (skb , pid , seq , & team_nl_family , flags ,
1687
+ opt_inst = list_first_entry (sel_opt_inst_list ,
1688
+ struct team_option_inst , tmp_list );
1689
+
1690
+ start_again :
1691
+ err = __send_and_alloc_skb (& skb , team , pid , send_func );
1692
+ if (err )
1693
+ return err ;
1694
+
1695
+ hdr = genlmsg_put (skb , pid , seq , & team_nl_family , flags | NLM_F_MULTI ,
1670
1696
TEAM_CMD_OPTIONS_GET );
1671
1697
if (IS_ERR (hdr ))
1672
1698
return PTR_ERR (hdr );
@@ -1677,46 +1703,62 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
1677
1703
if (!option_list )
1678
1704
goto nla_put_failure ;
1679
1705
1680
- list_for_each_entry (opt_inst , sel_opt_inst_list , tmp_list ) {
1706
+ i = 0 ;
1707
+ incomplete = false;
1708
+ list_for_each_entry_from (opt_inst , sel_opt_inst_list , tmp_list ) {
1681
1709
err = team_nl_fill_one_option_get (skb , team , opt_inst );
1682
- if (err )
1710
+ if (err ) {
1711
+ if (err == - EMSGSIZE ) {
1712
+ if (!i )
1713
+ goto errout ;
1714
+ incomplete = true;
1715
+ break ;
1716
+ }
1683
1717
goto errout ;
1718
+ }
1719
+ i ++ ;
1684
1720
}
1685
1721
1686
1722
nla_nest_end (skb , option_list );
1687
- return genlmsg_end (skb , hdr );
1723
+ genlmsg_end (skb , hdr );
1724
+ if (incomplete )
1725
+ goto start_again ;
1726
+
1727
+ send_done :
1728
+ nlh = nlmsg_put (skb , pid , seq , NLMSG_DONE , 0 , flags | NLM_F_MULTI );
1729
+ if (!nlh ) {
1730
+ err = __send_and_alloc_skb (& skb , team , pid , send_func );
1731
+ if (err )
1732
+ goto errout ;
1733
+ goto send_done ;
1734
+ }
1735
+
1736
+ return send_func (skb , team , pid );
1688
1737
1689
1738
nla_put_failure :
1690
1739
err = - EMSGSIZE ;
1691
1740
errout :
1692
1741
genlmsg_cancel (skb , hdr );
1742
+ nlmsg_free (skb );
1693
1743
return err ;
1694
1744
}
1695
1745
1696
- static int team_nl_fill_options_get_all (struct sk_buff * skb ,
1697
- struct genl_info * info , int flags ,
1698
- struct team * team )
1699
- {
1700
- struct team_option_inst * opt_inst ;
1701
- LIST_HEAD (sel_opt_inst_list );
1702
-
1703
- list_for_each_entry (opt_inst , & team -> option_inst_list , list )
1704
- list_add_tail (& opt_inst -> tmp_list , & sel_opt_inst_list );
1705
- return team_nl_fill_options_get (skb , info -> snd_pid ,
1706
- info -> snd_seq , NLM_F_ACK ,
1707
- team , & sel_opt_inst_list );
1708
- }
1709
-
1710
1746
static int team_nl_cmd_options_get (struct sk_buff * skb , struct genl_info * info )
1711
1747
{
1712
1748
struct team * team ;
1749
+ struct team_option_inst * opt_inst ;
1713
1750
int err ;
1751
+ LIST_HEAD (sel_opt_inst_list );
1714
1752
1715
1753
team = team_nl_team_get (info );
1716
1754
if (!team )
1717
1755
return - EINVAL ;
1718
1756
1719
- err = team_nl_send_generic (info , team , team_nl_fill_options_get_all );
1757
+ list_for_each_entry (opt_inst , & team -> option_inst_list , list )
1758
+ list_add_tail (& opt_inst -> tmp_list , & sel_opt_inst_list );
1759
+ err = team_nl_send_options_get (team , info -> snd_pid , info -> snd_seq ,
1760
+ NLM_F_ACK , team_nl_send_unicast ,
1761
+ & sel_opt_inst_list );
1720
1762
1721
1763
team_nl_team_put (team );
1722
1764
@@ -1963,28 +2005,18 @@ static struct genl_multicast_group team_change_event_mcgrp = {
1963
2005
.name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME ,
1964
2006
};
1965
2007
2008
+ static int team_nl_send_multicast (struct sk_buff * skb ,
2009
+ struct team * team , u32 pid )
2010
+ {
2011
+ return genlmsg_multicast_netns (dev_net (team -> dev ), skb , 0 ,
2012
+ team_change_event_mcgrp .id , GFP_KERNEL );
2013
+ }
2014
+
1966
2015
static int team_nl_send_event_options_get (struct team * team ,
1967
2016
struct list_head * sel_opt_inst_list )
1968
2017
{
1969
- struct sk_buff * skb ;
1970
- int err ;
1971
- struct net * net = dev_net (team -> dev );
1972
-
1973
- skb = nlmsg_new (NLMSG_GOODSIZE , GFP_KERNEL );
1974
- if (!skb )
1975
- return - ENOMEM ;
1976
-
1977
- err = team_nl_fill_options_get (skb , 0 , 0 , 0 , team , sel_opt_inst_list );
1978
- if (err < 0 )
1979
- goto err_fill ;
1980
-
1981
- err = genlmsg_multicast_netns (net , skb , 0 , team_change_event_mcgrp .id ,
1982
- GFP_KERNEL );
1983
- return err ;
1984
-
1985
- err_fill :
1986
- nlmsg_free (skb );
1987
- return err ;
2018
+ return team_nl_send_options_get (team , 0 , 0 , 0 , team_nl_send_multicast ,
2019
+ sel_opt_inst_list );
1988
2020
}
1989
2021
1990
2022
static int team_nl_send_event_port_list_get (struct team * team )
@@ -2053,7 +2085,8 @@ static void __team_options_change_check(struct team *team)
2053
2085
}
2054
2086
err = team_nl_send_event_options_get (team , & sel_opt_inst_list );
2055
2087
if (err )
2056
- netdev_warn (team -> dev , "Failed to send options change via netlink\n" );
2088
+ netdev_warn (team -> dev , "Failed to send options change via netlink (err %d)\n" ,
2089
+ err );
2057
2090
}
2058
2091
2059
2092
static void __team_option_inst_change (struct team * team ,
@@ -2066,7 +2099,8 @@ static void __team_option_inst_change(struct team *team,
2066
2099
list_add (& sel_opt_inst -> tmp_list , & sel_opt_inst_list );
2067
2100
err = team_nl_send_event_options_get (team , & sel_opt_inst_list );
2068
2101
if (err )
2069
- netdev_warn (team -> dev , "Failed to send option change via netlink\n" );
2102
+ netdev_warn (team -> dev , "Failed to send option change via netlink (err %d)\n" ,
2103
+ err );
2070
2104
}
2071
2105
2072
2106
/* rtnl lock is held */
0 commit comments