Re: [PATCH] CIFS: Respect negotiated MaxMpxCount

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 20 Mar 2012 12:55:09 +0300
Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:

> Some servers sets this value less than 50 that was hardcoded and
> we lost the connection if when we exceed this limit. Fix this by
> respecting this value - not sending more than the server allows.
> 
> Cc: stable@xxxxxxxxxx
> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
> ---
>  fs/cifs/cifsfs.c    |    8 ++++----
>  fs/cifs/cifsglob.h  |   10 +++-------
>  fs/cifs/cifssmb.c   |    9 +++++++--
>  fs/cifs/connect.c   |   11 ++++-------
>  fs/cifs/dir.c       |    6 ++++--
>  fs/cifs/file.c      |    4 ++--
>  fs/cifs/transport.c |    4 ++--
>  7 files changed, 26 insertions(+), 26 deletions(-)
> 
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index b1fd382..6ee1cb4 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -76,7 +76,7 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
>  unsigned int cifs_max_pending = CIFS_MAX_REQ;
>  module_param(cifs_max_pending, int, 0444);
>  MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
> -				   "Default: 50 Range: 2 to 256");
> +				   "Default: 32767 Range: 2 to 32767.");
>  unsigned short echo_retries = 5;
>  module_param(echo_retries, ushort, 0644);
>  MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
> @@ -1116,9 +1116,9 @@ init_cifs(void)
>  	if (cifs_max_pending < 2) {
>  		cifs_max_pending = 2;
>  		cFYI(1, "cifs_max_pending set to min of 2");
> -	} else if (cifs_max_pending > 256) {
> -		cifs_max_pending = 256;
> -		cFYI(1, "cifs_max_pending set to max of 256");
> +	} else if (cifs_max_pending > CIFS_MAX_REQ) {
> +		cifs_max_pending = CIFS_MAX_REQ;
> +		cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
>  	}
>  
>  	rc = cifs_fscache_register();
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 76e7d8b..d47d20a 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -55,14 +55,9 @@
>  
>  /*
>   * MAX_REQ is the maximum number of requests that WE will send
> - * on one socket concurrently. It also matches the most common
> - * value of max multiplex returned by servers.  We may
> - * eventually want to use the negotiated value (in case
> - * future servers can handle more) when we are more confident that
> - * we will not have problems oveloading the socket with pending
> - * write data.
> + * on one socket concurrently.
>   */
> -#define CIFS_MAX_REQ 50
> +#define CIFS_MAX_REQ 32767
>  
>  #define RFC1001_NAME_LEN 15
>  #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
> @@ -263,6 +258,7 @@ struct TCP_Server_Info {
>  	bool session_estab; /* mark when very first sess is established */
>  	u16 dialect; /* dialect index that server chose */
>  	enum securityEnum secType;
> +	bool oplocks:1; /* enable oplocks */
>  	unsigned int maxReq;	/* Clients should submit no more */
>  	/* than maxReq distinct unanswered SMBs to the server when using  */
>  	/* multiplexed reads or writes */
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 8b7794c..cd66b76 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -458,7 +458,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
>  			goto neg_err_exit;
>  		}
>  		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
> -		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
> +		server->maxReq = min_t(unsigned int,
> +				       le16_to_cpu(rsp->MaxMpxCount),
> +				       cifs_max_pending);
> +		server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
>  		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
>  		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
>  		/* even though we do not use raw we might as well set this
> @@ -564,7 +567,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
>  
>  	/* one byte, so no need to convert this or EncryptionKeyLen from
>  	   little endian */
> -	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
> +	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
> +			       cifs_max_pending);
> +	server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
>  	/* probably no need to store and check maxvcs */
>  	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
>  	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 602f77c..03f71fb 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -642,14 +642,10 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
>  	spin_unlock(&GlobalMid_Lock);
>  	wake_up_all(&server->response_q);
>  
> -	/*
> -	 * Check if we have blocked requests that need to free. Note that
> -	 * cifs_max_pending is normally 50, but can be set at module install
> -	 * time to as little as two.
> -	 */
> +	/* Check if we have blocked requests that need to free. */
>  	spin_lock(&GlobalMid_Lock);
> -	if (atomic_read(&server->inFlight) >= cifs_max_pending)
> -		atomic_set(&server->inFlight, cifs_max_pending - 1);
> +	if (atomic_read(&server->inFlight) >= server->maxReq)
> +		atomic_set(&server->inFlight, server->maxReq - 1);
>  	/*
>  	 * We do not want to set the max_pending too low or we could end up
>  	 * with the counter going negative.
> @@ -1910,6 +1906,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
>  	tcp_ses->noautotune = volume_info->noautotune;
>  	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
>  	atomic_set(&tcp_ses->inFlight, 0);
> +	tcp_ses->maxReq = 1; /* enough to send negotiate request */
>  	init_waitqueue_head(&tcp_ses->response_q);
>  	init_waitqueue_head(&tcp_ses->request_q);
>  	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index bc7e244..d172c8e 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
>  	}
>  	tcon = tlink_tcon(tlink);
>  
> -	if (enable_oplocks)
> +	if (tcon->ses->server->oplocks)
>  		oplock = REQ_OPLOCK;
>  
>  	if (nd)
> @@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  {
>  	int xid;
>  	int rc = 0; /* to get around spurious gcc warning, set to zero here */
> -	__u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
> +	__u32 oplock;
>  	__u16 fileHandle = 0;
>  	bool posix_open = false;
>  	struct cifs_sb_info *cifs_sb;
> @@ -518,6 +518,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  	}
>  	pTcon = tlink_tcon(tlink);
>  
> +	oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
> +
>  	/*
>  	 * Don't allow the separator character in a path component.
>  	 * The VFS will not allow "/", but "\" is allowed by posix.
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 8e02dbd..159fcc5 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -380,7 +380,7 @@ int cifs_open(struct inode *inode, struct file *file)
>  	cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
>  		 inode, file->f_flags, full_path);
>  
> -	if (enable_oplocks)
> +	if (tcon->ses->server->oplocks)
>  		oplock = REQ_OPLOCK;
>  	else
>  		oplock = 0;
> @@ -505,7 +505,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
>  	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
>  		 inode, pCifsFile->f_flags, full_path);
>  
> -	if (enable_oplocks)
> +	if (tcon->ses->server->oplocks)
>  		oplock = REQ_OPLOCK;
>  	else
>  		oplock = 0;
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 0cc9584..99a27cf 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -265,12 +265,12 @@ static int wait_for_free_request(struct TCP_Server_Info *server,
>  
>  	spin_lock(&GlobalMid_Lock);
>  	while (1) {
> -		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
> +		if (atomic_read(&server->inFlight) >= server->maxReq) {
>  			spin_unlock(&GlobalMid_Lock);
>  			cifs_num_waiters_inc(server);
>  			wait_event(server->request_q,
>  				   atomic_read(&server->inFlight)
> -				     < cifs_max_pending);
> +				     < server->maxReq);
>  			cifs_num_waiters_dec(server);
>  			spin_lock(&GlobalMid_Lock);
>  		} else {

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux