diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2011-06-09 21:27:09 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-06-09 23:38:07 -0400 |
commit | c7ac8679bec9397afe8918f788cbcef88c38da54 (patch) | |
tree | c152712de4c997ea79252ef9ac72aaedb8f88c18 /net/netlink/af_netlink.c | |
parent | 929dd047720785f099e12113780b3d7914ce6d9f (diff) |
rtnetlink: Compute and store minimum ifinfo dump size
The message size allocated for rtnl ifinfo dumps was limited to
a single page. This is not enough for additional interface info
available with devices that support SR-IOV and caused a bug in
which VF info would not be displayed if more than approximately
40 VFs were created per interface.
Implement a new function pointer for the rtnl_register service that will
calculate the amount of data required for the ifinfo dump and allocate
enough data to satisfy the request.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6ef64adf7362..0b92f75491b1 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1659,13 +1659,10 @@ static int netlink_dump(struct sock *sk) | |||
1659 | { | 1659 | { |
1660 | struct netlink_sock *nlk = nlk_sk(sk); | 1660 | struct netlink_sock *nlk = nlk_sk(sk); |
1661 | struct netlink_callback *cb; | 1661 | struct netlink_callback *cb; |
1662 | struct sk_buff *skb; | 1662 | struct sk_buff *skb = NULL; |
1663 | struct nlmsghdr *nlh; | 1663 | struct nlmsghdr *nlh; |
1664 | int len, err = -ENOBUFS; | 1664 | int len, err = -ENOBUFS; |
1665 | 1665 | int alloc_size; | |
1666 | skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL); | ||
1667 | if (!skb) | ||
1668 | goto errout; | ||
1669 | 1666 | ||
1670 | mutex_lock(nlk->cb_mutex); | 1667 | mutex_lock(nlk->cb_mutex); |
1671 | 1668 | ||
@@ -1675,6 +1672,12 @@ static int netlink_dump(struct sock *sk) | |||
1675 | goto errout_skb; | 1672 | goto errout_skb; |
1676 | } | 1673 | } |
1677 | 1674 | ||
1675 | alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE); | ||
1676 | |||
1677 | skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL); | ||
1678 | if (!skb) | ||
1679 | goto errout; | ||
1680 | |||
1678 | len = cb->dump(skb, cb); | 1681 | len = cb->dump(skb, cb); |
1679 | 1682 | ||
1680 | if (len > 0) { | 1683 | if (len > 0) { |
@@ -1721,7 +1724,8 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1721 | const struct nlmsghdr *nlh, | 1724 | const struct nlmsghdr *nlh, |
1722 | int (*dump)(struct sk_buff *skb, | 1725 | int (*dump)(struct sk_buff *skb, |
1723 | struct netlink_callback *), | 1726 | struct netlink_callback *), |
1724 | int (*done)(struct netlink_callback *)) | 1727 | int (*done)(struct netlink_callback *), |
1728 | u16 min_dump_alloc) | ||
1725 | { | 1729 | { |
1726 | struct netlink_callback *cb; | 1730 | struct netlink_callback *cb; |
1727 | struct sock *sk; | 1731 | struct sock *sk; |
@@ -1735,6 +1739,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1735 | cb->dump = dump; | 1739 | cb->dump = dump; |
1736 | cb->done = done; | 1740 | cb->done = done; |
1737 | cb->nlh = nlh; | 1741 | cb->nlh = nlh; |
1742 | cb->min_dump_alloc = min_dump_alloc; | ||
1738 | atomic_inc(&skb->users); | 1743 | atomic_inc(&skb->users); |
1739 | cb->skb = skb; | 1744 | cb->skb = skb; |
1740 | 1745 | ||