aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-07-11 09:09:35 -0400
committerSteve French <smfrench@gmail.com>2012-07-17 00:57:09 -0400
commit3ae629d98bd5ed77585a878566f04f310adbc591 (patch)
tree11a55d0bdca06f3a8d0b37df19e668a400c7a62c /fs/cifs/connect.c
parentffc61ccbb96809df8d97ed609ac86b509eaf9056 (diff)
cifs: on CONFIG_HIGHMEM machines, limit the rsize/wsize to the kmap space
We currently rely on being able to kmap all of the pages in an async read or write request. If you're on a machine that has CONFIG_HIGHMEM set then that kmap space is limited, sometimes to as low as 512 slots. With 512 slots, we can only support up to a 2M r/wsize, and that's assuming that we can get our greedy little hands on all of them. There are other users however, so it's possible we'll end up stuck with a size that large. Since we can't handle a rsize or wsize larger than that currently, cap those options at the number of kmap slots we have. We could consider capping it even lower, but we currently default to a max of 1M. Might as well allow those luddites on 32 bit arches enough rope to hang themselves. A more robust fix would be to teach the send and receive routines how to contend with an array of pages so we don't need to marshal up a kvec array at all. That's a fairly significant overhaul though, so we'll need this limit in place until that's ready. Cc: <stable@vger.kernel.org> Reported-by: Jian Li <jiali@redhat.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0ae86ddf2213..94b7788c3189 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3445,6 +3445,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3445#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) 3445#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
3446#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) 3446#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
3447 3447
3448/*
3449 * On hosts with high memory, we can't currently support wsize/rsize that are
3450 * larger than we can kmap at once. Cap the rsize/wsize at
3451 * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
3452 * larger than that anyway.
3453 */
3454#ifdef CONFIG_HIGHMEM
3455#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE)
3456#else /* CONFIG_HIGHMEM */
3457#define CIFS_KMAP_SIZE_LIMIT (1<<24)
3458#endif /* CONFIG_HIGHMEM */
3459
3448static unsigned int 3460static unsigned int
3449cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) 3461cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3450{ 3462{
@@ -3475,6 +3487,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3475 wsize = min_t(unsigned int, wsize, 3487 wsize = min_t(unsigned int, wsize,
3476 server->maxBuf - sizeof(WRITE_REQ) + 4); 3488 server->maxBuf - sizeof(WRITE_REQ) + 4);
3477 3489
3490 /* limit to the amount that we can kmap at once */
3491 wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
3492
3478 /* hard limit of CIFS_MAX_WSIZE */ 3493 /* hard limit of CIFS_MAX_WSIZE */
3479 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); 3494 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3480 3495
@@ -3516,6 +3531,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3516 if (!(server->capabilities & CAP_LARGE_READ_X)) 3531 if (!(server->capabilities & CAP_LARGE_READ_X))
3517 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); 3532 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3518 3533
3534 /* limit to the amount that we can kmap at once */
3535 rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
3536
3519 /* hard limit of CIFS_MAX_RSIZE */ 3537 /* hard limit of CIFS_MAX_RSIZE */
3520 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); 3538 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3521 3539