@@ -1571,102 +1571,128 @@ static int team_nl_send_generic(struct genl_info *info, struct team *team,
15711571 return err ;
15721572}
15731573
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+
15741582static int team_nl_fill_one_option_get (struct sk_buff * skb , struct team * team ,
15751583 struct team_option_inst * opt_inst )
15761584{
15771585 struct nlattr * option_item ;
15781586 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 ;
15801588 struct team_gsetter_ctx ctx ;
15811589 int err ;
15821590
1591+ ctx .info = opt_inst_info ;
1592+ err = team_option_get (team , opt_inst , & ctx );
1593+ if (err )
1594+ return err ;
1595+
15831596 option_item = nla_nest_start (skb , TEAM_ATTR_ITEM_OPTION );
15841597 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 ;
15951599
1596- opt_inst_info = & opt_inst -> info ;
1600+ if (nla_put_string (skb , TEAM_ATTR_OPTION_NAME , option -> name ))
1601+ goto nest_cancel ;
15971602 if (opt_inst_info -> port &&
15981603 nla_put_u32 (skb , TEAM_ATTR_OPTION_PORT_IFINDEX ,
15991604 opt_inst_info -> port -> dev -> ifindex ))
1600- goto nla_put_failure ;
1605+ goto nest_cancel ;
16011606 if (opt_inst -> option -> array_size &&
16021607 nla_put_u32 (skb , TEAM_ATTR_OPTION_ARRAY_INDEX ,
16031608 opt_inst_info -> array_index ))
1604- goto nla_put_failure ;
1605- ctx .info = opt_inst_info ;
1609+ goto nest_cancel ;
16061610
16071611 switch (option -> type ) {
16081612 case TEAM_OPTION_TYPE_U32 :
16091613 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 ;
16141615 if (nla_put_u32 (skb , TEAM_ATTR_OPTION_DATA , ctx .data .u32_val ))
1615- goto nla_put_failure ;
1616+ goto nest_cancel ;
16161617 break ;
16171618 case TEAM_OPTION_TYPE_STRING :
16181619 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 ;
16231621 if (nla_put_string (skb , TEAM_ATTR_OPTION_DATA ,
16241622 ctx .data .str_val ))
1625- goto nla_put_failure ;
1623+ goto nest_cancel ;
16261624 break ;
16271625 case TEAM_OPTION_TYPE_BINARY :
16281626 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 ;
16331628 if (nla_put (skb , TEAM_ATTR_OPTION_DATA , ctx .data .bin_val .len ,
16341629 ctx .data .bin_val .ptr ))
1635- goto nla_put_failure ;
1630+ goto nest_cancel ;
16361631 break ;
16371632 case TEAM_OPTION_TYPE_BOOL :
16381633 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 ;
16431635 if (ctx .data .bool_val &&
16441636 nla_put_flag (skb , TEAM_ATTR_OPTION_DATA ))
1645- goto nla_put_failure ;
1637+ goto nest_cancel ;
16461638 break ;
16471639 default :
16481640 BUG ();
16491641 }
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+ }
16501649 nla_nest_end (skb , option_item );
16511650 return 0 ;
16521651
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 ;
16571672}
16581673
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 ,
16621676 struct list_head * sel_opt_inst_list )
16631677{
16641678 struct nlattr * option_list ;
1679+ struct nlmsghdr * nlh ;
16651680 void * hdr ;
16661681 struct team_option_inst * opt_inst ;
16671682 int err ;
1683+ struct sk_buff * skb = NULL ;
1684+ bool incomplete ;
1685+ int i ;
16681686
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 ,
16701696 TEAM_CMD_OPTIONS_GET );
16711697 if (IS_ERR (hdr ))
16721698 return PTR_ERR (hdr );
@@ -1677,46 +1703,62 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
16771703 if (!option_list )
16781704 goto nla_put_failure ;
16791705
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 ) {
16811709 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+ }
16831717 goto errout ;
1718+ }
1719+ i ++ ;
16841720 }
16851721
16861722 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 );
16881737
16891738nla_put_failure :
16901739 err = - EMSGSIZE ;
16911740errout :
16921741 genlmsg_cancel (skb , hdr );
1742+ nlmsg_free (skb );
16931743 return err ;
16941744}
16951745
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-
17101746static int team_nl_cmd_options_get (struct sk_buff * skb , struct genl_info * info )
17111747{
17121748 struct team * team ;
1749+ struct team_option_inst * opt_inst ;
17131750 int err ;
1751+ LIST_HEAD (sel_opt_inst_list );
17141752
17151753 team = team_nl_team_get (info );
17161754 if (!team )
17171755 return - EINVAL ;
17181756
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 );
17201762
17211763 team_nl_team_put (team );
17221764
@@ -1963,28 +2005,18 @@ static struct genl_multicast_group team_change_event_mcgrp = {
19632005 .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME ,
19642006};
19652007
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+
19662015static int team_nl_send_event_options_get (struct team * team ,
19672016 struct list_head * sel_opt_inst_list )
19682017{
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 );
19882020}
19892021
19902022static int team_nl_send_event_port_list_get (struct team * team )
@@ -2053,7 +2085,8 @@ static void __team_options_change_check(struct team *team)
20532085 }
20542086 err = team_nl_send_event_options_get (team , & sel_opt_inst_list );
20552087 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 );
20572090}
20582091
20592092static void __team_option_inst_change (struct team * team ,
@@ -2066,7 +2099,8 @@ static void __team_option_inst_change(struct team *team,
20662099 list_add (& sel_opt_inst -> tmp_list , & sel_opt_inst_list );
20672100 err = team_nl_send_event_options_get (team , & sel_opt_inst_list );
20682101 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 );
20702104}
20712105
20722106/* rtnl lock is held */
0 commit comments