aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-06-22 17:33:57 -0400
committerSteve French <sfrench@us.ibm.com>2011-06-23 13:54:39 -0400
commit1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 (patch)
tree7a754b292e2cac6f5fe808d3e66c90c9689593e9 /fs/cifs/connect.c
parent446b23a75804d7ffa4cca2d4d8f0afb822108c7e (diff)
cifs: fix wsize negotiation to respect max buffer size and active signing (try #4)
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>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 19fdbda7aa95..c761935eab8c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2750,21 +2750,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2750 2750
2751/* 2751/*
2752 * When the server supports very large writes via POSIX extensions, we can 2752 * When the server supports very large writes via POSIX extensions, we can
2753 * allow up to 2^24 - PAGE_CACHE_SIZE. 2753 * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
2754 * the RFC1001 length.
2754 * 2755 *
2755 * Note that this might make for "interesting" allocation problems during 2756 * Note that this might make for "interesting" allocation problems during
2756 * writeback however (as we have to allocate an array of pointers for the 2757 * writeback however as we have to allocate an array of pointers for the
2757 * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. 2758 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
2758 */ 2759 */
2759#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE) 2760#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
2760 2761
2761/* 2762/*
2762 * When the server doesn't allow large posix writes, default to a wsize of 2763 * When the server doesn't allow large posix writes, only allow a wsize of
2763 * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size 2764 * 128k minus the size of the WRITE_AND_X header. That allows for a write up
2764 * described in RFC1001. This allows space for the header without going over 2765 * to the maximum size described by RFC1002.
2765 * that by default.
2766 */ 2766 */
2767#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE) 2767#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
2768 2768
2769/* 2769/*
2770 * The default wsize is 1M. find_get_pages seems to return a maximum of 256 2770 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
@@ -2783,11 +2783,18 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
2783 2783
2784 /* can server support 24-bit write sizes? (via UNIX extensions) */ 2784 /* can server support 24-bit write sizes? (via UNIX extensions) */
2785 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) 2785 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
2786 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE); 2786 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
2787 2787
2788 /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */ 2788 /*
2789 if (!(server->capabilities & CAP_LARGE_WRITE_X)) 2789 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
2790 wsize = min_t(unsigned int, wsize, USHRT_MAX); 2790 * Limit it to max buffer offered by the server, minus the size of the
2791 * WRITEX header, not including the 4 byte RFC1001 length.
2792 */
2793 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
2794 (!(server->capabilities & CAP_UNIX) &&
2795 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
2796 wsize = min_t(unsigned int, wsize,
2797 server->maxBuf - sizeof(WRITE_REQ) + 4);
2791 2798
2792 /* hard limit of CIFS_MAX_WSIZE */ 2799 /* hard limit of CIFS_MAX_WSIZE */
2793 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); 2800 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);