Re: [PATCH] cifs: try to pick channel with a minimum of credits

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

 



The comment caught my attention - is that accurate?  When a channel
has fewer than 3 credits (assuming we had two reserved for oplock and
echo), that doesn't mean that there are fewer than 3 credits in flight
- just that current credits available is lower right?  So the channel
could still recover as long as current credits + credits in flight is
at least 3.

+/*
+ * Min number of credits for a channel to be picked.
+ *
+ * Note that once a channel reaches this threshold it will never be
+ * picked again as no credits can be requested from it.
+ */
+#define CIFS_CHANNEL_MIN_CREDITS 3

On Fri, Mar 5, 2021 at 8:24 AM Aurélien Aptel <aaptel@xxxxxxxx> wrote:
>
> From: Aurelien Aptel <aaptel@xxxxxxxx>
>
> Check channel credits to prevent the client from using a starved
> channel that cannot send anything.
>
> Special care must be taken in selecting the minimum value: when
> channels are created they start off with a small amount that slowly
> ramps up as the channel gets used. Thus a new channel might never be
> picked if the min value is too small.
>
> Signed-off-by: Aurelien Aptel <aaptel@xxxxxxxx>
> ---
>  fs/cifs/transport.c | 57 ++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 49 insertions(+), 8 deletions(-)
>
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index e90a1d1380b0..7bb1584b3724 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -44,6 +44,14 @@
>  /* Max number of iovectors we can use off the stack when sending requests. */
>  #define CIFS_MAX_IOV_SIZE 8
>
> +/*
> + * Min number of credits for a channel to be picked.
> + *
> + * Note that once a channel reaches this threshold it will never be
> + * picked again as no credits can be requested from it.
> + */
> +#define CIFS_CHANNEL_MIN_CREDITS 3
> +
>  void
>  cifs_wake_up_task(struct mid_q_entry *mid)
>  {
> @@ -1051,20 +1059,53 @@ cifs_cancelled_callback(struct mid_q_entry *mid)
>  struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
>  {
>         uint index = 0;
> +       struct TCP_Server_Info *s;
>
>         if (!ses)
>                 return NULL;
>
> -       if (!ses->binding) {
> -               /* round robin */
> -               if (ses->chan_count > 1) {
> -                       index = (uint)atomic_inc_return(&ses->chan_seq);
> -                       index %= ses->chan_count;
> -               }
> -               return ses->chans[index].server;
> -       } else {
> +       if (ses->binding)
>                 return cifs_ses_server(ses);
> +
> +       /*
> +        * Channels are created right after the session is made. The
> +        * count cannot change after that so it is not racy to check.
> +        */
> +       if (ses->chan_count == 1)
> +               return ses->chans[index].server;
> +
> +       /* round robin */
> +       index = (uint)atomic_inc_return(&ses->chan_seq);
> +       index %= ses->chan_count;
> +       s = ses->chans[index].server;
> +
> +       /*
> +        * Checking server credits is racy, but getting a slightly
> +        * stale value should not be an issue here
> +        */
> +       if (s->credits <= CIFS_CHANNEL_MIN_CREDITS) {
> +               uint i;
> +
> +               cifs_dbg(VFS, "cannot pick conn_id=0x%llx not enough credits (%u)",
> +                        s->conn_id,
> +                        s->credits);
> +
> +               /*
> +                * Look at all other channels starting from the next
> +                * one and pick first possible channel.
> +                */
> +               for (i = 1; i < ses->chan_count; i++) {
> +                       s = ses->chans[(index+i) % ses->chan_count].server;
> +                       if (s->credits > CIFS_CHANNEL_MIN_CREDITS)
> +                               return s;
> +               }
>         }
> +
> +       /*
> +        * If none are possible, keep the initially picked one, but
> +        * later on it will block to wait for credits or fail.
> +        */
> +       return ses->chans[index].server;
>  }
>
>  int
> --
> 2.30.0
>


-- 
Thanks,

Steve




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

  Powered by Linux