aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-05-19 16:22:58 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-25 16:12:16 -0400
commitf7910cbd9fa319ee4501074f1f3b5ce23c4b1518 (patch)
tree940a9f9836771d2b8820dff93010457ed3e0444c /fs/cifs
parentc3d17b63e5eafcaf2678c11de801c189468631c8 (diff)
cifs: clean up wsize negotiation and allow for larger wsize
Now that we can handle larger wsizes in writepages, fix up the negotiation of the wsize to allow for that. find_get_pages only seems to give out a max of 256 pages at a time, so that gives us a reasonable default of 1M for the wsize. If the server however does not support large writes via POSIX extensions, then we cap the wsize to (128k - PAGE_CACHE_SIZE). That gives us a size that goes up to the max frame size specified in RFC1001. Finally, if CAP_LARGE_WRITE_AND_X isn't set, then further cap it to the largest size allowed by the protocol (USHRT_MAX). Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-and-Tested-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/connect.c69
1 files changed, 49 insertions, 20 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6070ba69647b..2e7a79cd2b93 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2647,23 +2647,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2647 else /* default */ 2647 else /* default */
2648 cifs_sb->rsize = CIFSMaxBufSize; 2648 cifs_sb->rsize = CIFSMaxBufSize;
2649 2649
2650 if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2651 cERROR(1, "wsize %d too large, using 4096 instead",
2652 pvolume_info->wsize);
2653 cifs_sb->wsize = 4096;
2654 } else if (pvolume_info->wsize)
2655 cifs_sb->wsize = pvolume_info->wsize;
2656 else
2657 cifs_sb->wsize = min_t(const int,
2658 PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2659 127*1024);
2660 /* old default of CIFSMaxBufSize was too small now
2661 that SMB Write2 can send multiple pages in kvec.
2662 RFC1001 does not describe what happens when frame
2663 bigger than 128K is sent so use that as max in
2664 conjunction with 52K kvec constraint on arch with 4K
2665 page size */
2666
2667 if (cifs_sb->rsize < 2048) { 2650 if (cifs_sb->rsize < 2048) {
2668 cifs_sb->rsize = 2048; 2651 cifs_sb->rsize = 2048;
2669 /* Windows ME may prefer this */ 2652 /* Windows ME may prefer this */
@@ -2742,6 +2725,53 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2742 "mount option supported"); 2725 "mount option supported");
2743} 2726}
2744 2727
2728/*
2729 * When the server supports very large writes via POSIX extensions, we can
2730 * allow up to 2^24 - PAGE_CACHE_SIZE.
2731 *
2732 * Note that this might make for "interesting" allocation problems during
2733 * writeback however (as we have to allocate an array of pointers for the
2734 * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
2735 */
2736#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE)
2737
2738/*
2739 * When the server doesn't allow large posix writes, default to a wsize of
2740 * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size
2741 * described in RFC1001. This allows space for the header without going over
2742 * that by default.
2743 */
2744#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE)
2745
2746/*
2747 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
2748 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
2749 * a single wsize request with a single call.
2750 */
2751#define CIFS_DEFAULT_WSIZE (1024 * 1024)
2752
2753static unsigned int
2754cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
2755{
2756 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2757 struct TCP_Server_Info *server = tcon->ses->server;
2758 unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
2759 CIFS_DEFAULT_WSIZE;
2760
2761 /* can server support 24-bit write sizes? (via UNIX extensions) */
2762 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
2763 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE);
2764
2765 /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */
2766 if (!(server->capabilities & CAP_LARGE_WRITE_X))
2767 wsize = min_t(unsigned int, wsize, USHRT_MAX);
2768
2769 /* hard limit of CIFS_MAX_WSIZE */
2770 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
2771
2772 return wsize;
2773}
2774
2745static int 2775static int
2746is_path_accessible(int xid, struct cifsTconInfo *tcon, 2776is_path_accessible(int xid, struct cifsTconInfo *tcon,
2747 struct cifs_sb_info *cifs_sb, const char *full_path) 2777 struct cifs_sb_info *cifs_sb, const char *full_path)
@@ -3014,13 +3044,12 @@ try_mount_again:
3014 cifs_sb->rsize = 1024 * 127; 3044 cifs_sb->rsize = 1024 * 127;
3015 cFYI(DBG2, "no very large read support, rsize now 127K"); 3045 cFYI(DBG2, "no very large read support, rsize now 127K");
3016 } 3046 }
3017 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
3018 cifs_sb->wsize = min(cifs_sb->wsize,
3019 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
3020 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) 3047 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
3021 cifs_sb->rsize = min(cifs_sb->rsize, 3048 cifs_sb->rsize = min(cifs_sb->rsize,
3022 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 3049 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
3023 3050
3051 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
3052
3024remote_path_check: 3053remote_path_check:
3025#ifdef CONFIG_CIFS_DFS_UPCALL 3054#ifdef CONFIG_CIFS_DFS_UPCALL
3026 /* 3055 /*