CIFS: Move r/wsize negotiating to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:

committed by
Steve French

parent
7a5cfb1965
commit
24985c53d5
@@ -17,6 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/pagemap.h>
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
@@ -410,6 +411,89 @@ cifs_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
|
||||
{
|
||||
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
unsigned int wsize;
|
||||
|
||||
/* start with specified wsize, or default */
|
||||
if (volume_info->wsize)
|
||||
wsize = volume_info->wsize;
|
||||
else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
|
||||
wsize = CIFS_DEFAULT_IOSIZE;
|
||||
else
|
||||
wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
|
||||
|
||||
/* 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_RFC1002_WSIZE);
|
||||
|
||||
/*
|
||||
* 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->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
|
||||
wsize = min_t(unsigned int, wsize,
|
||||
server->maxBuf - sizeof(WRITE_REQ) + 4);
|
||||
|
||||
/* limit to the amount that we can kmap at once */
|
||||
wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
|
||||
|
||||
/* hard limit of CIFS_MAX_WSIZE */
|
||||
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
|
||||
|
||||
return wsize;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
|
||||
{
|
||||
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
unsigned int rsize, defsize;
|
||||
|
||||
/*
|
||||
* Set default value...
|
||||
*
|
||||
* HACK alert! Ancient servers have very small buffers. Even though
|
||||
* MS-CIFS indicates that servers are only limited by the client's
|
||||
* bufsize for reads, testing against win98se shows that it throws
|
||||
* INVALID_PARAMETER errors if you try to request too large a read.
|
||||
* OS/2 just sends back short reads.
|
||||
*
|
||||
* If the server doesn't advertise CAP_LARGE_READ_X, then assume that
|
||||
* it can't handle a read request larger than its MaxBufferSize either.
|
||||
*/
|
||||
if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
|
||||
defsize = CIFS_DEFAULT_IOSIZE;
|
||||
else if (server->capabilities & CAP_LARGE_READ_X)
|
||||
defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
|
||||
else
|
||||
defsize = server->maxBuf - sizeof(READ_RSP);
|
||||
|
||||
rsize = volume_info->rsize ? volume_info->rsize : defsize;
|
||||
|
||||
/*
|
||||
* no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
|
||||
* the client's MaxBufferSize.
|
||||
*/
|
||||
if (!(server->capabilities & CAP_LARGE_READ_X))
|
||||
rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
|
||||
|
||||
/* limit to the amount that we can kmap at once */
|
||||
rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
|
||||
|
||||
/* hard limit of CIFS_MAX_RSIZE */
|
||||
rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
|
||||
|
||||
return rsize;
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
|
||||
{
|
||||
@@ -678,6 +762,8 @@ struct smb_version_operations smb1_operations = {
|
||||
.check_trans2 = cifs_check_trans2,
|
||||
.need_neg = cifs_need_neg,
|
||||
.negotiate = cifs_negotiate,
|
||||
.negotiate_wsize = cifs_negotiate_wsize,
|
||||
.negotiate_rsize = cifs_negotiate_rsize,
|
||||
.sess_setup = CIFS_SessSetup,
|
||||
.logoff = CIFSSMBLogoff,
|
||||
.tree_connect = CIFSTCon,
|
||||
|
Reference in New Issue
Block a user