diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-05-19 16:22:58 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-05-25 16:12:16 -0400 |
commit | f7910cbd9fa319ee4501074f1f3b5ce23c4b1518 (patch) | |
tree | 940a9f9836771d2b8820dff93010457ed3e0444c /fs/cifs/connect.c | |
parent | c3d17b63e5eafcaf2678c11de801c189468631c8 (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/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 69 |
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 | |||
2753 | static unsigned int | ||
2754 | cifs_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 | |||
2745 | static int | 2775 | static int |
2746 | is_path_accessible(int xid, struct cifsTconInfo *tcon, | 2776 | is_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 | |||
3024 | remote_path_check: | 3053 | remote_path_check: |
3025 | #ifdef CONFIG_CIFS_DFS_UPCALL | 3054 | #ifdef CONFIG_CIFS_DFS_UPCALL |
3026 | /* | 3055 | /* |