]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Sep 2013 00:00:04 +0000 (17:00 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Sep 2013 00:00:04 +0000 (17:00 -0700)
added patches:
cw1200-don-t-perform-spi-transfers-in-interrupt-context.patch
cw1200-prevent-a-lock-related-hang-in-the-cw1200_spi-driver.patch
rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch
rpc-fix-huge-kmalloc-s-in-gss-proxy.patch
rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch

queue-3.11/cw1200-don-t-perform-spi-transfers-in-interrupt-context.patch [new file with mode: 0644]
queue-3.11/cw1200-prevent-a-lock-related-hang-in-the-cw1200_spi-driver.patch [new file with mode: 0644]
queue-3.11/rpc-clean-up-decoding-of-gssproxy-linux-creds.patch [new file with mode: 0644]
queue-3.11/rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch [new file with mode: 0644]
queue-3.11/rpc-fix-huge-kmalloc-s-in-gss-proxy.patch [new file with mode: 0644]
queue-3.11/rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch [new file with mode: 0644]
queue-3.11/series

diff --git a/queue-3.11/cw1200-don-t-perform-spi-transfers-in-interrupt-context.patch b/queue-3.11/cw1200-don-t-perform-spi-transfers-in-interrupt-context.patch
new file mode 100644 (file)
index 0000000..f154d03
--- /dev/null
@@ -0,0 +1,136 @@
+From aec8e88c947b7017e2b4bbcb68a4bfc4a1f8ad35 Mon Sep 17 00:00:00 2001
+From: Solomon Peachy <pizza@shaftnet.org>
+Date: Tue, 27 Aug 2013 20:29:46 -0400
+Subject: cw1200: Don't perform SPI transfers in interrupt context
+
+From: Solomon Peachy <pizza@shaftnet.org>
+
+commit aec8e88c947b7017e2b4bbcb68a4bfc4a1f8ad35 upstream.
+
+When we get an interrupt from the hardware, the first thing the driver does
+is tell the device to mask off the interrupt line.  Unfortunately this
+involves a SPI transaction in interrupt context.  Some (most?) SPI
+controllers perform the transfer asynchronously and try to sleep.
+This is bad, and triggers a BUG().
+
+So, work around this by using adding a hwbus hook for the cw1200 driver
+core to call.  The cw1200_spi driver translates this into
+irq_disable()/irq_enable() calls instead, which can safely be called in
+interrupt context.
+
+Apparently the platforms I used to develop the cw1200_spi driver used
+synchronous spi_sync() implementations, which is why this didn't surface
+until now.
+
+Many thanks to Dave Sizeburns for the inital bug report and his services
+as a tester.
+
+Signed-off-by: Solomon Peachy <pizza@shaftnet.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/cw1200/cw1200_spi.c |   19 ++++++++++++++++---
+ drivers/net/wireless/cw1200/fwio.c       |    2 +-
+ drivers/net/wireless/cw1200/hwbus.h      |    1 +
+ drivers/net/wireless/cw1200/hwio.c       |   15 +++++++++++++++
+ 4 files changed, 33 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/cw1200/cw1200_spi.c
++++ b/drivers/net/wireless/cw1200/cw1200_spi.c
+@@ -42,6 +42,7 @@ struct hwbus_priv {
+       spinlock_t              lock; /* Serialize all bus operations */
+       wait_queue_head_t       wq;
+       int claimed;
++      int irq_disabled;
+ };
+ #define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
+@@ -237,6 +238,8 @@ static irqreturn_t cw1200_spi_irq_handle
+       struct hwbus_priv *self = dev_id;
+       if (self->core) {
++              disable_irq_nosync(self->func->irq);
++              self->irq_disabled = 1;
+               cw1200_irq_handler(self->core);
+               return IRQ_HANDLED;
+       } else {
+@@ -270,13 +273,22 @@ exit:
+ static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
+ {
+-      int ret = 0;
+-
+       pr_debug("SW IRQ unsubscribe\n");
+       disable_irq_wake(self->func->irq);
+       free_irq(self->func->irq, self);
+-      return ret;
++      return 0;
++}
++
++static int cw1200_spi_irq_enable(struct hwbus_priv *self, int enable)
++{
++      /* Disables are handled by the interrupt handler */
++      if (enable && self->irq_disabled) {
++              enable_irq(self->func->irq);
++              self->irq_disabled = 0;
++      }
++
++      return 0;
+ }
+ static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
+@@ -356,6 +368,7 @@ static struct hwbus_ops cw1200_spi_hwbus
+       .unlock                 = cw1200_spi_unlock,
+       .align_size             = cw1200_spi_align_size,
+       .power_mgmt             = cw1200_spi_pm,
++      .irq_enable             = cw1200_spi_irq_enable,
+ };
+ /* Probe Function to be called by SPI stack when device is discovered */
+--- a/drivers/net/wireless/cw1200/fwio.c
++++ b/drivers/net/wireless/cw1200/fwio.c
+@@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_c
+       /* Enable interrupt signalling */
+       priv->hwbus_ops->lock(priv->hwbus_priv);
+-      ret = __cw1200_irq_enable(priv, 1);
++      ret = __cw1200_irq_enable(priv, 2);
+       priv->hwbus_ops->unlock(priv->hwbus_priv);
+       if (ret < 0)
+               goto unsubscribe;
+--- a/drivers/net/wireless/cw1200/hwbus.h
++++ b/drivers/net/wireless/cw1200/hwbus.h
+@@ -28,6 +28,7 @@ struct hwbus_ops {
+       void (*unlock)(struct hwbus_priv *self);
+       size_t (*align_size)(struct hwbus_priv *self, size_t size);
+       int (*power_mgmt)(struct hwbus_priv *self, bool suspend);
++      int (*irq_enable)(struct hwbus_priv *self, int enable);
+ };
+ #endif /* CW1200_HWBUS_H */
+--- a/drivers/net/wireless/cw1200/hwio.c
++++ b/drivers/net/wireless/cw1200/hwio.c
+@@ -273,6 +273,21 @@ int __cw1200_irq_enable(struct cw1200_co
+       u16 val16;
+       int ret;
++      /* We need to do this hack because the SPI layer can sleep on I/O
++         and the general path involves I/O to the device in interrupt
++         context.
++
++         However, the initial enable call needs to go to the hardware.
++
++         We don't worry about shutdown because we do a full reset which
++         clears the interrupt enabled bits.
++      */
++      if (priv->hwbus_ops->irq_enable) {
++              ret = priv->hwbus_ops->irq_enable(priv->hwbus_priv, enable);
++              if (ret || enable < 2)
++                      return ret;
++      }
++
+       if (HIF_8601_SILICON == priv->hw_type) {
+               ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
+               if (ret < 0) {
diff --git a/queue-3.11/cw1200-prevent-a-lock-related-hang-in-the-cw1200_spi-driver.patch b/queue-3.11/cw1200-prevent-a-lock-related-hang-in-the-cw1200_spi-driver.patch
new file mode 100644 (file)
index 0000000..b9131a5
--- /dev/null
@@ -0,0 +1,77 @@
+From 85ba8f529c57ac6e2fca9be0d9e17920a1afb2e8 Mon Sep 17 00:00:00 2001
+From: Solomon Peachy <pizza@shaftnet.org>
+Date: Tue, 27 Aug 2013 20:29:47 -0400
+Subject: cw1200: Prevent a lock-related hang in the cw1200_spi driver
+
+From: Solomon Peachy <pizza@shaftnet.org>
+
+commit 85ba8f529c57ac6e2fca9be0d9e17920a1afb2e8 upstream.
+
+The cw1200_spi driver tries to mirror the cw1200_sdio driver's lock
+API, which relies on sdio_claim_host/sdio_release_host to serialize
+hardware operations across multiple threads.
+
+Unfortunately the implementation was flawed, as it lacked a way to wake
+up the lock requestor when there was contention, often resulting in a
+hang.
+
+This problem was uncovered while trying to fix the
+spi-transfers-in-interrupt-context BUG() corrected in the previous
+patch.  Many thanks to Dave Sizeburns for his assistance in fixing this.
+
+Signed-off-by: Solomon Peachy <pizza@shaftnet.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/cw1200/cw1200_spi.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/net/wireless/cw1200/cw1200_spi.c
++++ b/drivers/net/wireless/cw1200/cw1200_spi.c
+@@ -40,6 +40,7 @@ struct hwbus_priv {
+       struct cw1200_common    *core;
+       const struct cw1200_platform_data_spi *pdata;
+       spinlock_t              lock; /* Serialize all bus operations */
++      wait_queue_head_t       wq;
+       int claimed;
+ };
+@@ -197,8 +198,11 @@ static void cw1200_spi_lock(struct hwbus
+ {
+       unsigned long flags;
++      DECLARE_WAITQUEUE(wait, current);
++
+       might_sleep();
++      add_wait_queue(&self->wq, &wait);
+       spin_lock_irqsave(&self->lock, flags);
+       while (1) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+@@ -211,6 +215,7 @@ static void cw1200_spi_lock(struct hwbus
+       set_current_state(TASK_RUNNING);
+       self->claimed = 1;
+       spin_unlock_irqrestore(&self->lock, flags);
++      remove_wait_queue(&self->wq, &wait);
+       return;
+ }
+@@ -222,6 +227,8 @@ static void cw1200_spi_unlock(struct hwb
+       spin_lock_irqsave(&self->lock, flags);
+       self->claimed = 0;
+       spin_unlock_irqrestore(&self->lock, flags);
++      wake_up(&self->wq);
++
+       return;
+ }
+@@ -400,6 +407,8 @@ static int cw1200_spi_probe(struct spi_d
+       spi_set_drvdata(func, self);
++      init_waitqueue_head(&self->wq);
++
+       status = cw1200_spi_irq_subscribe(self);
+       status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
diff --git a/queue-3.11/rpc-clean-up-decoding-of-gssproxy-linux-creds.patch b/queue-3.11/rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
new file mode 100644 (file)
index 0000000..ad71c24
--- /dev/null
@@ -0,0 +1,108 @@
+From 778e512bb1d3315c6b55832248cd30c566c081d7 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Wed, 21 Aug 2013 10:32:52 -0400
+Subject: rpc: clean up decoding of gssproxy linux creds
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit 778e512bb1d3315c6b55832248cd30c566c081d7 upstream.
+
+We can use the normal coding infrastructure here.
+
+Two minor behavior changes:
+
+       - we're assuming no wasted space at the end of the linux cred.
+         That seems to match gss-proxy's behavior, and I can't see why
+         it would need to do differently in the future.
+
+       - NGROUPS_MAX check added: note groups_alloc doesn't do this,
+         this is the caller's responsibility.
+
+Tested-by: Simo Sorce <simo@redhat.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_xdr.c |   32 +++++++++++++-------------------
+ 1 file changed, 13 insertions(+), 19 deletions(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+@@ -166,14 +166,14 @@ static int dummy_dec_opt_array(struct xd
+       return 0;
+ }
+-static int get_s32(void **p, void *max, s32 *res)
++static int get_s32(struct xdr_stream *xdr, s32 *res)
+ {
+-      void *base = *p;
+-      void *next = (void *)((char *)base + sizeof(s32));
+-      if (unlikely(next > max || next < base))
++      __be32 *p;
++
++      p = xdr_inline_decode(xdr, 4);
++      if (!p)
+               return -EINVAL;
+-      memcpy(res, base, sizeof(s32));
+-      *p = next;
++      memcpy(res, p, sizeof(s32));
+       return 0;
+ }
+@@ -182,7 +182,6 @@ static int gssx_dec_linux_creds(struct x
+ {
+       u32 length;
+       __be32 *p;
+-      void *q, *end;
+       s32 tmp;
+       int N, i, err;
+@@ -192,33 +191,28 @@ static int gssx_dec_linux_creds(struct x
+       length = be32_to_cpup(p);
+-      /* FIXME: we do not want to use the scratch buffer for this one
+-       * may need to use functions that allows us to access an io vector
+-       * directly */
+-      p = xdr_inline_decode(xdr, length);
+-      if (unlikely(p == NULL))
++      if (length > (3 + NGROUPS_MAX) * sizeof(u32))
+               return -ENOSPC;
+-      q = p;
+-      end = q + length;
+-
+       /* uid */
+-      err = get_s32(&q, end, &tmp);
++      err = get_s32(xdr, &tmp);
+       if (err)
+               return err;
+       creds->cr_uid = make_kuid(&init_user_ns, tmp);
+       /* gid */
+-      err = get_s32(&q, end, &tmp);
++      err = get_s32(xdr, &tmp);
+       if (err)
+               return err;
+       creds->cr_gid = make_kgid(&init_user_ns, tmp);
+       /* number of additional gid's */
+-      err = get_s32(&q, end, &tmp);
++      err = get_s32(xdr, &tmp);
+       if (err)
+               return err;
+       N = tmp;
++      if ((3 + N) * sizeof(u32) != length)
++              return -EINVAL;
+       creds->cr_group_info = groups_alloc(N);
+       if (creds->cr_group_info == NULL)
+               return -ENOMEM;
+@@ -226,7 +220,7 @@ static int gssx_dec_linux_creds(struct x
+       /* gid's */
+       for (i = 0; i < N; i++) {
+               kgid_t kgid;
+-              err = get_s32(&q, end, &tmp);
++              err = get_s32(xdr, &tmp);
+               if (err)
+                       goto out_free_groups;
+               err = -EINVAL;
diff --git a/queue-3.11/rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch b/queue-3.11/rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch
new file mode 100644 (file)
index 0000000..317a97f
--- /dev/null
@@ -0,0 +1,88 @@
+From 6a36978e6931e6601be586eb313375335f2cfaa3 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Fri, 23 Aug 2013 11:17:53 -0400
+Subject: rpc: comment on linux_cred encoding, treat all as unsigned
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit 6a36978e6931e6601be586eb313375335f2cfaa3 upstream.
+
+The encoding of linux creds is a bit confusing.
+
+Also: I think in practice it doesn't really matter whether we treat any
+of these things as signed or unsigned, but unsigned seems more
+straightforward: uid_t/gid_t are unsigned and it simplifies the ngroups
+overflow check.
+
+Tested-by: Simo Sorce <simo@redhat.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_xdr.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+@@ -166,14 +166,15 @@ static int dummy_dec_opt_array(struct xd
+       return 0;
+ }
+-static int get_s32(struct xdr_stream *xdr, s32 *res)
++static int get_host_u32(struct xdr_stream *xdr, u32 *res)
+ {
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+       if (!p)
+               return -EINVAL;
+-      memcpy(res, p, sizeof(s32));
++      /* Contents of linux creds are all host-endian: */
++      memcpy(res, p, sizeof(u32));
+       return 0;
+ }
+@@ -182,8 +183,9 @@ static int gssx_dec_linux_creds(struct x
+ {
+       u32 length;
+       __be32 *p;
+-      s32 tmp;
+-      int N, i, err;
++      u32 tmp;
++      u32 N;
++      int i, err;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+@@ -195,19 +197,19 @@ static int gssx_dec_linux_creds(struct x
+               return -ENOSPC;
+       /* uid */
+-      err = get_s32(xdr, &tmp);
++      err = get_host_u32(xdr, &tmp);
+       if (err)
+               return err;
+       creds->cr_uid = make_kuid(&init_user_ns, tmp);
+       /* gid */
+-      err = get_s32(xdr, &tmp);
++      err = get_host_u32(xdr, &tmp);
+       if (err)
+               return err;
+       creds->cr_gid = make_kgid(&init_user_ns, tmp);
+       /* number of additional gid's */
+-      err = get_s32(xdr, &tmp);
++      err = get_host_u32(xdr, &tmp);
+       if (err)
+               return err;
+       N = tmp;
+@@ -220,7 +222,7 @@ static int gssx_dec_linux_creds(struct x
+       /* gid's */
+       for (i = 0; i < N; i++) {
+               kgid_t kgid;
+-              err = get_s32(xdr, &tmp);
++              err = get_host_u32(xdr, &tmp);
+               if (err)
+                       goto out_free_groups;
+               err = -EINVAL;
diff --git a/queue-3.11/rpc-fix-huge-kmalloc-s-in-gss-proxy.patch b/queue-3.11/rpc-fix-huge-kmalloc-s-in-gss-proxy.patch
new file mode 100644 (file)
index 0000000..7b67ee0
--- /dev/null
@@ -0,0 +1,107 @@
+From 9dfd87da1aeb0fd364167ad199f40fe96a6a87be Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Tue, 20 Aug 2013 18:13:27 -0400
+Subject: rpc: fix huge kmalloc's in gss-proxy
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit 9dfd87da1aeb0fd364167ad199f40fe96a6a87be upstream.
+
+The reply to a gssproxy can include up to NGROUPS_MAX gid's, which will
+take up more than a page.  We therefore need to allocate an array of
+pages to hold the reply instead of trying to allocate a single huge
+buffer.
+
+Tested-by: Simo Sorce <simo@redhat.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_upcall.c |   30 ++++++++++++++++++++++++++++++
+ net/sunrpc/auth_gss/gss_rpc_xdr.c    |    3 +++
+ net/sunrpc/auth_gss/gss_rpc_xdr.h    |    5 ++++-
+ 3 files changed, 37 insertions(+), 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -213,6 +213,30 @@ static int gssp_call(struct net *net, st
+       return status;
+ }
++static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
++{
++      int i;
++
++      for (i = 0; i < arg->npages && arg->pages[i]; i++)
++              __free_page(arg->pages[i]);
++}
++
++static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
++{
++      int i;
++
++      arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
++      arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
++
++      for (i=0; i < arg->npages; i++) {
++              arg->pages[i] = alloc_page(GFP_KERNEL);
++              if (arg->pages[i] == NULL) {
++                      gssp_free_receive_pages(arg);
++                      return -ENOMEM;
++              }
++      }
++      return 0;
++}
+ /*
+  * Public functions
+@@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struc
+               arg.context_handle = &ctxh;
+       res.output_token->len = GSSX_max_output_token_sz;
++      ret = gssp_alloc_receive_pages(&arg);
++      if (ret)
++              return ret;
++
+       /* use nfs/ for targ_name ? */
+       ret = gssp_call(net, &msg);
++      gssp_free_receive_pages(&arg);
++
+       /* we need to fetch all data even in case of error so
+        * that we can free special strctures is they have been allocated */
+       data->major_status = res.status.major_status;
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+@@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct
+       /* arg->options */
+       err = dummy_enc_opt_array(xdr, &arg->options);
++      xdr_inline_pages(&req->rq_rcv_buf,
++              PAGE_SIZE/2 /* pretty arbitrary */,
++              arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
+ done:
+       if (err)
+               dprintk("RPC:       gssx_enc_accept_sec_context: %d\n", err);
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.h
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h
+@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
+       struct gssx_cb *input_cb;
+       u32 ret_deleg_cred;
+       struct gssx_option_array options;
++      struct page **pages;
++      unsigned int npages;
+ };
+ struct gssx_res_accept_sec_context {
+@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct r
+                            2 * GSSX_max_princ_sz + \
+                            8 + 8 + 4 + 4 + 4)
+ #define GSSX_max_output_token_sz 1024
+-#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4)
++/* grouplist not included; we allocate separate pages for that: */
++#define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */)
+ #define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
+                                       GSSX_default_ctx_sz + \
+                                       GSSX_max_output_token_sz + \
diff --git a/queue-3.11/rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch b/queue-3.11/rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
new file mode 100644 (file)
index 0000000..03158b3
--- /dev/null
@@ -0,0 +1,50 @@
+From d4a516560fc96a9d486a9939bcb567e3fdce8f49 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Fri, 23 Aug 2013 17:26:28 -0400
+Subject: rpc: let xdr layer allocate gssproxy receieve pages
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit d4a516560fc96a9d486a9939bcb567e3fdce8f49 upstream.
+
+In theory the linux cred in a gssproxy reply can include up to
+NGROUPS_MAX data, 256K of data.  In the common case we expect it to be
+shorter.  So do as the nfsv3 ACL code does and let the xdr code allocate
+the pages as they come in, instead of allocating a lot of pages that
+won't typically be used.
+
+Tested-by: Simo Sorce <simo@redhat.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_upcall.c |   16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -223,18 +223,14 @@ static void gssp_free_receive_pages(stru
+ static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
+ {
+-      int i;
+-
+       arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
+       arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
+-
+-      for (i=0; i < arg->npages; i++) {
+-              arg->pages[i] = alloc_page(GFP_KERNEL);
+-              if (arg->pages[i] == NULL) {
+-                      gssp_free_receive_pages(arg);
+-                      return -ENOMEM;
+-              }
+-      }
++      /*
++       * XXX: actual pages are allocated by xdr layer in
++       * xdr_partial_copy_from_skb.
++       */
++      if (!arg->pages)
++              return -ENOMEM;
+       return 0;
+ }
index b5e6b07813ce839bf1d13fa7f7b7279d5c06c553..4172522fc6028ae007e80e55dcb8769666d03284 100644 (file)
@@ -62,3 +62,9 @@ audit-fix-endless-wait-in-audit_log_start.patch
 mm-fix-aio-performance-regression-for-database-caused-by-thp.patch
 bio-integrity-fix-use-of-bs-bio_integrity_pool-after-free.patch
 cfq-explicitly-use-64bit-divide-operation-for-64bit-arguments.patch
+rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
+rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch
+rpc-fix-huge-kmalloc-s-in-gss-proxy.patch
+rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
+cw1200-prevent-a-lock-related-hang-in-the-cw1200_spi-driver.patch
+cw1200-don-t-perform-spi-transfers-in-interrupt-context.patch