Re: [PATCH 1/6] CIFS: Introduce credit-based flow control

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

 



2012/2/12 Jeff Layton <jlayton@xxxxxxxxx>:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Thu,  9 Feb 2012 11:41:24 +0300
> Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>
>> and send no more than credits value requests at once. For SMB/CIFS
>> it's trivial: increment this value by receiving any message and
>> decrement by sending one.
>>
>> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
>
> Yes! Nice work. This is clearly the right approach for merging SMB2
> support into the kernel. Extend the CIFS code to do what we need and
> share as much code as possible between the SMB1 and SMB2 support. By
> doing this piecemeal too we can avoid a wholesale "code dump" into the
> kernel.
>
> Some comments below.
>
>> ---
>>  fs/cifs/cifsglob.h  |    1 +
>>  fs/cifs/cifssmb.c   |    3 +++
>>  fs/cifs/connect.c   |   10 ++++------
>>  fs/cifs/transport.c |   20 ++++++++++++++++----
>>  4 files changed, 24 insertions(+), 10 deletions(-)
>>
>> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> index 76e7d8b..f96752a 100644
>> --- a/fs/cifs/cifsglob.h
>> +++ b/fs/cifs/cifsglob.h
>> @@ -256,6 +256,7 @@ struct TCP_Server_Info {
>>       bool noautotune;                /* do not autotune send buf sizes */
>>       bool tcp_nodelay;
>>       atomic_t inFlight;  /* number of requests on the wire to server */
>> +     atomic_t credits;  /* send no more requests at once */
>
> Currently, it's not clear whether the inFlight counter is protected by
> the GlobalMid_lock or not. Ditto for this new counter. If it is
> protected by it, then there's no need for it to be an atomic value. The
> locking around this needs to be explicitly clear to avoid later bugs
> when we tinker with this code.

We decrement inFlight value without holding GlobalMid_lock - so it
should be atomic.

>
> Also, should we just replace the inFlight counter with the credits
> counter? Is there some way to calculate the # of requests in flight given
> the value of "credits" in the SMB2 case?

I don't think so.

>
>>       struct mutex srv_mutex;
>>       struct task_struct *tsk;
>>       char server_GUID[16];
>> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
>> index 8b7794c..fbc4437 100644
>> --- a/fs/cifs/cifssmb.c
>> +++ b/fs/cifs/cifssmb.c
>> @@ -717,6 +717,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
>>
>>       DeleteMidQEntry(mid);
>>       atomic_dec(&server->inFlight);
>> +     atomic_inc(&server->credits);
>>       wake_up(&server->request_q);
>>  }
>>
>> @@ -1670,6 +1671,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
>>       queue_work(system_nrt_wq, &rdata->work);
>>       DeleteMidQEntry(mid);
>>       atomic_dec(&server->inFlight);
>> +     atomic_inc(&server->credits);
>>       wake_up(&server->request_q);
>>  }
>>
>> @@ -2111,6 +2113,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
>>       queue_work(system_nrt_wq, &wdata->work);
>>       DeleteMidQEntry(mid);
>>       atomic_dec(&tcon->ses->server->inFlight);
>> +     atomic_inc(&tcon->ses->server->credits);
>>       wake_up(&tcon->ses->server->request_q);
>>  }
>>
>> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> index 602f77c..6b95304 100644
>> --- a/fs/cifs/connect.c
>> +++ b/fs/cifs/connect.c
>> @@ -648,12 +648,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
>>        * time to as little as two.
>>        */
>>       spin_lock(&GlobalMid_Lock);
>> -     if (atomic_read(&server->inFlight) >= cifs_max_pending)
>> -             atomic_set(&server->inFlight, cifs_max_pending - 1);
>> -     /*
>> -      * We do not want to set the max_pending too low or we could end up
>> -      * with the counter going negative.
>> -      */
>> +     if (atomic_read(&server->credits) == 0)
>> +             atomic_set(&server->credits, 1);
>>       spin_unlock(&GlobalMid_Lock);
>>       /*
>>        * Although there should not be any requests blocked on this queue it
>> @@ -3759,9 +3755,11 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
>>       if (server->maxBuf != 0)
>>               return 0;
>>
>> +     atomic_set(&ses->server->credits, cifs_max_pending);
>>       rc = CIFSSMBNegotiate(xid, ses);
>>       if (rc == -EAGAIN) {
>>               /* retry only once on 1st time connection */
>> +             atomic_set(&ses->server->credits, cifs_max_pending);
>>               rc = CIFSSMBNegotiate(xid, ses);
>>               if (rc == -EAGAIN)
>>                       rc = -EHOSTDOWN;
>> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
>> index 0cc9584..f1f927f 100644
>> --- a/fs/cifs/transport.c
>> +++ b/fs/cifs/transport.c
>> @@ -260,17 +260,17 @@ static int wait_for_free_request(struct TCP_Server_Info *server,
>>       if (long_op == CIFS_ASYNC_OP) {
>>               /* oplock breaks must not be held up */
>>               atomic_inc(&server->inFlight);
>> +             atomic_dec(&server->credits);
>>               return 0;
>>       }
>>
>
> I haven't gotten to your later patches so I may be reviewing
> prematurely, but I think we need to rethink the code above. Allowing
> the client to exceed the maxmpx is clearly problematic. Rather than
> doing that we ought to attempt to keep 2 credits in reserve at any
> given time -- one for oplock breaks and one for echo requests.
>
> If MaxMpx 2, then we should disable oplocks. If it's 1, then we
> should disable echoes and oplocks. The latter case may take some overhaul
> of how the echo timeout handling works.

I agree that allowing to exceed the maxmps is wrong, but I think we
can leave it as it is for this patch.

>
>>       spin_lock(&GlobalMid_Lock);
>>       while (1) {
>> -             if (atomic_read(&server->inFlight) >= cifs_max_pending) {
>> +             if (atomic_read(&server->credits) == 0) {

Now I think that (according to echo and oplock problem) we need this to be:

if (atomic_read(&server->credits) <= 0) {

Right?

>>                       spin_unlock(&GlobalMid_Lock);
>>                       cifs_num_waiters_inc(server);
>>                       wait_event(server->request_q,
>> -                                atomic_read(&server->inFlight)
>> -                                  < cifs_max_pending);
>> +                                atomic_read(&server->credits) > 0);
>>                       cifs_num_waiters_dec(server);
>>                       spin_lock(&GlobalMid_Lock);
>>               } else {
>> @@ -283,8 +283,10 @@ static int wait_for_free_request(struct TCP_Server_Info *server,
>>                          as they are allowed to block on server */
>>
>>                       /* update # of requests on the wire to server */
>> -                     if (long_op != CIFS_BLOCKING_OP)
>> +                     if (long_op != CIFS_BLOCKING_OP) {
>>                               atomic_inc(&server->inFlight);
>> +                             atomic_dec(&server->credits);
>> +                     }
>>                       spin_unlock(&GlobalMid_Lock);
>>                       break;
>>               }
>> @@ -360,6 +362,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>>       if (mid == NULL) {
>>               mutex_unlock(&server->srv_mutex);
>>               atomic_dec(&server->inFlight);
>> +             atomic_inc(&server->credits);
>>               wake_up(&server->request_q);
>>               return -ENOMEM;
>>       }
>> @@ -393,6 +396,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>>  out_err:
>>       delete_mid(mid);
>>       atomic_dec(&server->inFlight);
>> +     atomic_inc(&server->credits);
>>       wake_up(&server->request_q);
>>       return rc;
>>  }
>> @@ -565,6 +569,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>>               cifs_small_buf_release(in_buf);
>>               /* Update # of requests on wire to server */
>>               atomic_dec(&ses->server->inFlight);
>> +             atomic_inc(&ses->server->credits);
>>               wake_up(&ses->server->request_q);
>>               return rc;
>>       }
>> @@ -602,6 +607,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>>                       spin_unlock(&GlobalMid_Lock);
>>                       cifs_small_buf_release(in_buf);
>>                       atomic_dec(&ses->server->inFlight);
>> +                     atomic_inc(&ses->server->credits);
>>                       wake_up(&ses->server->request_q);
>>                       return rc;
>>               }
>> @@ -613,6 +619,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>>       rc = cifs_sync_mid_result(midQ, ses->server);
>>       if (rc != 0) {
>>               atomic_dec(&ses->server->inFlight);
>> +             atomic_inc(&ses->server->credits);
>>               wake_up(&ses->server->request_q);
>>               return rc;
>>       }
>> @@ -638,6 +645,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>>  out:
>>       delete_mid(midQ);
>>       atomic_dec(&ses->server->inFlight);
>> +     atomic_inc(&ses->server->credits);
>>       wake_up(&ses->server->request_q);
>>
>>       return rc;
>> @@ -689,6 +697,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>>               mutex_unlock(&ses->server->srv_mutex);
>>               /* Update # of requests on wire to server */
>>               atomic_dec(&ses->server->inFlight);
>> +             atomic_inc(&ses->server->credits);
>>               wake_up(&ses->server->request_q);
>>               return rc;
>>       }
>> @@ -722,6 +731,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>>                       midQ->callback = DeleteMidQEntry;
>>                       spin_unlock(&GlobalMid_Lock);
>>                       atomic_dec(&ses->server->inFlight);
>> +                     atomic_inc(&ses->server->credits);
>>                       wake_up(&ses->server->request_q);
>>                       return rc;
>>               }
>> @@ -731,6 +741,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>>       rc = cifs_sync_mid_result(midQ, ses->server);
>>       if (rc != 0) {
>>               atomic_dec(&ses->server->inFlight);
>> +             atomic_inc(&ses->server->credits);
>>               wake_up(&ses->server->request_q);
>>               return rc;
>>       }
>> @@ -748,6 +759,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>>  out:
>>       delete_mid(midQ);
>>       atomic_dec(&ses->server->inFlight);
>> +     atomic_inc(&ses->server->credits);
>>       wake_up(&ses->server->request_q);
>>
>>       return rc;
>
>
> - --
> Jeff Layton <jlayton@xxxxxxxxx>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2.0.18 (GNU/Linux)
>
> iQIcBAEBAgAGBQJPN7Y1AAoJEAAOaEEZVoIVil4P/1IfpsJswGldw1/ufTuoMw4Y
> pT80BdlFuNQ612hVXq3xrzrP8WYHlwnhfADS5n+JCdeBJwfJzV//bah5I5/4cLfY
> htvajLzlhL0aCIK57Sxa1GoHiXkadaO9TI+vA6x5hM2SALhJT2UA/4QVNGsC5jhG
> nDs07RjcGRzFT2nZ8/LLDliYmQXZk5FvnieShEdiDofcod2ILwaBUTIbJ5hz+CGL
> GXTFmo2GKKyZGIuGCeg+8AkV3oeFXdfakjzjkTBFZSqLnGZoJyHe4vzKhob1mGtO
> Xw7szAlFDxCLylccfid+ila60u2EHQiGZkPjRJCTcZmb+BpUuKo+5ShXBLOItIxQ
> gWLsydodP9G5uIHsrWakY/tfaQSUZzbfmIQMJKrJ31MKo/EtVdPgSdRGJKlPukjS
> 0oc+hW1o6Gkdqz98lL4sBiT6Mn6/ekB3CXdhOR1TTC+5tyOdLwxoI6DejDp0HlDs
> wypfNgbrhLarV/BF/LpY/5MXI8kGyOLZT584bO2Bl2QTRwfGUwgmMAwluf0MEMs2
> JJO5KLN+uozfLi/6b7YcT4/Uqy5D1BwWowT/0Lf2IpZYuLkyaKiWZ/Q/K6mMDKNo
> p7P+qsyF2RjwYpltSWG6zPPldLPczkWvy9BiQKXMFWI2EVNHbbPMUKRaWvIw66hX
> 28PtjNXqCfDFfIhrHE86
> =aqY+
> -----END PGP SIGNATURE-----

Thanks for reviewing this one!

-- 
Best regards,
Pavel Shilovsky.
--
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