Commit 1190f6a0 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

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: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 446b23a7
...@@ -2750,21 +2750,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -2750,21 +2750,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
/* /*
* When the server supports very large writes via POSIX extensions, we can * 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 * Note that this might make for "interesting" allocation problems during
* writeback however (as we have to allocate an array of pointers for the * 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. * 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 * When the server doesn't allow large posix writes, only allow a wsize of
* 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size * 128k minus the size of the WRITE_AND_X header. That allows for a write up
* described in RFC1001. This allows space for the header without going over * to the maximum size described by RFC1002.
* that by default.
*/ */
#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 * 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,11 +2783,18 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
/* can server support 24-bit write sizes? (via UNIX extensions) */ /* can server support 24-bit write sizes? (via UNIX extensions) */
if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) 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)) * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
wsize = min_t(unsigned int, wsize, USHRT_MAX); * 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->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
wsize = min_t(unsigned int, wsize,
server->maxBuf - sizeof(WRITE_REQ) + 4);
/* hard limit of CIFS_MAX_WSIZE */ /* hard limit of CIFS_MAX_WSIZE */
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment