aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-10-19 15:30:26 -0400
committerJeff Layton <jlayton@redhat.com>2011-10-19 15:30:26 -0400
commit5eba8ab3606621f7e175ae9f521d71f3ac534f82 (patch)
tree8fe7387d9ec3b284a8c1d4a5d2fc9e49d2c393b5 /fs/cifs
parent690c5e3163502f229e5b5d455e5212e28c20cd6d (diff)
cifs: allow for larger rsize= options and change defaults
Currently we cap the rsize at a value that fits in CIFSMaxBufSize. That's not needed any longer for readpages. Allow the use of larger values for readpages. cifs_iovec_read and cifs_read however are still limited to the CIFSMaxBufSize. Make sure they don't exceed that. The patch also changes the rsize defaults. The default when unix extensions are enabled is set to 1M for parity with the wsize, and there is a hard cap of ~16M. When unix extensions are not enabled, the default is set to 60k. According to MS-CIFS, Windows servers can only send a max of 60k at a time, so this is more efficient than requesting a larger size. If the user wishes however, the max can be extended up to 128k - the length of the READ_RSP header. Really old servers however require a special hack to ensure that we don't request too large a read. Reviewed-and-Tested-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/connect.c120
-rw-r--r--fs/cifs/file.c14
2 files changed, 84 insertions, 50 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3d518b9e8c18..06dfaacfea5d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2310,16 +2310,16 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2310 (new->mnt_cifs_flags & CIFS_MOUNT_MASK)) 2310 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2311 return 0; 2311 return 0;
2312 2312
2313 if (old->rsize != new->rsize)
2314 return 0;
2315
2316 /* 2313 /*
2317 * We want to share sb only if we don't specify wsize or specified wsize 2314 * We want to share sb only if we don't specify an r/wsize or
2318 * is greater or equal than existing one. 2315 * specified r/wsize is greater than or equal to existing one.
2319 */ 2316 */
2320 if (new->wsize && new->wsize < old->wsize) 2317 if (new->wsize && new->wsize < old->wsize)
2321 return 0; 2318 return 0;
2322 2319
2320 if (new->rsize && new->rsize < old->rsize)
2321 return 0;
2322
2323 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) 2323 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2324 return 0; 2324 return 0;
2325 2325
@@ -2757,14 +2757,6 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
2757 CIFS_MOUNT_POSIX_PATHS; 2757 CIFS_MOUNT_POSIX_PATHS;
2758 } 2758 }
2759 2759
2760 if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) {
2761 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
2762 cifs_sb->rsize = 127 * 1024;
2763 cFYI(DBG2, "larger reads not supported by srv");
2764 }
2765 }
2766
2767
2768 cFYI(1, "Negotiate caps 0x%x", (int)cap); 2760 cFYI(1, "Negotiate caps 0x%x", (int)cap);
2769#ifdef CONFIG_CIFS_DEBUG2 2761#ifdef CONFIG_CIFS_DEBUG2
2770 if (cap & CIFS_UNIX_FCNTL_CAP) 2762 if (cap & CIFS_UNIX_FCNTL_CAP)
@@ -2809,27 +2801,11 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2809 spin_lock_init(&cifs_sb->tlink_tree_lock); 2801 spin_lock_init(&cifs_sb->tlink_tree_lock);
2810 cifs_sb->tlink_tree = RB_ROOT; 2802 cifs_sb->tlink_tree = RB_ROOT;
2811 2803
2812 if (pvolume_info->rsize > CIFSMaxBufSize) {
2813 cERROR(1, "rsize %d too large, using MaxBufSize",
2814 pvolume_info->rsize);
2815 cifs_sb->rsize = CIFSMaxBufSize;
2816 } else if ((pvolume_info->rsize) &&
2817 (pvolume_info->rsize <= CIFSMaxBufSize))
2818 cifs_sb->rsize = pvolume_info->rsize;
2819 else /* default */
2820 cifs_sb->rsize = CIFSMaxBufSize;
2821
2822 if (cifs_sb->rsize < 2048) {
2823 cifs_sb->rsize = 2048;
2824 /* Windows ME may prefer this */
2825 cFYI(1, "readsize set to minimum: 2048");
2826 }
2827
2828 /* 2804 /*
2829 * Temporarily set wsize for matching superblock. If we end up using 2805 * Temporarily set r/wsize for matching superblock. If we end up using
2830 * new sb then cifs_negotiate_wsize will later negotiate it downward 2806 * new sb then client will later negotiate it downward if needed.
2831 * if needed.
2832 */ 2807 */
2808 cifs_sb->rsize = pvolume_info->rsize;
2833 cifs_sb->wsize = pvolume_info->wsize; 2809 cifs_sb->wsize = pvolume_info->wsize;
2834 2810
2835 cifs_sb->mnt_uid = pvolume_info->linux_uid; 2811 cifs_sb->mnt_uid = pvolume_info->linux_uid;
@@ -2904,29 +2880,41 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2904} 2880}
2905 2881
2906/* 2882/*
2907 * When the server supports very large writes via POSIX extensions, we can 2883 * When the server supports very large reads and writes via POSIX extensions,
2908 * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including 2884 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
2909 * the RFC1001 length. 2885 * including the RFC1001 length.
2910 * 2886 *
2911 * Note that this might make for "interesting" allocation problems during 2887 * Note that this might make for "interesting" allocation problems during
2912 * writeback however as we have to allocate an array of pointers for the 2888 * writeback however as we have to allocate an array of pointers for the
2913 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. 2889 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
2890 *
2891 * For reads, there is a similar problem as we need to allocate an array
2892 * of kvecs to handle the receive, though that should only need to be done
2893 * once.
2914 */ 2894 */
2915#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4) 2895#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
2896#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
2916 2897
2917/* 2898/*
2918 * When the server doesn't allow large posix writes, only allow a wsize of 2899 * When the server doesn't allow large posix writes, only allow a rsize/wsize
2919 * 2^17-1 minus the size of the WRITE_AND_X header. That allows for a write up 2900 * of 2^17-1 minus the size of the call header. That allows for a read or
2920 * to the maximum size described by RFC1002. 2901 * write up to the maximum size described by RFC1002.
2921 */ 2902 */
2922#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4) 2903#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
2904#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
2923 2905
2924/* 2906/*
2925 * The default wsize is 1M. find_get_pages seems to return a maximum of 256 2907 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
2926 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill 2908 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
2927 * a single wsize request with a single call. 2909 * a single wsize request with a single call.
2928 */ 2910 */
2929#define CIFS_DEFAULT_WSIZE (1024 * 1024) 2911#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
2912
2913/*
2914 * Windows only supports a max of 60k reads. Default to that when posix
2915 * extensions aren't in force.
2916 */
2917#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
2930 2918
2931static unsigned int 2919static unsigned int
2932cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) 2920cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
@@ -2934,7 +2922,7 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
2934 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); 2922 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2935 struct TCP_Server_Info *server = tcon->ses->server; 2923 struct TCP_Server_Info *server = tcon->ses->server;
2936 unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize : 2924 unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
2937 CIFS_DEFAULT_WSIZE; 2925 CIFS_DEFAULT_IOSIZE;
2938 2926
2939 /* can server support 24-bit write sizes? (via UNIX extensions) */ 2927 /* can server support 24-bit write sizes? (via UNIX extensions) */
2940 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) 2928 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
@@ -2957,6 +2945,50 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
2957 return wsize; 2945 return wsize;
2958} 2946}
2959 2947
2948static unsigned int
2949cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
2950{
2951 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2952 struct TCP_Server_Info *server = tcon->ses->server;
2953 unsigned int rsize, defsize;
2954
2955 /*
2956 * Set default value...
2957 *
2958 * HACK alert! Ancient servers have very small buffers. Even though
2959 * MS-CIFS indicates that servers are only limited by the client's
2960 * bufsize for reads, testing against win98se shows that it throws
2961 * INVALID_PARAMETER errors if you try to request too large a read.
2962 *
2963 * If the server advertises a MaxBufferSize of less than one page,
2964 * assume that it also can't satisfy reads larger than that either.
2965 *
2966 * FIXME: Is there a better heuristic for this?
2967 */
2968 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
2969 defsize = CIFS_DEFAULT_IOSIZE;
2970 else if (server->capabilities & CAP_LARGE_READ_X)
2971 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
2972 else if (server->maxBuf >= PAGE_CACHE_SIZE)
2973 defsize = CIFSMaxBufSize;
2974 else
2975 defsize = server->maxBuf - sizeof(READ_RSP);
2976
2977 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
2978
2979 /*
2980 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
2981 * the client's MaxBufferSize.
2982 */
2983 if (!(server->capabilities & CAP_LARGE_READ_X))
2984 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
2985
2986 /* hard limit of CIFS_MAX_RSIZE */
2987 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
2988
2989 return rsize;
2990}
2991
2960static int 2992static int
2961is_path_accessible(int xid, struct cifs_tcon *tcon, 2993is_path_accessible(int xid, struct cifs_tcon *tcon,
2962 struct cifs_sb_info *cifs_sb, const char *full_path) 2994 struct cifs_sb_info *cifs_sb, const char *full_path)
@@ -3234,14 +3266,8 @@ try_mount_again:
3234 CIFSSMBQFSAttributeInfo(xid, tcon); 3266 CIFSSMBQFSAttributeInfo(xid, tcon);
3235 } 3267 }
3236 3268
3237 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
3238 cifs_sb->rsize = 1024 * 127;
3239 cFYI(DBG2, "no very large read support, rsize now 127K");
3240 }
3241 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
3242 cifs_sb->rsize = min(cifs_sb->rsize, CIFSMaxBufSize);
3243
3244 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info); 3269 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
3270 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
3245 3271
3246remote_path_check: 3272remote_path_check:
3247#ifdef CONFIG_CIFS_DFS_UPCALL 3273#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8f6917816fec..a3b545ff5250 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1758,6 +1758,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
1758 struct smb_com_read_rsp *pSMBr; 1758 struct smb_com_read_rsp *pSMBr;
1759 struct cifs_io_parms io_parms; 1759 struct cifs_io_parms io_parms;
1760 char *read_data; 1760 char *read_data;
1761 unsigned int rsize;
1761 __u32 pid; 1762 __u32 pid;
1762 1763
1763 if (!nr_segs) 1764 if (!nr_segs)
@@ -1770,6 +1771,9 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
1770 xid = GetXid(); 1771 xid = GetXid();
1771 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1772 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1772 1773
1774 /* FIXME: set up handlers for larger reads and/or convert to async */
1775 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
1776
1773 open_file = file->private_data; 1777 open_file = file->private_data;
1774 pTcon = tlink_tcon(open_file->tlink); 1778 pTcon = tlink_tcon(open_file->tlink);
1775 1779
@@ -1782,7 +1786,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
1782 cFYI(1, "attempting read on write only file instance"); 1786 cFYI(1, "attempting read on write only file instance");
1783 1787
1784 for (total_read = 0; total_read < len; total_read += bytes_read) { 1788 for (total_read = 0; total_read < len; total_read += bytes_read) {
1785 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); 1789 cur_len = min_t(const size_t, len - total_read, rsize);
1786 rc = -EAGAIN; 1790 rc = -EAGAIN;
1787 read_data = NULL; 1791 read_data = NULL;
1788 1792
@@ -1874,6 +1878,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1874 unsigned int bytes_read = 0; 1878 unsigned int bytes_read = 0;
1875 unsigned int total_read; 1879 unsigned int total_read;
1876 unsigned int current_read_size; 1880 unsigned int current_read_size;
1881 unsigned int rsize;
1877 struct cifs_sb_info *cifs_sb; 1882 struct cifs_sb_info *cifs_sb;
1878 struct cifs_tcon *pTcon; 1883 struct cifs_tcon *pTcon;
1879 int xid; 1884 int xid;
@@ -1886,6 +1891,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1886 xid = GetXid(); 1891 xid = GetXid();
1887 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1892 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1888 1893
1894 /* FIXME: set up handlers for larger reads and/or convert to async */
1895 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
1896
1889 if (file->private_data == NULL) { 1897 if (file->private_data == NULL) {
1890 rc = -EBADF; 1898 rc = -EBADF;
1891 FreeXid(xid); 1899 FreeXid(xid);
@@ -1905,8 +1913,8 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1905 for (total_read = 0, current_offset = read_data; 1913 for (total_read = 0, current_offset = read_data;
1906 read_size > total_read; 1914 read_size > total_read;
1907 total_read += bytes_read, current_offset += bytes_read) { 1915 total_read += bytes_read, current_offset += bytes_read) {
1908 current_read_size = min_t(uint, read_size - total_read, 1916 current_read_size = min_t(uint, read_size - total_read, rsize);
1909 cifs_sb->rsize); 1917
1910 /* For windows me and 9x we do not want to request more 1918 /* For windows me and 9x we do not want to request more
1911 than it negotiated since it will refuse the read then */ 1919 than it negotiated since it will refuse the read then */
1912 if ((pTcon->ses) && 1920 if ((pTcon->ses) &&