From: "Aurélien Aptel" <aaptel@suse.com>
To: Shyam Prasad N <nspmangalore@gmail.com>,
Steve French <smfrench@gmail.com>,
CIFS <linux-cifs@vger.kernel.org>,
Pavel Shilovsky <piastryyy@gmail.com>
Subject: Re: [PATCH] cifs: detect dead connections only when echoes are enabled.
Date: Thu, 29 Apr 2021 13:46:22 +0200 [thread overview]
Message-ID: <87zgxhuxdd.fsf@suse.com> (raw)
In-Reply-To: <CANT5p=qykPGoWwtfSdXe9BsXp083M9-7zaAXJgkPok0Onp6Zow@mail.gmail.com>
Hi Shyam,
Ok so I ended up looking at a lot of code to check this... And I'm still
unsure.
First, it looks like server->echoes is only used for smb2 and there is
a generic server->ops->can_echo() you can use that just returns
server->echoes it for smb2.
Shyam Prasad N <nspmangalore@gmail.com> writes:
> Hi,
>
> Recently, some xfstests and later some manual testing on multi-channel
> revealed that we detect unresponsive servers on some of the channels
> to the same server.
>
> The issue is seen when a channel is setup and sits idle without any
> traffic. Generally, we enable echoes and oplocks on a channel during
> the first request, based on the number of credits available on the
> channel. So on idle channels, we trip in our logic to check server
> unresponsiveness.
That makes sense but while looking at the code I see we always queue
echo request in cifs_get_tcp_session(), which is called when adding a
channel.
cifs_ses_add_channel() {
ctx.echo_interval = ses->server->echo_interval / HZ;
chan->server = cifs_get_tcp_session(&ctx);
rc = cifs_negotiate_protocol(xid, ses) {
server->tcpStatus = CifsGood;
}
rc = cifs_setup_session(xid, ses, cifs_sb->local_nls);
}
cifs_get_tcp_session() {
INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
tcp_ses->tcpStatus = CifsNeedNegotiate;
tcp_ses->lstrp = jiffies;
if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
tcp_ses->echo_interval = ctx->echo_interval * HZ;
else
tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
}
cifs_echo_request() {
if (server->tcpStatus == CifsNeedNegotiate)
echo_interval = 0; <=== branch taken
else
echo_interval = server->echo_interval;
if (server->tcpStatus not in {NeedReconnect, Exiting, New}
&& server->can_echo()
&& jiffies > server->lstrp + echo_interval - HZ)
{
server->echo();
}
queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
===> echo_interval = 0 so calls itself immediatly
}
SMB2_echo() {
if (server->tcpStatus == CifsNeedNegotiate) {
/* No need to send echo on newly established connections */
mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
====> calls smb2_reconnect_server() immediatly if NeedNego
return rc;
}
}
smb2_reconnect_server() {
// channel has no TCONs so it does essentially nothing
}
server_unresponsive() {
if (server->tcpStatus in {Good, NeedNegotiate}
&& jiffies > server->lstrp + 3 * server->echo_interval)
{
cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
(3 * server->echo_interval) / HZ);
cifs_reconnect(server);
return true;
}
return false;
}
So it looks to me that cifs_get_tcp_session() starts the
cifs_echo_request() work, which calls itself with no delay in an
infinite loop doing nothing (that's probably bad...) until session_setup
succeeds, after which the delay between the self-call is set.
During session_setup():
* last response time (lstrp) gets updated
* sending/recv requests should interact with the server
credits and call change_conf(), which should enable server->echoes
==> is that part not working?
Once enabled, the echo_request workq will finally send the echo on the
wire, which should -/+ 1 credit and update lstrp.
> Attached a one-line fix for this. Have tested it in my environment.
> Another approach to fix this could be to enable echoes during
> initialization of a server struct. Or soon after the session setup.
> But I felt that this approach is better. Let me know if you feel
> otherwise.
I think the idea of your change is ok but there's probably also an issue
in crediting in session_setup()/change_conf() if echoes is not enabled
at this point no?
Cheers,
--
Aurélien Aptel / SUSE Labs Samba Team
GPG: 1839 CB5F 9F5B FB9B AA97 8C99 03C8 A49B 521B D5D3
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, DE
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah HRB 247165 (AG München)
next prev parent reply other threads:[~2021-04-29 11:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-29 8:12 [PATCH] cifs: detect dead connections only when echoes are enabled Shyam Prasad N
2021-04-29 11:46 ` Aurélien Aptel [this message]
2021-04-29 12:29 ` Shyam Prasad N
2021-04-29 15:47 ` Shyam Prasad N
2021-04-29 17:37 ` Steve French
2021-04-29 18:52 ` Steve French
2021-05-01 16:40 ` Shyam Prasad N
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87zgxhuxdd.fsf@suse.com \
--to=aaptel@suse.com \
--cc=linux-cifs@vger.kernel.org \
--cc=nspmangalore@gmail.com \
--cc=piastryyy@gmail.com \
--cc=smfrench@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.