diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-01 14:08:19 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-01 14:08:19 -0700 |
commit | 85d4c989728d0498552d000cb4cac2d1e848e58b (patch) | |
tree | 1e22f4b13f6ea14e868e6e525fd6ba9007a47867 | |
parent | b3d798eae426b73c3105edfec1a4686ce2e82938 (diff) | |
download | stable-queue-85d4c989728d0498552d000cb4cac2d1e848e58b.tar.gz |
2.6.39 patches
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 |