> We ought to be going to great lengths to *avoid* breaking the
> connection whenever possible as so much of the state is tied up with
> the state of the socket.
We do go to great lengths to avoid giving up on the server, but there are a
few reasons we have to give up on the server and reconnect:
1) malformed smb length errors and signing errors (because typically we can't
"resync" to the beginning of the next smb safely)
2) unresponsive servers
For unresponsive servers it is difficult to pick a perfect timeout value,
but allowing i/o to retry forever can cause system hangs, and
perhaps allow a bad firewall or rogue server to make a client
unusable. There are cases in which pending i/o can not
be cancelled with <ctl-c>.
A typical SMB/CIFS network roundtrip takes 1ms or less. A "slow"
response still be well under 100ms, unless on a WAN (where
1 second might be considered slow).
In the dark ages (older Windows, OS/2 etc.) 45 seconds (or half of that,
about 22 seconds) were commonly used values to decide if a server
was unresponsive/broken, but this is probably too long for modern servers.
If a server is not responding in 15 seconds to a routine request, then
something bad has happened (disk hung, server crashed,
firewall eaten a request, etc.). Note that NFS can lose
requests (over UDP) and (for v3 and v2) and can repeat requests
since it is supposed to be idempotent which stateful protocols
can not do safely. In SMB2 since the server can send
an "async" response to a synchronous request, we probably
can retry certain commands safely in some cases (and can
cancel slow requests).
There are a few exceptions where the server could reasonably
take a while to respond:
1) very, very large writes (many megabytes in one request
frame) - which we don't do
2) SMB copy (which we don't issue)
3) Writes past end of file (which for some servers without
sparse file support may require zero-filling the previous bytes)
4) blocking byte range locks
5) SMB find notify (we don't send, directory change notification)
6) operations on offline files (which we should check for
via the corresponding DOS attribute bit but don't yet)
cifs kernel client adjusts the timeout longer for the case of Writes,
(and of course special cases writes past end of file and blocking
byte range locks so they don't time out). In addition we
don't timeout if any response (not just the one we are waiting on) has
been received from the server within the timeout period.
We clearly have to timeout eventually when the network
or server is unresponsive, and have to do it before the user
decides to reboot or turn off the machine. Users would be
mad if a network or firewall problem (common) caused
them to have to reboot their system in some cases
where they can't issue control-c. We could
make that timeout configurable or simply
fix the "hard" mount option as Shirish has
suggested. Setting the timeout to infinite this way for
"broken" servers that will take more than 15 seconds
to respond sometimes (when they should take 1 ms),
may be enough.
Besides fixing the "hard" mount option there are three
1) When the server has not responded in 15 or so seconds
to this request (and no other request in other threads)
issue an "SMB echo" request to see if the server is still
alive. If the echo comes back ok - reset the timeout.
I have been trying something like this in the SMB2
code (although haven't run into a very slow server
like we see from time to time in CIFS yet)
2) issue an SMB cancel for requests that have been
pending too long (15 seconds?) and then retry them
3) Don't timeout requests to files with the
"offline" file attribute bit (or perhaps don't timeout
read or write or sync requests)