Re: [PATCH 04/13] cifs: wait indefinitely for responses

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

 



2010/12/10 Jeff Layton <jlayton@xxxxxxxxxx>:
> The client should not be timing out on individual SMB requests. Too much
> of the state between client and server is tied to the state of the
> socket. If we time out requests and issue spurious disconnects then that
> comprimises data integrity.
>
> Instead of doing this complicated dance where we try to decide how long
> to wait for a response for particular requests, have the client instead
> wait indefinitely for a response. Also, use a TASK_KILLABLE sleep here
> so that fatal signals will break out of this waiting.
>
> Later patches will add support for detecting dead peers and forcing
> reconnects based on that.
>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/transport.c |  110 ++++++++-------------------------------------------
>  1 files changed, 17 insertions(+), 93 deletions(-)
>
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 2d21bbd..989674c 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -311,48 +311,17 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
>        return 0;
>  }
>
> -static int wait_for_response(struct cifsSesInfo *ses,
> -                       struct mid_q_entry *midQ,
> -                       unsigned long timeout,
> -                       unsigned long time_to_wait)
> +static int
> +wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
>  {
> -       unsigned long curr_timeout;
> -
> -       for (;;) {
> -               curr_timeout = timeout + jiffies;
> -               wait_event_timeout(ses->server->response_q,
> -                       midQ->midState != MID_REQUEST_SUBMITTED, timeout);
> -
> -               if (time_after(jiffies, curr_timeout) &&
> -                       (midQ->midState == MID_REQUEST_SUBMITTED) &&
> -                       ((ses->server->tcpStatus == CifsGood) ||
> -                        (ses->server->tcpStatus == CifsNew))) {
> -
> -                       unsigned long lrt;
> +       int error;
>
> -                       /* We timed out. Is the server still
> -                          sending replies ? */
> -                       spin_lock(&GlobalMid_Lock);
> -                       lrt = ses->server->lstrp;
> -                       spin_unlock(&GlobalMid_Lock);
> +       error = wait_event_killable(server->response_q,
> +                                   midQ->midState != MID_REQUEST_SUBMITTED);
> +       if (error < 0)
> +               return -ERESTARTSYS;
>
> -                       /* Calculate time_to_wait past last receive time.
> -                        Although we prefer not to time out if the
> -                        server is still responding - we will time
> -                        out if the server takes more than 15 (or 45
> -                        or 180) seconds to respond to this request
> -                        and has not responded to any request from
> -                        other threads on the client within 10 seconds */
> -                       lrt += time_to_wait;
> -                       if (time_after(jiffies, lrt)) {
> -                               /* No replies for time_to_wait. */
> -                               cERROR(1, "server not responding");
> -                               return -1;
> -                       }
> -               } else {
> -                       return 0;
> -               }
> -       }
> +       return 0;
>  }
>
>
> @@ -430,7 +399,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
>        int rc = 0;
>        int long_op;
>        unsigned int receive_len;
> -       unsigned long timeout;
>        struct mid_q_entry *midQ;
>        struct smb_hdr *in_buf = iov[0].iov_base;
>
> @@ -497,33 +465,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
>        if (rc < 0)
>                goto out;
>
> -       if (long_op == CIFS_STD_OP)
> -               timeout = 15 * HZ;
> -       else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
> -               timeout = 180 * HZ;
> -       else if (long_op == CIFS_LONG_OP)
> -               timeout = 45 * HZ; /* should be greater than
> -                       servers oplock break timeout (about 43 seconds) */
> -       else if (long_op == CIFS_ASYNC_OP)
> -               goto out;
> -       else if (long_op == CIFS_BLOCKING_OP)
> -               timeout = 0x7FFFFFFF; /*  large, but not so large as to wrap */
> -       else {
> -               cERROR(1, "unknown timeout flag %d", long_op);
> -               rc = -EIO;
> +       if (long_op == CIFS_ASYNC_OP)
>                goto out;
> -       }
> -
> -       /* wait for 15 seconds or until woken up due to response arriving or
> -          due to last connection to this server being unmounted */
> -       if (signal_pending(current)) {
> -               /* if signal pending do not hold up user for full smb timeout
> -               but we still give response a chance to complete */
> -               timeout = 2 * HZ;
> -       }
>
> -       /* No user interrupts in wait - wreaks havoc with performance */
> -       wait_for_response(ses, midQ, timeout, 10 * HZ);
> +       rc = wait_for_response(ses->server, midQ);
> +       if (rc != 0)
> +               goto out;
>
>        rc = handle_mid_result(midQ, ses->server);
>        if (rc != 0)
> @@ -598,7 +545,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
>  {
>        int rc = 0;
>        unsigned int receive_len;
> -       unsigned long timeout;
>        struct mid_q_entry *midQ;
>
>        if (ses == NULL) {
> @@ -662,33 +608,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
>        if (rc < 0)
>                goto out;
>
> -       if (long_op == CIFS_STD_OP)
> -               timeout = 15 * HZ;
> -       /* wait for 15 seconds or until woken up due to response arriving or
> -          due to last connection to this server being unmounted */
> -       else if (long_op == CIFS_ASYNC_OP)
> -               goto out;
> -       else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
> -               timeout = 180 * HZ;
> -       else if (long_op == CIFS_LONG_OP)
> -               timeout = 45 * HZ; /* should be greater than
> -                       servers oplock break timeout (about 43 seconds) */
> -       else if (long_op == CIFS_BLOCKING_OP)
> -               timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
> -       else {
> -               cERROR(1, "unknown timeout flag %d", long_op);
> -               rc = -EIO;
> +       if (long_op == CIFS_ASYNC_OP)
>                goto out;
> -       }
>
> -       if (signal_pending(current)) {
> -               /* if signal pending do not hold up user for full smb timeout
> -               but we still give response a chance to complete */
> -               timeout = 2 * HZ;
> -       }
> -
> -       /* No user interrupts in wait - wreaks havoc with performance */
> -       wait_for_response(ses, midQ, timeout, 10 * HZ);
> +       rc = wait_for_response(ses->server, midQ);
> +       if (rc != 0)
> +               goto out;
>
>        rc = handle_mid_result(midQ, ses->server);
>        if (rc != 0)
> @@ -906,8 +831,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
>                        }
>                }
>
> -               /* Wait 5 seconds for the response. */
> -               if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
> +               if (wait_for_response(ses->server, midQ) == 0) {
>                        /* We got the response - restart system call. */
>                        rstart = 1;
>                }
> --
> 1.7.3.2
>


Reviewed-by:  Pavel Shilovsky <piastryyy@xxxxxxxxx>

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