aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@samba.org>2012-09-18 19:20:28 -0400
committerSteve French <smfrench@gmail.com>2012-09-24 22:46:27 -0400
commit24985c53d5b04a56ac7c8ae7f74b8cb807e2ed2f (patch)
treee3864d9504852a5c7410cb9bae4cc9e0249cce1e /fs
parent7a5cfb1965854132f2f382eade8c6ce2eeb6f692 (diff)
CIFS: Move r/wsize negotiating to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsglob.h61
-rw-r--r--fs/cifs/connect.c144
-rw-r--r--fs/cifs/smb1ops.c86
3 files changed, 149 insertions, 142 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index abb831019039..e5cb1941e251 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -213,6 +213,10 @@ struct smb_version_operations {
213 bool (*need_neg)(struct TCP_Server_Info *); 213 bool (*need_neg)(struct TCP_Server_Info *);
214 /* negotiate to the server */ 214 /* negotiate to the server */
215 int (*negotiate)(const unsigned int, struct cifs_ses *); 215 int (*negotiate)(const unsigned int, struct cifs_ses *);
216 /* set negotiated write size */
217 unsigned int (*negotiate_wsize)(struct cifs_tcon *, struct smb_vol *);
218 /* set negotiated read size */
219 unsigned int (*negotiate_rsize)(struct cifs_tcon *, struct smb_vol *);
216 /* setup smb sessionn */ 220 /* setup smb sessionn */
217 int (*sess_setup)(const unsigned int, struct cifs_ses *, 221 int (*sess_setup)(const unsigned int, struct cifs_ses *,
218 const struct nls_table *); 222 const struct nls_table *);
@@ -516,6 +520,63 @@ get_next_mid(struct TCP_Server_Info *server)
516} 520}
517 521
518/* 522/*
523 * When the server supports very large reads and writes via POSIX extensions,
524 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
525 * including the RFC1001 length.
526 *
527 * Note that this might make for "interesting" allocation problems during
528 * writeback however as we have to allocate an array of pointers for the
529 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
530 *
531 * For reads, there is a similar problem as we need to allocate an array
532 * of kvecs to handle the receive, though that should only need to be done
533 * once.
534 */
535#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
536#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
537
538/*
539 * When the server doesn't allow large posix writes, only allow a rsize/wsize
540 * of 2^17-1 minus the size of the call header. That allows for a read or
541 * write up to the maximum size described by RFC1002.
542 */
543#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
544#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
545
546/*
547 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
548 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
549 * a single wsize request with a single call.
550 */
551#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
552
553/*
554 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
555 * those values when posix extensions aren't in force. In actuality here, we
556 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
557 * to be ok with the extra byte even though Windows doesn't send writes that
558 * are that large.
559 *
560 * Citation:
561 *
562 * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
563 */
564#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
565#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
566
567/*
568 * On hosts with high memory, we can't currently support wsize/rsize that are
569 * larger than we can kmap at once. Cap the rsize/wsize at
570 * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
571 * larger than that anyway.
572 */
573#ifdef CONFIG_HIGHMEM
574#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE)
575#else /* CONFIG_HIGHMEM */
576#define CIFS_KMAP_SIZE_LIMIT (1<<24)
577#endif /* CONFIG_HIGHMEM */
578
579/*
519 * Macros to allow the TCP_Server_Info->net field and related code to drop out 580 * Macros to allow the TCP_Server_Info->net field and related code to drop out
520 * when CONFIG_NET_NS isn't set. 581 * when CONFIG_NET_NS isn't set.
521 */ 582 */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6df6fa14cba8..c31b30b572e0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3261,146 +3261,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3261 "mount option supported"); 3261 "mount option supported");
3262} 3262}
3263 3263
3264/*
3265 * When the server supports very large reads and writes via POSIX extensions,
3266 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3267 * including the RFC1001 length.
3268 *
3269 * Note that this might make for "interesting" allocation problems during
3270 * writeback however as we have to allocate an array of pointers for the
3271 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
3272 *
3273 * For reads, there is a similar problem as we need to allocate an array
3274 * of kvecs to handle the receive, though that should only need to be done
3275 * once.
3276 */
3277#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
3278#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
3279
3280/*
3281 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3282 * of 2^17-1 minus the size of the call header. That allows for a read or
3283 * write up to the maximum size described by RFC1002.
3284 */
3285#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
3286#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
3287
3288/*
3289 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3290 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3291 * a single wsize request with a single call.
3292 */
3293#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3294
3295/*
3296 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3297 * those values when posix extensions aren't in force. In actuality here, we
3298 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3299 * to be ok with the extra byte even though Windows doesn't send writes that
3300 * are that large.
3301 *
3302 * Citation:
3303 *
3304 * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
3305 */
3306#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
3307#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
3308
3309/*
3310 * On hosts with high memory, we can't currently support wsize/rsize that are
3311 * larger than we can kmap at once. Cap the rsize/wsize at
3312 * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
3313 * larger than that anyway.
3314 */
3315#ifdef CONFIG_HIGHMEM
3316#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE)
3317#else /* CONFIG_HIGHMEM */
3318#define CIFS_KMAP_SIZE_LIMIT (1<<24)
3319#endif /* CONFIG_HIGHMEM */
3320
3321static unsigned int
3322cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3323{
3324 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3325 struct TCP_Server_Info *server = tcon->ses->server;
3326 unsigned int wsize;
3327
3328 /* start with specified wsize, or default */
3329 if (pvolume_info->wsize)
3330 wsize = pvolume_info->wsize;
3331 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3332 wsize = CIFS_DEFAULT_IOSIZE;
3333 else
3334 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
3335
3336 /* can server support 24-bit write sizes? (via UNIX extensions) */
3337 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3338 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
3339
3340 /*
3341 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3342 * Limit it to max buffer offered by the server, minus the size of the
3343 * WRITEX header, not including the 4 byte RFC1001 length.
3344 */
3345 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3346 (!(server->capabilities & CAP_UNIX) &&
3347 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3348 wsize = min_t(unsigned int, wsize,
3349 server->maxBuf - sizeof(WRITE_REQ) + 4);
3350
3351 /* limit to the amount that we can kmap at once */
3352 wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
3353
3354 /* hard limit of CIFS_MAX_WSIZE */
3355 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3356
3357 return wsize;
3358}
3359
3360static unsigned int
3361cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3362{
3363 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3364 struct TCP_Server_Info *server = tcon->ses->server;
3365 unsigned int rsize, defsize;
3366
3367 /*
3368 * Set default value...
3369 *
3370 * HACK alert! Ancient servers have very small buffers. Even though
3371 * MS-CIFS indicates that servers are only limited by the client's
3372 * bufsize for reads, testing against win98se shows that it throws
3373 * INVALID_PARAMETER errors if you try to request too large a read.
3374 * OS/2 just sends back short reads.
3375 *
3376 * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
3377 * it can't handle a read request larger than its MaxBufferSize either.
3378 */
3379 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3380 defsize = CIFS_DEFAULT_IOSIZE;
3381 else if (server->capabilities & CAP_LARGE_READ_X)
3382 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3383 else
3384 defsize = server->maxBuf - sizeof(READ_RSP);
3385
3386 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3387
3388 /*
3389 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3390 * the client's MaxBufferSize.
3391 */
3392 if (!(server->capabilities & CAP_LARGE_READ_X))
3393 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3394
3395 /* limit to the amount that we can kmap at once */
3396 rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
3397
3398 /* hard limit of CIFS_MAX_RSIZE */
3399 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3400
3401 return rsize;
3402}
3403
3404static void 3264static void
3405cleanup_volume_info_contents(struct smb_vol *volume_info) 3265cleanup_volume_info_contents(struct smb_vol *volume_info)
3406{ 3266{
@@ -3651,8 +3511,8 @@ try_mount_again:
3651 if (!tcon->ipc && server->ops->qfs_tcon) 3511 if (!tcon->ipc && server->ops->qfs_tcon)
3652 server->ops->qfs_tcon(xid, tcon); 3512 server->ops->qfs_tcon(xid, tcon);
3653 3513
3654 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info); 3514 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3655 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info); 3515 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
3656 3516
3657 /* tune readahead according to rsize */ 3517 /* tune readahead according to rsize */
3658 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE; 3518 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
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,