]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
2.6.39 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 1 Aug 2011 21:08:19 +0000 (14:08 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 1 Aug 2011 21:08:19 +0000 (14:08 -0700)
queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch [new file with mode: 0644]
queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch [new file with mode: 0644]
queue-2.6.39/series

diff --git a/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch b/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
new file mode 100644 (file)
index 0000000..9d2b5a4
--- /dev/null
@@ -0,0 +1,89 @@
+From 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Wed, 22 Jun 2011 17:33:57 -0400
+Subject: cifs: fix wsize negotiation to respect max buffer size and
+ active signing (try #4)
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 upstream.
+
+Hopefully last version. Base signing check on CAP_UNIX instead of
+tcon->unix_ext, also clean up the comments a bit more.
+
+According to Hongwei Sun's blog posting here:
+
+    http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
+
+CAP_LARGE_WRITEX is ignored when signing is active. Also, the maximum
+size for a write without CAP_LARGE_WRITEX should be the maxBuf that
+the server sent in the NEGOTIATE request.
+
+Fix the wsize negotiation to take this into account. While we're at it,
+alter the other wsize definitions to use sizeof(WRITE_REQ) to allow for
+slightly larger amounts of data to potentially be written per request.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/cifs/connect.c |   33 ++++++++++++++++++++-------------
+ 1 file changed, 20 insertions(+), 13 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -2650,21 +2650,21 @@ static void setup_cifs_sb(struct smb_vol
+ /*
+  * When the server supports very large writes via POSIX extensions, we can
+- * allow up to 2^24 - PAGE_CACHE_SIZE.
++ * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
++ * the RFC1001 length.
+  *
+  * Note that this might make for "interesting" allocation problems during
+- * writeback however (as we have to allocate an array of pointers for the
+- * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
++ * writeback however as we have to allocate an array of pointers for the
++ * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
+  */
+-#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE)
++#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
+ /*
+- * When the server doesn't allow large posix writes, default to a wsize of
+- * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size
+- * described in RFC1001. This allows space for the header without going over
+- * that by default.
++ * When the server doesn't allow large posix writes, only allow a wsize of
++ * 128k minus the size of the WRITE_AND_X header. That allows for a write up
++ * to the maximum size described by RFC1002.
+  */
+-#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE)
++#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
+ /*
+  * The default wsize is 1M. find_get_pages seems to return a maximum of 256
+@@ -2683,11 +2683,18 @@ cifs_negotiate_wsize(struct cifsTconInfo
+       /* can server support 24-bit write sizes? (via UNIX extensions) */
+       if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+-              wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE);
++              wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
+-      /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */
+-      if (!(server->capabilities & CAP_LARGE_WRITE_X))
+-              wsize = min_t(unsigned int, wsize, USHRT_MAX);
++      /*
++       * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
++       * Limit it to max buffer offered by the server, minus the size of the
++       * WRITEX header, not including the 4 byte RFC1001 length.
++       */
++      if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
++          (!(server->capabilities & CAP_UNIX) &&
++           (server->secMode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
++              wsize = min_t(unsigned int, wsize,
++                              server->maxBuf - sizeof(WRITE_REQ) + 4);
+       /* hard limit of CIFS_MAX_WSIZE */
+       wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
diff --git a/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch b/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch
new file mode 100644 (file)
index 0000000..b6f4e03
--- /dev/null
@@ -0,0 +1,74 @@
+From jlayton@redhat.com  Mon Aug  1 14:03:24 2011
+From: Jeff Layton <jlayton@redhat.com>
+Date: Mon, 1 Aug 2011 15:14:16 -0400
+Subject: cifs: lower default and max wsize to what 2.6.39 can handle
+To: Greg KH <gregkh@suse.de>
+Cc: stable@kernel.org, stable-commits@vger.kernel.org
+Message-ID: <20110801151416.1743b18c@tlielax.poochiereds.net>
+
+From: Jeff Layton <jlayton@redhat.com>
+
+This patch is intended for 2.6.39-stable kernels only and is needed to
+fix a regression introduced in 2.6.39. Prior to 2.6.39, when signing was
+enabled on a socket the client only sent single-page writes. This
+changed with commit ca83ce3, which made signed and unsigned connections
+use the same codepaths for write calls.
+
+This caused a regression when working with windows servers. Windows
+machines will reject writes larger than the MaxBufferSize when signing
+is active, but do not clear the CAP_LARGE_WRITE_X flag in the protocol
+negotiation. The upshot is that when signing is active, windows servers
+often reject large writes from the client in 2.6.39.
+
+Because 3.0 adds support for larger wsize values, simply cherry picking
+the upstream patches that fix the wsize negotiation isn't sufficient to
+fix this issue. We also need to alter the maximum and default values to
+something suitable for 2.6.39.
+
+This patch also accounts for the change in field name from sec_mode to
+secMode that went into 3.0.
+
+Cc: <stable@kernel.org> # .39.x: f7910cb: cifs: clean up wsize negotiation and allow for larger wsize
+Cc: <stable@kernel.org> # .39.x: 1190f6a: cifs: fix wsize negotiation to respect max buffer size and active signing (try #4)
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ fs/cifs/connect.c |   20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -2648,16 +2648,8 @@ static void setup_cifs_sb(struct smb_vol
+                          "mount option supported");
+ }
+-/*
+- * When the server supports very large writes via POSIX extensions, we can
+- * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
+- * the RFC1001 length.
+- *
+- * Note that this might make for "interesting" allocation problems during
+- * writeback however as we have to allocate an array of pointers for the
+- * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
+- */
+-#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
++/* Prior to 3.0, cifs couldn't handle writes larger than this */
++#define CIFS_MAX_WSIZE (PAGEVEC_SIZE * PAGE_CACHE_SIZE)
+ /*
+  * When the server doesn't allow large posix writes, only allow a wsize of
+@@ -2666,12 +2658,8 @@ static void setup_cifs_sb(struct smb_vol
+  */
+ #define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
+-/*
+- * The default wsize is 1M. find_get_pages seems to return a maximum of 256
+- * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
+- * a single wsize request with a single call.
+- */
+-#define CIFS_DEFAULT_WSIZE (1024 * 1024)
++/* Make the default the same as the max */
++#define CIFS_DEFAULT_WSIZE CIFS_MAX_WSIZE
+ static unsigned int
+ cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
index c42a42fbbc8b0d42e8176efd32c284af4616c1ff..d20d01777441b522808df8df11454a293d7b4647 100644 (file)
@@ -64,3 +64,5 @@ mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.
 mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch
 revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch
 vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch
+cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
+cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch