aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb1ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb1ops.c')
-rw-r--r--fs/cifs/smb1ops.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index df20dd9e64ca..7e8a2bdd69c8 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -17,6 +17,7 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#include <linux/pagemap.h>
20#include "cifsglob.h" 21#include "cifsglob.h"
21#include "cifsproto.h" 22#include "cifsproto.h"
22#include "cifs_debug.h" 23#include "cifs_debug.h"
@@ -410,6 +411,89 @@ cifs_negotiate(const unsigned int xid, struct cifs_ses *ses)
410 return rc; 411 return rc;
411} 412}
412 413
414static unsigned int
415cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
416{
417 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
418 struct TCP_Server_Info *server = tcon->ses->server;
419 unsigned int wsize;
420
421 /* start with specified wsize, or default */
422 if (volume_info->wsize)
423 wsize = volume_info->wsize;
424 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
425 wsize = CIFS_DEFAULT_IOSIZE;
426 else
427 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
428
429 /* can server support 24-bit write sizes? (via UNIX extensions) */
430 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
431 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
432
433 /*
434 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
435 * Limit it to max buffer offered by the server, minus the size of the
436 * WRITEX header, not including the 4 byte RFC1001 length.
437 */
438 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
439 (!(server->capabilities & CAP_UNIX) &&
440 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
441 wsize = min_t(unsigned int, wsize,
442 server->maxBuf - sizeof(WRITE_REQ) + 4);
443
444 /* limit to the amount that we can kmap at once */
445 wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
446
447 /* hard limit of CIFS_MAX_WSIZE */
448 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
449
450 return wsize;
451}
452
453static unsigned int
454cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
455{
456 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
457 struct TCP_Server_Info *server = tcon->ses->server;
458 unsigned int rsize, defsize;
459
460 /*
461 * Set default value...
462 *
463 * HACK alert! Ancient servers have very small buffers. Even though
464 * MS-CIFS indicates that servers are only limited by the client's
465 * bufsize for reads, testing against win98se shows that it throws
466 * INVALID_PARAMETER errors if you try to request too large a read.
467 * OS/2 just sends back short reads.
468 *
469 * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
470 * it can't handle a read request larger than its MaxBufferSize either.
471 */
472 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
473 defsize = CIFS_DEFAULT_IOSIZE;
474 else if (server->capabilities & CAP_LARGE_READ_X)
475 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
476 else
477 defsize = server->maxBuf - sizeof(READ_RSP);
478
479 rsize = volume_info->rsize ? volume_info->rsize : defsize;
480
481 /*
482 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
483 * the client's MaxBufferSize.
484 */
485 if (!(server->capabilities & CAP_LARGE_READ_X))
486 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
487
488 /* limit to the amount that we can kmap at once */
489 rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
490
491 /* hard limit of CIFS_MAX_RSIZE */
492 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
493
494 return rsize;
495}
496
413static void 497static void
414cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) 498cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
415{ 499{
@@ -678,6 +762,8 @@ struct smb_version_operations smb1_operations = {
678 .check_trans2 = cifs_check_trans2, 762 .check_trans2 = cifs_check_trans2,
679 .need_neg = cifs_need_neg, 763 .need_neg = cifs_need_neg,
680 .negotiate = cifs_negotiate, 764 .negotiate = cifs_negotiate,
765 .negotiate_wsize = cifs_negotiate_wsize,
766 .negotiate_rsize = cifs_negotiate_rsize,
681 .sess_setup = CIFS_SessSetup, 767 .sess_setup = CIFS_SessSetup,
682 .logoff = CIFSSMBLogoff, 768 .logoff = CIFSSMBLogoff,
683 .tree_connect = CIFSTCon, 769 .tree_connect = CIFSTCon,