|
@@ -95,6 +95,7 @@ enum {
|
|
|
Opt_cruid, Opt_gid, Opt_file_mode,
|
|
|
Opt_dirmode, Opt_port,
|
|
|
Opt_rsize, Opt_wsize, Opt_actimeo,
|
|
|
+ Opt_echo_interval,
|
|
|
|
|
|
/* Mount options which take string value */
|
|
|
Opt_user, Opt_pass, Opt_ip,
|
|
@@ -188,6 +189,7 @@ static const match_table_t cifs_mount_option_tokens = {
|
|
|
{ Opt_rsize, "rsize=%s" },
|
|
|
{ Opt_wsize, "wsize=%s" },
|
|
|
{ Opt_actimeo, "actimeo=%s" },
|
|
|
+ { Opt_echo_interval, "echo_interval=%s" },
|
|
|
|
|
|
{ Opt_blank_user, "user=" },
|
|
|
{ Opt_blank_user, "username=" },
|
|
@@ -418,6 +420,7 @@ cifs_echo_request(struct work_struct *work)
|
|
|
int rc;
|
|
|
struct TCP_Server_Info *server = container_of(work,
|
|
|
struct TCP_Server_Info, echo.work);
|
|
|
+ unsigned long echo_interval = server->echo_interval;
|
|
|
|
|
|
/*
|
|
|
* We cannot send an echo if it is disabled or until the
|
|
@@ -427,7 +430,7 @@ cifs_echo_request(struct work_struct *work)
|
|
|
*/
|
|
|
if (!server->ops->need_neg || server->ops->need_neg(server) ||
|
|
|
(server->ops->can_echo && !server->ops->can_echo(server)) ||
|
|
|
- time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
|
|
|
+ time_before(jiffies, server->lstrp + echo_interval - HZ))
|
|
|
goto requeue_echo;
|
|
|
|
|
|
rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
|
|
@@ -436,7 +439,7 @@ cifs_echo_request(struct work_struct *work)
|
|
|
server->hostname);
|
|
|
|
|
|
requeue_echo:
|
|
|
- queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
|
|
|
+ queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
|
|
|
}
|
|
|
|
|
|
static bool
|
|
@@ -487,12 +490,9 @@ server_unresponsive(struct TCP_Server_Info *server)
|
|
|
* a response in >60s.
|
|
|
*/
|
|
|
if (server->tcpStatus == CifsGood &&
|
|
|
- time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
|
|
|
- cifs_dbg(VFS, "Server %s (addr=%pISc) has not responded in "
|
|
|
- "%d seconds. Reconnecting...\n",
|
|
|
- server->hostname,
|
|
|
- (struct sockaddr *)&server->dstaddr,
|
|
|
- (2 * SMB_ECHO_INTERVAL) / HZ);
|
|
|
+ time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
|
|
|
+ cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
|
|
|
+ server->hostname, (2 * server->echo_interval) / HZ);
|
|
|
cifs_reconnect(server);
|
|
|
wake_up(&server->response_q);
|
|
|
return true;
|
|
@@ -1627,6 +1627,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|
|
goto cifs_parse_mount_err;
|
|
|
}
|
|
|
break;
|
|
|
+ case Opt_echo_interval:
|
|
|
+ if (get_option_ul(args, &option)) {
|
|
|
+ cifs_dbg(VFS, "%s: Invalid echo interval value\n",
|
|
|
+ __func__);
|
|
|
+ goto cifs_parse_mount_err;
|
|
|
+ }
|
|
|
+ vol->echo_interval = option;
|
|
|
+ break;
|
|
|
|
|
|
/* String Arguments */
|
|
|
|
|
@@ -2092,6 +2100,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
|
|
|
if (!match_security(server, vol))
|
|
|
return 0;
|
|
|
|
|
|
+ if (server->echo_interval != vol->echo_interval)
|
|
|
+ return 0;
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -2211,6 +2222,12 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
|
|
tcp_ses->tcpStatus = CifsNew;
|
|
|
++tcp_ses->srv_count;
|
|
|
|
|
|
+ if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
|
|
|
+ volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
|
|
|
+ tcp_ses->echo_interval = volume_info->echo_interval * HZ;
|
|
|
+ else
|
|
|
+ tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
|
|
|
+
|
|
|
rc = ip_connect(tcp_ses);
|
|
|
if (rc < 0) {
|
|
|
cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
|
|
@@ -2240,7 +2257,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
|
|
cifs_fscache_get_client_cookie(tcp_ses);
|
|
|
|
|
|
/* queue echo request delayed work */
|
|
|
- queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
|
|
|
+ queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
|
|
|
|
|
|
return tcp_ses;
|
|
|
|