summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-08-01 14:08:19 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-01 14:08:19 -0700
commit85d4c989728d0498552d000cb4cac2d1e848e58b (patch)
tree1e22f4b13f6ea14e868e6e525fd6ba9007a47867
parentb3d798eae426b73c3105edfec1a4686ce2e82938 (diff)
downloadstable-queue-85d4c989728d0498552d000cb4cac2d1e848e58b.tar.gz
2.6.39 patches
-rw-r--r--queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch89
-rw-r--r--queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch74
-rw-r--r--queue-2.6.39/series2
3 files changed, 165 insertions, 0 deletions
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
index 0000000000..9d2b5a4b3d
--- /dev/null
+++ b/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
@@ -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
index 0000000000..b6f4e030f7
--- /dev/null
+++ b/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch
@@ -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)
diff --git a/queue-2.6.39/series b/queue-2.6.39/series
index c42a42fbbc..d20d017774 100644
--- a/queue-2.6.39/series
+++ b/queue-2.6.39/series
@@ -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