]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Jan 2013 21:41:56 +0000 (13:41 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Jan 2013 21:41:56 +0000 (13:41 -0800)
added patches:
acpi-do-not-use-lid-and-sleep-button-for-s5-wakeup.patch
epoll-prevent-missed-events-on-epoll_ctl_mod.patch
rtnetlink-compute-and-store-minimum-ifinfo-dump-size.patch
rtnetlink-fix-problem-with-buffer-allocation.patch
rtnetlink-fix-rtnl_calcit-and-rtnl_dump_ifinfo.patch

queue-3.0/acpi-do-not-use-lid-and-sleep-button-for-s5-wakeup.patch [new file with mode: 0644]
queue-3.0/epoll-prevent-missed-events-on-epoll_ctl_mod.patch [new file with mode: 0644]
queue-3.0/rtnetlink-compute-and-store-minimum-ifinfo-dump-size.patch [new file with mode: 0644]
queue-3.0/rtnetlink-fix-problem-with-buffer-allocation.patch [new file with mode: 0644]
queue-3.0/rtnetlink-fix-rtnl_calcit-and-rtnl_dump_ifinfo.patch [new file with mode: 0644]
queue-3.0/series

diff --git a/queue-3.0/acpi-do-not-use-lid-and-sleep-button-for-s5-wakeup.patch b/queue-3.0/acpi-do-not-use-lid-and-sleep-button-for-s5-wakeup.patch
new file mode 100644 (file)
index 0000000..56dd87d
--- /dev/null
@@ -0,0 +1,48 @@
+From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001
+From: Zhang Rui <rui.zhang@intel.com>
+Date: Tue, 4 Dec 2012 23:23:16 +0100
+Subject: ACPI : do not use Lid and Sleep button for S5 wakeup
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+commit b7e383046c2c7c13ad928cd7407eafff758ddd4b upstream.
+
+When system enters power off, the _PSW of Lid device is enabled.
+But this may cause the system to reboot instead of power off.
+
+A proper way to fix this is to always disable lid wakeup capability for S5.
+
+References: https://bugzilla.kernel.org/show_bug.cgi?id=35262
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Joseph Salisbury <joseph.salisbury@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/scan.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -789,8 +789,8 @@ acpi_bus_extract_wakeup_device_power_pac
+ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
+ {
+       struct acpi_device_id button_device_ids[] = {
+-              {"PNP0C0D", 0},
+               {"PNP0C0C", 0},
++              {"PNP0C0D", 0},
+               {"PNP0C0E", 0},
+               {"", 0},
+       };
+@@ -802,6 +802,11 @@ static void acpi_bus_set_run_wake_flags(
+       /* Power button, Lid switch always enable wakeup */
+       if (!acpi_match_device_ids(device, button_device_ids)) {
+               device->wakeup.flags.run_wake = 1;
++              if (!acpi_match_device_ids(device, &button_device_ids[1])) {
++                      /* Do not use Lid/sleep button for S5 wakeup */
++                      if (device->wakeup.sleep_state == ACPI_STATE_S5)
++                              device->wakeup.sleep_state = ACPI_STATE_S4;
++              }
+               device_set_wakeup_capable(&device->dev, true);
+               return;
+       }
diff --git a/queue-3.0/epoll-prevent-missed-events-on-epoll_ctl_mod.patch b/queue-3.0/epoll-prevent-missed-events-on-epoll_ctl_mod.patch
new file mode 100644 (file)
index 0000000..779719f
--- /dev/null
@@ -0,0 +1,79 @@
+From: Eric Wong <normalperson@yhbt.net>
+Date: Tue, 1 Jan 2013 21:20:27 +0000
+Subject: epoll: prevent missed events on EPOLL_CTL_MOD
+
+commit 128dd1759d96ad36c379240f8b9463e8acfd37a1 upstream.
+
+EPOLL_CTL_MOD sets the interest mask before calling f_op->poll() to
+ensure events are not missed.  Since the modifications to the interest
+mask are not protected by the same lock as ep_poll_callback, we need to
+ensure the change is visible to other CPUs calling ep_poll_callback.
+
+We also need to ensure f_op->poll() has an up-to-date view of past
+events which occured before we modified the interest mask.  So this
+barrier also pairs with the barrier in wq_has_sleeper().
+
+This should guarantee either ep_poll_callback or f_op->poll() (or both)
+will notice the readiness of a recently-ready/modified item.
+
+This issue was encountered by Andreas Voellmy and Junchang(Jason) Wang in:
+http://thread.gmane.org/gmane.linux.kernel/1408782/
+
+Signed-off-by: Eric Wong <normalperson@yhbt.net>
+Cc: Hans Verkuil <hans.verkuil@cisco.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Davide Libenzi <davidel@xmailserver.org>
+Cc: Hans de Goede <hdegoede@redhat.com>
+Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
+Cc: David Miller <davem@davemloft.net>
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Andreas Voellmy <andreas.voellmy@yale.edu>
+Tested-by: "Junchang(Jason) Wang" <junchang.wang@yale.edu>
+Cc: netdev@vger.kernel.org
+Cc: linux-fsdevel@vger.kernel.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/eventpoll.c |   22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -1197,10 +1197,30 @@ static int ep_modify(struct eventpoll *e
+        * otherwise we might miss an event that happens between the
+        * f_op->poll() call and the new event set registering.
+        */
+-      epi->event.events = event->events;
++      epi->event.events = event->events; /* need barrier below */
+       epi->event.data = event->data; /* protected by mtx */
+       /*
++       * The following barrier has two effects:
++       *
++       * 1) Flush epi changes above to other CPUs.  This ensures
++       *    we do not miss events from ep_poll_callback if an
++       *    event occurs immediately after we call f_op->poll().
++       *    We need this because we did not take ep->lock while
++       *    changing epi above (but ep_poll_callback does take
++       *    ep->lock).
++       *
++       * 2) We also need to ensure we do not miss _past_ events
++       *    when calling f_op->poll().  This barrier also
++       *    pairs with the barrier in wq_has_sleeper (see
++       *    comments for wq_has_sleeper).
++       *
++       * This barrier will now guarantee ep_poll_callback or f_op->poll
++       * (or both) will notice the readiness of an item.
++       */
++      smp_mb();
++
++      /*
+        * Get current event bits. We can safely use the file* here because
+        * its usage count has been increased by the caller of this function.
+        */
diff --git a/queue-3.0/rtnetlink-compute-and-store-minimum-ifinfo-dump-size.patch b/queue-3.0/rtnetlink-compute-and-store-minimum-ifinfo-dump-size.patch
new file mode 100644 (file)
index 0000000..6792390
--- /dev/null
@@ -0,0 +1,712 @@
+From bhutchings@solarflare.com  Mon Jan 14 13:02:41 2013
+From: Greg Rose <gregory.v.rose@intel.com>
+Date: Fri, 4 Jan 2013 00:32:54 +0000
+Subject: rtnetlink: Compute and store minimum ifinfo dump size
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "David S. Miller" <davem@davemloft.net>, Greg Rose <gregory.v.rose@intel.com>, Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Message-ID: <1357259574.2685.61.camel@bwh-desktop.uk.solarflarecom.com>
+
+
+From: Greg Rose <gregory.v.rose@intel.com>
+
+commit c7ac8679bec9397afe8918f788cbcef88c38da54 upstream.
+
+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>
+Cc: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/netlink.c    |    2 -
+ include/linux/netlink.h              |    6 ++-
+ include/net/rtnetlink.h              |    7 ++--
+ net/bridge/br_netlink.c              |   15 +++++---
+ net/core/fib_rules.c                 |    6 +--
+ net/core/neighbour.c                 |   11 +++---
+ net/core/rtnetlink.c                 |   60 ++++++++++++++++++++++++++++-------
+ net/dcb/dcbnl.c                      |    4 +-
+ net/decnet/dn_dev.c                  |    6 +--
+ net/decnet/dn_fib.c                  |    4 +-
+ net/decnet/dn_route.c                |    5 +-
+ net/ipv4/devinet.c                   |    6 +--
+ net/ipv4/fib_frontend.c              |    6 +--
+ net/ipv4/inet_diag.c                 |    2 -
+ net/ipv4/ipmr.c                      |    3 +
+ net/ipv4/route.c                     |    2 -
+ net/ipv6/addrconf.c                  |   16 +++++----
+ net/ipv6/addrlabel.c                 |    9 +++--
+ net/ipv6/ip6_fib.c                   |    3 +
+ net/ipv6/ip6mr.c                     |    3 +
+ net/ipv6/route.c                     |    6 +--
+ net/netfilter/ipset/ip_set_core.c    |    2 -
+ net/netfilter/nf_conntrack_netlink.c |    4 +-
+ net/netlink/af_netlink.c             |   17 ++++++---
+ net/netlink/genetlink.c              |    2 -
+ net/phonet/pn_netlink.c              |   13 ++++---
+ net/sched/act_api.c                  |    7 ++--
+ net/sched/cls_api.c                  |    6 +--
+ net/sched/sch_api.c                  |   12 +++----
+ net/xfrm/xfrm_user.c                 |    3 +
+ 30 files changed, 158 insertions(+), 90 deletions(-)
+
+--- a/drivers/infiniband/core/netlink.c
++++ b/drivers/infiniband/core/netlink.c
+@@ -148,7 +148,7 @@ static int ibnl_rcv_msg(struct sk_buff *
+                               return -EINVAL;
+                       return netlink_dump_start(nls, skb, nlh,
+                                                 client->cb_table[op].dump,
+-                                                NULL);
++                                                NULL, 0);
+               }
+       }
+--- a/include/linux/netlink.h
++++ b/include/linux/netlink.h
+@@ -221,7 +221,8 @@ struct netlink_callback {
+       int                     (*dump)(struct sk_buff * skb,
+                                       struct netlink_callback *cb);
+       int                     (*done)(struct netlink_callback *cb);
+-      int                     family;
++      u16                     family;
++      u16                     min_dump_alloc;
+       long                    args[6];
+ };
+@@ -259,7 +260,8 @@ __nlmsg_put(struct sk_buff *skb, u32 pid
+ extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+                             const struct nlmsghdr *nlh,
+                             int (*dump)(struct sk_buff *skb, struct netlink_callback*),
+-                            int (*done)(struct netlink_callback*));
++                            int (*done)(struct netlink_callback*),
++                            u16 min_dump_alloc);
+ #define NL_NONROOT_RECV 0x1
+--- a/include/net/rtnetlink.h
++++ b/include/net/rtnetlink.h
+@@ -6,11 +6,14 @@
+ typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
+ typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
++typedef u16 (*rtnl_calcit_func)(struct sk_buff *);
+ extern int    __rtnl_register(int protocol, int msgtype,
+-                              rtnl_doit_func, rtnl_dumpit_func);
++                              rtnl_doit_func, rtnl_dumpit_func,
++                              rtnl_calcit_func);
+ extern void   rtnl_register(int protocol, int msgtype,
+-                            rtnl_doit_func, rtnl_dumpit_func);
++                            rtnl_doit_func, rtnl_dumpit_func,
++                            rtnl_calcit_func);
+ extern int    rtnl_unregister(int protocol, int msgtype);
+ extern void   rtnl_unregister_all(int protocol);
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -219,19 +219,24 @@ int __init br_netlink_init(void)
+       if (err < 0)
+               goto err1;
+-      err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo);
++      err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
++                            br_dump_ifinfo, NULL);
+       if (err)
+               goto err2;
+-      err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL);
++      err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
++                            br_rtm_setlink, NULL, NULL);
+       if (err)
+               goto err3;
+-      err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL);
++      err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
++                            br_fdb_add, NULL, NULL);
+       if (err)
+               goto err3;
+-      err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL);
++      err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
++                            br_fdb_delete, NULL, NULL);
+       if (err)
+               goto err3;
+-      err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump);
++      err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
++                            NULL, br_fdb_dump, NULL);
+       if (err)
+               goto err3;
+--- a/net/core/fib_rules.c
++++ b/net/core/fib_rules.c
+@@ -740,9 +740,9 @@ static struct pernet_operations fib_rule
+ static int __init fib_rules_init(void)
+ {
+       int err;
+-      rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
++      rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule, NULL);
+       err = register_pernet_subsys(&fib_rules_net_ops);
+       if (err < 0)
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -2918,12 +2918,13 @@ EXPORT_SYMBOL(neigh_sysctl_unregister);
+ static int __init neigh_init(void)
+ {
+-      rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info);
++      rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info);
+-      rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
++                    NULL);
++      rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
+       return 0;
+ }
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -56,9 +56,11 @@
+ struct rtnl_link {
+       rtnl_doit_func          doit;
+       rtnl_dumpit_func        dumpit;
++      rtnl_calcit_func        calcit;
+ };
+ static DEFINE_MUTEX(rtnl_mutex);
++static u16 min_ifinfo_dump_size;
+ void rtnl_lock(void)
+ {
+@@ -144,12 +146,28 @@ static rtnl_dumpit_func rtnl_get_dumpit(
+       return tab ? tab[msgindex].dumpit : NULL;
+ }
++static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
++{
++      struct rtnl_link *tab;
++
++      if (protocol <= RTNL_FAMILY_MAX)
++              tab = rtnl_msg_handlers[protocol];
++      else
++              tab = NULL;
++
++      if (tab == NULL || tab[msgindex].calcit == NULL)
++              tab = rtnl_msg_handlers[PF_UNSPEC];
++
++      return tab ? tab[msgindex].calcit : NULL;
++}
++
+ /**
+  * __rtnl_register - Register a rtnetlink message type
+  * @protocol: Protocol family or PF_UNSPEC
+  * @msgtype: rtnetlink message type
+  * @doit: Function pointer called for each request message
+  * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
++ * @calcit: Function pointer to calc size of dump message
+  *
+  * Registers the specified function pointers (at least one of them has
+  * to be non-NULL) to be called whenever a request message for the
+@@ -162,7 +180,8 @@ static rtnl_dumpit_func rtnl_get_dumpit(
+  * Returns 0 on success or a negative error code.
+  */
+ int __rtnl_register(int protocol, int msgtype,
+-                  rtnl_doit_func doit, rtnl_dumpit_func dumpit)
++                  rtnl_doit_func doit, rtnl_dumpit_func dumpit,
++                  rtnl_calcit_func calcit)
+ {
+       struct rtnl_link *tab;
+       int msgindex;
+@@ -185,6 +204,9 @@ int __rtnl_register(int protocol, int ms
+       if (dumpit)
+               tab[msgindex].dumpit = dumpit;
++      if (calcit)
++              tab[msgindex].calcit = calcit;
++
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(__rtnl_register);
+@@ -199,9 +221,10 @@ EXPORT_SYMBOL_GPL(__rtnl_register);
+  * of memory implies no sense in continuing.
+  */
+ void rtnl_register(int protocol, int msgtype,
+-                 rtnl_doit_func doit, rtnl_dumpit_func dumpit)
++                 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
++                 rtnl_calcit_func calcit)
+ {
+-      if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0)
++      if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
+               panic("Unable to register rtnetlink message handler, "
+                     "protocol = %d, message type = %d\n",
+                     protocol, msgtype);
+@@ -1825,6 +1848,11 @@ static int rtnl_getlink(struct sk_buff *
+       return err;
+ }
++static u16 rtnl_calcit(struct sk_buff *skb)
++{
++      return min_ifinfo_dump_size;
++}
++
+ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+       int idx;
+@@ -1854,11 +1882,14 @@ void rtmsg_ifinfo(int type, struct net_d
+       struct net *net = dev_net(dev);
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
++      size_t if_info_size;
+-      skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
++      skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
+       if (skb == NULL)
+               goto errout;
++      min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
++
+       err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in if_nlmsg_size() */
+@@ -1909,14 +1940,20 @@ static int rtnetlink_rcv_msg(struct sk_b
+       if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
+               struct sock *rtnl;
+               rtnl_dumpit_func dumpit;
++              rtnl_calcit_func calcit;
++              u16 min_dump_alloc = 0;
+               dumpit = rtnl_get_dumpit(family, type);
+               if (dumpit == NULL)
+                       return -EOPNOTSUPP;
++              calcit = rtnl_get_calcit(family, type);
++              if (calcit)
++                      min_dump_alloc = calcit(skb);
+               __rtnl_unlock();
+               rtnl = net->rtnl;
+-              err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
++              err = netlink_dump_start(rtnl, skb, nlh, dumpit,
++                                       NULL, min_dump_alloc);
+               rtnl_lock();
+               return err;
+       }
+@@ -2026,12 +2063,13 @@ void __init rtnetlink_init(void)
+       netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
+       register_netdevice_notifier(&rtnetlink_dev_notifier);
+-      rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
+-      rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
++                    rtnl_dump_ifinfo, rtnl_calcit);
++      rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
+-      rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
++      rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
+ }
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -1819,8 +1819,8 @@ static int __init dcbnl_init(void)
+ {
+       INIT_LIST_HEAD(&dcb_app_list);
+-      rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
+       return 0;
+ }
+--- a/net/decnet/dn_dev.c
++++ b/net/decnet/dn_dev.c
+@@ -1414,9 +1414,9 @@ void __init dn_dev_init(void)
+       dn_dev_devices_on();
+-      rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL);
+-      rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
+-      rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
++      rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL, NULL);
++      rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL, NULL);
++      rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr, NULL);
+       proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
+--- a/net/decnet/dn_fib.c
++++ b/net/decnet/dn_fib.c
+@@ -763,8 +763,8 @@ void __init dn_fib_init(void)
+       register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
+-      rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL);
+-      rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL);
++      rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL, NULL);
++      rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL, NULL);
+ }
+--- a/net/decnet/dn_route.c
++++ b/net/decnet/dn_route.c
+@@ -1843,10 +1843,11 @@ void __init dn_route_init(void)
+       proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
+ #ifdef CONFIG_DECNET_ROUTER
+-      rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
++      rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
++                    dn_fib_dump, NULL);
+ #else
+       rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
+-                    dn_cache_dump);
++                    dn_cache_dump, NULL);
+ #endif
+ }
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -1838,8 +1838,8 @@ void __init devinet_init(void)
+       rtnl_af_register(&inet_af_ops);
+-      rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
+-      rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
+-      rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
++      rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, NULL);
++      rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
++      rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
+ }
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -1124,9 +1124,9 @@ static struct pernet_operations fib_net_
+ void __init ip_fib_init(void)
+ {
+-      rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
+-      rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
+-      rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
++      rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL);
++      rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL);
++      rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL);
+       register_pernet_subsys(&fib_net_ops);
+       register_netdevice_notifier(&fib_netdev_notifier);
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -869,7 +869,7 @@ static int inet_diag_rcv_msg(struct sk_b
+               }
+               return netlink_dump_start(idiagnl, skb, nlh,
+-                                        inet_diag_dump, NULL);
++                                        inet_diag_dump, NULL, 0);
+       }
+       return inet_diag_get_exact(skb, nlh);
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -2554,7 +2554,8 @@ int __init ip_mr_init(void)
+               goto add_proto_fail;
+       }
+ #endif
+-      rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute);
++      rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE,
++                    NULL, ipmr_rtm_dumproute, NULL);
+       return 0;
+ #ifdef CONFIG_IP_PIMSM_V2
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -3454,7 +3454,7 @@ int __init ip_rt_init(void)
+       xfrm_init();
+       xfrm4_init(ip_rt_max_size);
+ #endif
+-      rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL);
++      rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
+ #ifdef CONFIG_SYSCTL
+       register_pernet_subsys(&sysctl_route_ops);
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -4694,16 +4694,20 @@ int __init addrconf_init(void)
+       if (err < 0)
+               goto errout_af;
+-      err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
++      err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
++                            NULL);
+       if (err < 0)
+               goto errout;
+       /* Only the first call to __rtnl_register can fail */
+-      __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL);
+-      __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL);
+-      __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr);
+-      __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
+-      __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
++      __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL);
++      __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL);
++      __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr,
++                      inet6_dump_ifaddr, NULL);
++      __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL,
++                      inet6_dump_ifmcaddr, NULL);
++      __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
++                      inet6_dump_ifacaddr, NULL);
+       ipv6_addr_label_rtnl_register();
+--- a/net/ipv6/addrlabel.c
++++ b/net/ipv6/addrlabel.c
+@@ -592,8 +592,11 @@ out:
+ void __init ipv6_addr_label_rtnl_register(void)
+ {
+-      __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL);
+-      __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL);
+-      __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump);
++      __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel,
++                      NULL, NULL);
++      __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel,
++                      NULL, NULL);
++      __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get,
++                      ip6addrlbl_dump, NULL);
+ }
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -1586,7 +1586,8 @@ int __init fib6_init(void)
+       if (ret)
+               goto out_kmem_cache_create;
+-      ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
++      ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib,
++                            NULL);
+       if (ret)
+               goto out_unregister_subsys;
+ out:
+--- a/net/ipv6/ip6mr.c
++++ b/net/ipv6/ip6mr.c
+@@ -1356,7 +1356,8 @@ int __init ip6_mr_init(void)
+               goto add_proto_fail;
+       }
+ #endif
+-      rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute);
++      rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
++                    ip6mr_rtm_dumproute, NULL);
+       return 0;
+ #ifdef CONFIG_IPV6_PIMSM_V2
+ add_proto_fail:
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -2956,9 +2956,9 @@ int __init ip6_route_init(void)
+               goto fib6_rules_init;
+       ret = -ENOBUFS;
+-      if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
+-          __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
+-          __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
++      if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
++          __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
++          __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
+               goto out_register_late_subsys;
+       ret = register_netdevice_notifier(&ip6_route_dev_notifier);
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -1120,7 +1120,7 @@ ip_set_dump(struct sock *ctnl, struct sk
+       return netlink_dump_start(ctnl, skb, nlh,
+                                 ip_set_dump_start,
+-                                ip_set_dump_done);
++                                ip_set_dump_done, 0);
+ }
+ /* Add, del and test */
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -970,7 +970,7 @@ ctnetlink_get_conntrack(struct sock *ctn
+       if (nlh->nlmsg_flags & NLM_F_DUMP)
+               return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
+-                                        ctnetlink_done);
++                                        ctnetlink_done, 0);
+       err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
+       if (err < 0)
+@@ -1840,7 +1840,7 @@ ctnetlink_get_expect(struct sock *ctnl,
+       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+               return netlink_dump_start(ctnl, skb, nlh,
+                                         ctnetlink_exp_dump_table,
+-                                        ctnetlink_exp_done);
++                                        ctnetlink_exp_done, 0);
+       }
+       err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1677,13 +1677,10 @@ static int netlink_dump(struct sock *sk)
+ {
+       struct netlink_sock *nlk = nlk_sk(sk);
+       struct netlink_callback *cb;
+-      struct sk_buff *skb;
++      struct sk_buff *skb = NULL;
+       struct nlmsghdr *nlh;
+       int len, err = -ENOBUFS;
+-
+-      skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
+-      if (!skb)
+-              goto errout;
++      int alloc_size;
+       mutex_lock(nlk->cb_mutex);
+@@ -1693,6 +1690,12 @@ static int netlink_dump(struct sock *sk)
+               goto errout_skb;
+       }
++      alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
++
++      skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL);
++      if (!skb)
++              goto errout;
++
+       len = cb->dump(skb, cb);
+       if (len > 0) {
+@@ -1735,7 +1738,8 @@ int netlink_dump_start(struct sock *ssk,
+                      const struct nlmsghdr *nlh,
+                      int (*dump)(struct sk_buff *skb,
+                                  struct netlink_callback *),
+-                     int (*done)(struct netlink_callback *))
++                     int (*done)(struct netlink_callback *),
++                     u16 min_dump_alloc)
+ {
+       struct netlink_callback *cb;
+       struct sock *sk;
+@@ -1749,6 +1753,7 @@ int netlink_dump_start(struct sock *ssk,
+       cb->dump = dump;
+       cb->done = done;
+       cb->nlh = nlh;
++      cb->min_dump_alloc = min_dump_alloc;
+       atomic_inc(&skb->users);
+       cb->skb = skb;
+--- a/net/netlink/genetlink.c
++++ b/net/netlink/genetlink.c
+@@ -525,7 +525,7 @@ static int genl_rcv_msg(struct sk_buff *
+               genl_unlock();
+               err = netlink_dump_start(net->genl_sock, skb, nlh,
+-                                       ops->dumpit, ops->done);
++                                       ops->dumpit, ops->done, 0);
+               genl_lock();
+               return err;
+       }
+--- a/net/phonet/pn_netlink.c
++++ b/net/phonet/pn_netlink.c
+@@ -289,15 +289,16 @@ out:
+ int __init phonet_netlink_register(void)
+ {
+-      int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
++      int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit,
++                                NULL, NULL);
+       if (err)
+               return err;
+       /* Further __rtnl_register() cannot fail */
+-      __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
+-      __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
+-      __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL);
+-      __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL);
+-      __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit);
++      __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL, NULL);
++      __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit, NULL);
++      __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL, NULL);
++      __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL, NULL);
++      __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit, NULL);
+       return 0;
+ }
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -1115,9 +1115,10 @@ nlmsg_failure:
+ static int __init tc_action_init(void)
+ {
+-      rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action);
++      rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
++                    NULL);
+       return 0;
+ }
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -610,10 +610,10 @@ EXPORT_SYMBOL(tcf_exts_dump_stats);
+ static int __init tc_filter_init(void)
+ {
+-      rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL);
++      rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, NULL);
+       rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
+-                                               tc_dump_tfilter);
++                    tc_dump_tfilter, NULL);
+       return 0;
+ }
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -1792,12 +1792,12 @@ static int __init pktsched_init(void)
+       register_qdisc(&pfifo_head_drop_qdisc_ops);
+       register_qdisc(&mq_qdisc_ops);
+-      rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc);
+-      rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass);
++      rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc, NULL);
++      rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL, NULL);
++      rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass, NULL);
+       return 0;
+ }
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -2326,7 +2326,8 @@ static int xfrm_user_rcv_msg(struct sk_b
+               if (link->dump == NULL)
+                       return -EINVAL;
+-              return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done);
++              return netlink_dump_start(net->xfrm.nlsk, skb, nlh,
++                                        link->dump, link->done, 0);
+       }
+       err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
diff --git a/queue-3.0/rtnetlink-fix-problem-with-buffer-allocation.patch b/queue-3.0/rtnetlink-fix-problem-with-buffer-allocation.patch
new file mode 100644 (file)
index 0000000..7444a16
--- /dev/null
@@ -0,0 +1,287 @@
+From bhutchings@solarflare.com  Mon Jan 14 13:03:31 2013
+From: Greg Rose <gregory.v.rose@intel.com>
+Date: Fri, 4 Jan 2013 00:33:34 +0000
+Subject: rtnetlink: Fix problem with buffer allocation
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "David S. Miller" <davem@davemloft.net>, Greg Rose <gregory.v.rose@intel.com>
+Message-ID: <1357259614.2685.62.camel@bwh-desktop.uk.solarflarecom.com>
+
+
+From: Greg Rose <gregory.v.rose@intel.com>
+
+commit 115c9b81928360d769a76c632bae62d15206a94a upstream.
+
+Implement a new netlink attribute type IFLA_EXT_MASK.  The mask
+is a 32 bit value that can be used to indicate to the kernel that
+certain extended ifinfo values are requested by the user application.
+At this time the only mask value defined is RTEXT_FILTER_VF to
+indicate that the user wants the ifinfo dump to send information
+about the VFs belonging to the interface.
+
+This patch fixes a bug in which certain applications do not have
+large enough buffers to accommodate the extra information returned
+by the kernel with large numbers of SR-IOV virtual functions.
+Those applications will not send the new netlink attribute with
+the interface info dump request netlink messages so they will
+not get unexpectedly large request buffers returned by the kernel.
+
+Modifies the rtnl_calcit function to traverse the list of net
+devices and compute the minimum buffer size that can hold the
+info dumps of all matching devices based upon the filter passed
+in via the new netlink attribute filter mask.  If no filter
+mask is sent then the buffer allocation defaults to NLMSG_GOODSIZE.
+
+With this change it is possible to add yet to be defined netlink
+attributes to the dump request which should make it fairly extensible
+in the future.
+
+Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
+Acked-by: Greg Rose <gregory.v.rose@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.0:
+ - Adjust context
+ - Drop the change in do_setlink() that reverts commit f18da1456581
+   ('net: RTNETLINK adjusting values of min_ifinfo_dump_size'), which
+   was never applied here]
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/if_link.h   |    1 
+ include/linux/rtnetlink.h |    3 +
+ include/net/rtnetlink.h   |    2 -
+ net/core/rtnetlink.c      |   77 ++++++++++++++++++++++++++++++++++------------
+ 4 files changed, 63 insertions(+), 20 deletions(-)
+
+--- a/include/linux/if_link.h
++++ b/include/linux/if_link.h
+@@ -137,6 +137,7 @@ enum {
+       IFLA_AF_SPEC,
+       IFLA_GROUP,             /* Group the device belongs to */
+       IFLA_NET_NS_FD,
++      IFLA_EXT_MASK,          /* Extended info mask, VFs, etc */
+       __IFLA_MAX
+ };
+--- a/include/linux/rtnetlink.h
++++ b/include/linux/rtnetlink.h
+@@ -600,6 +600,9 @@ struct tcamsg {
+ #define TCA_ACT_TAB 1 /* attr type must be >=1 */     
+ #define TCAA_MAX 1
++/* New extended info filters for IFLA_EXT_MASK */
++#define RTEXT_FILTER_VF               (1 << 0)
++
+ /* End of information exported to user level */
+ #ifdef __KERNEL__
+--- a/include/net/rtnetlink.h
++++ b/include/net/rtnetlink.h
+@@ -6,7 +6,7 @@
+ typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
+ typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
+-typedef u16 (*rtnl_calcit_func)(struct sk_buff *);
++typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *);
+ extern int    __rtnl_register(int protocol, int msgtype,
+                               rtnl_doit_func, rtnl_dumpit_func,
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -60,7 +60,6 @@ struct rtnl_link {
+ };
+ static DEFINE_MUTEX(rtnl_mutex);
+-static u16 min_ifinfo_dump_size;
+ void rtnl_lock(void)
+ {
+@@ -727,10 +726,11 @@ static void copy_rtnl_link_stats64(void
+ }
+ /* All VF info */
+-static inline int rtnl_vfinfo_size(const struct net_device *dev)
++static inline int rtnl_vfinfo_size(const struct net_device *dev,
++                                 u32 ext_filter_mask)
+ {
+-      if (dev->dev.parent && dev_is_pci(dev->dev.parent)) {
+-
++      if (dev->dev.parent && dev_is_pci(dev->dev.parent) &&
++          (ext_filter_mask & RTEXT_FILTER_VF)) {
+               int num_vfs = dev_num_vf(dev->dev.parent);
+               size_t size = nla_total_size(sizeof(struct nlattr));
+               size += nla_total_size(num_vfs * sizeof(struct nlattr));
+@@ -768,7 +768,8 @@ static size_t rtnl_port_size(const struc
+               return port_self_size;
+ }
+-static noinline size_t if_nlmsg_size(const struct net_device *dev)
++static noinline size_t if_nlmsg_size(const struct net_device *dev,
++                                   u32 ext_filter_mask)
+ {
+       return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+              + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+@@ -786,8 +787,9 @@ static noinline size_t if_nlmsg_size(con
+              + nla_total_size(4) /* IFLA_MASTER */
+              + nla_total_size(1) /* IFLA_OPERSTATE */
+              + nla_total_size(1) /* IFLA_LINKMODE */
+-             + nla_total_size(4) /* IFLA_NUM_VF */
+-             + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
++             + nla_total_size(ext_filter_mask
++                              & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
++             + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
+              + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
+              + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
+              + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
+@@ -870,7 +872,7 @@ static int rtnl_port_fill(struct sk_buff
+ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
+                           int type, u32 pid, u32 seq, u32 change,
+-                          unsigned int flags)
++                          unsigned int flags, u32 ext_filter_mask)
+ {
+       struct ifinfomsg *ifm;
+       struct nlmsghdr *nlh;
+@@ -943,10 +945,11 @@ static int rtnl_fill_ifinfo(struct sk_bu
+               goto nla_put_failure;
+       copy_rtnl_link_stats64(nla_data(attr), stats);
+-      if (dev->dev.parent)
++      if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF))
+               NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
+-      if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {
++      if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent
++          && (ext_filter_mask & RTEXT_FILTER_VF)) {
+               int i;
+               struct nlattr *vfinfo, *vf;
+@@ -1033,11 +1036,20 @@ static int rtnl_dump_ifinfo(struct sk_bu
+       struct net_device *dev;
+       struct hlist_head *head;
+       struct hlist_node *node;
++      struct nlattr *tb[IFLA_MAX+1];
++      u32 ext_filter_mask = 0;
+       s_h = cb->args[0];
+       s_idx = cb->args[1];
+       rcu_read_lock();
++
++      nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
++                  ifla_policy);
++
++      if (tb[IFLA_EXT_MASK])
++              ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++
+       for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+               idx = 0;
+               head = &net->dev_index_head[h];
+@@ -1047,7 +1059,8 @@ static int rtnl_dump_ifinfo(struct sk_bu
+                       if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
+                                            NETLINK_CB(cb->skb).pid,
+                                            cb->nlh->nlmsg_seq, 0,
+-                                           NLM_F_MULTI) <= 0)
++                                           NLM_F_MULTI,
++                                           ext_filter_mask) <= 0)
+                               goto out;
+ cont:
+                       idx++;
+@@ -1081,6 +1094,7 @@ const struct nla_policy ifla_policy[IFLA
+       [IFLA_VF_PORTS]         = { .type = NLA_NESTED },
+       [IFLA_PORT_SELF]        = { .type = NLA_NESTED },
+       [IFLA_AF_SPEC]          = { .type = NLA_NESTED },
++      [IFLA_EXT_MASK]         = { .type = NLA_U32 },
+ };
+ EXPORT_SYMBOL(ifla_policy);
+@@ -1813,6 +1827,7 @@ static int rtnl_getlink(struct sk_buff *
+       struct net_device *dev = NULL;
+       struct sk_buff *nskb;
+       int err;
++      u32 ext_filter_mask = 0;
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+       if (err < 0)
+@@ -1821,6 +1836,9 @@ static int rtnl_getlink(struct sk_buff *
+       if (tb[IFLA_IFNAME])
+               nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
++      if (tb[IFLA_EXT_MASK])
++              ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++
+       ifm = nlmsg_data(nlh);
+       if (ifm->ifi_index > 0)
+               dev = __dev_get_by_index(net, ifm->ifi_index);
+@@ -1832,12 +1850,12 @@ static int rtnl_getlink(struct sk_buff *
+       if (dev == NULL)
+               return -ENODEV;
+-      nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
++      nskb = nlmsg_new(if_nlmsg_size(dev, ext_filter_mask), GFP_KERNEL);
+       if (nskb == NULL)
+               return -ENOBUFS;
+       err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid,
+-                             nlh->nlmsg_seq, 0, 0);
++                             nlh->nlmsg_seq, 0, 0, ext_filter_mask);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in if_nlmsg_size */
+               WARN_ON(err == -EMSGSIZE);
+@@ -1848,8 +1866,31 @@ static int rtnl_getlink(struct sk_buff *
+       return err;
+ }
+-static u16 rtnl_calcit(struct sk_buff *skb)
++static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
++      struct net *net = sock_net(skb->sk);
++      struct net_device *dev;
++      struct nlattr *tb[IFLA_MAX+1];
++      u32 ext_filter_mask = 0;
++      u16 min_ifinfo_dump_size = 0;
++
++      nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, ifla_policy);
++
++      if (tb[IFLA_EXT_MASK])
++              ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++
++      if (!ext_filter_mask)
++              return NLMSG_GOODSIZE;
++      /*
++       * traverse the list of net devices and compute the minimum
++       * buffer size based upon the filter mask.
++       */
++      list_for_each_entry(dev, &net->dev_base_head, dev_list) {
++              min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size,
++                                           if_nlmsg_size(dev,
++                                                         ext_filter_mask));
++      }
++
+       return min_ifinfo_dump_size;
+ }
+@@ -1884,13 +1925,11 @@ void rtmsg_ifinfo(int type, struct net_d
+       int err = -ENOBUFS;
+       size_t if_info_size;
+-      skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
++      skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), GFP_KERNEL);
+       if (skb == NULL)
+               goto errout;
+-      min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
+-
+-      err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
++      err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in if_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+@@ -1948,7 +1987,7 @@ static int rtnetlink_rcv_msg(struct sk_b
+                       return -EOPNOTSUPP;
+               calcit = rtnl_get_calcit(family, type);
+               if (calcit)
+-                      min_dump_alloc = calcit(skb);
++                      min_dump_alloc = calcit(skb, nlh);
+               __rtnl_unlock();
+               rtnl = net->rtnl;
diff --git a/queue-3.0/rtnetlink-fix-rtnl_calcit-and-rtnl_dump_ifinfo.patch b/queue-3.0/rtnetlink-fix-rtnl_calcit-and-rtnl_dump_ifinfo.patch
new file mode 100644 (file)
index 0000000..beacd0e
--- /dev/null
@@ -0,0 +1,63 @@
+From bhutchings@solarflare.com  Mon Jan 14 13:03:48 2013
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Fri, 4 Jan 2013 00:34:22 +0000
+Subject: rtnetlink: fix rtnl_calcit() and rtnl_dump_ifinfo()
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "David S. Miller" <davem@davemloft.net>, Eric Dumazet <eric.dumazet@gmail.com>, Greg Rose <gregory.v.rose@intel.com>
+Message-ID: <1357259662.2685.63.camel@bwh-desktop.uk.solarflarecom.com>
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+commit a4b64fbe482c7766f7925f03067fc637716bfa3f upstream.
+
+nlmsg_parse() might return an error, so test its return value before
+potential random memory accesses.
+
+Errors introduced in commit 115c9b81928 (rtnetlink: Fix problem with
+buffer allocation)
+
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Acked-by: Greg Rose <gregory.v.rose@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/rtnetlink.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1044,11 +1044,12 @@ static int rtnl_dump_ifinfo(struct sk_bu
+       rcu_read_lock();
+-      nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+-                  ifla_policy);
++      if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
++                      ifla_policy) >= 0) {
+-      if (tb[IFLA_EXT_MASK])
+-              ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++              if (tb[IFLA_EXT_MASK])
++                      ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++      }
+       for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+               idx = 0;
+@@ -1874,10 +1875,11 @@ static u16 rtnl_calcit(struct sk_buff *s
+       u32 ext_filter_mask = 0;
+       u16 min_ifinfo_dump_size = 0;
+-      nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, ifla_policy);
+-
+-      if (tb[IFLA_EXT_MASK])
+-              ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++      if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
++                      ifla_policy) >= 0) {
++              if (tb[IFLA_EXT_MASK])
++                      ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
++      }
+       if (!ext_filter_mask)
+               return NLMSG_GOODSIZE;
index 3a2047ebb201d5e085315cd485828fe1be26d9ae..790ceed0575e41c324d7560ef1529d721444a0ba 100644 (file)
@@ -39,3 +39,8 @@ udf-fix-memory-leak-while-allocating-blocks-during-write.patch
 udf-don-t-increment-lenextents-while-writing-to-a-hole.patch
 thp-memcg-split-hugepage-for-memcg-oom-on-cow.patch
 x86-amd-disable-way-access-filter-on-piledriver-cpus.patch
+acpi-do-not-use-lid-and-sleep-button-for-s5-wakeup.patch
+rtnetlink-compute-and-store-minimum-ifinfo-dump-size.patch
+rtnetlink-fix-problem-with-buffer-allocation.patch
+rtnetlink-fix-rtnl_calcit-and-rtnl_dump_ifinfo.patch
+epoll-prevent-missed-events-on-epoll_ctl_mod.patch