Re: [PATCH] CIFS: Respect negotiated MaxMpxCount

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

 



I like this better than my earlier patch.

I will try this in my test environment, but I don't have a Windows
Vista system or VM configured at the moment.  Anyone have a WIndows
Vista system to try this patch against?  In particular large
sequential file copy (cp of file 500MB or larger) to server with
maxmpx 10 and maxworkitems at default value in the WIndows Vista
registry.

On Tue, Mar 20, 2012 at 5:35 AM, Jeff Layton <jlayton@xxxxxxxxx> wrote:
> 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



-- 
Thanks,

Steve
--
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