|
@@ -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=" },
|
|
@@ -368,7 +370,6 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|
|
server->session_key.response = NULL;
|
|
|
server->session_key.len = 0;
|
|
|
server->lstrp = jiffies;
|
|
|
- mutex_unlock(&server->srv_mutex);
|
|
|
|
|
|
/* mark submitted MIDs for retry and issue callback */
|
|
|
INIT_LIST_HEAD(&retry_list);
|
|
@@ -381,6 +382,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|
|
list_move(&mid_entry->qhead, &retry_list);
|
|
|
}
|
|
|
spin_unlock(&GlobalMid_Lock);
|
|
|
+ mutex_unlock(&server->srv_mutex);
|
|
|
|
|
|
cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
|
|
|
list_for_each_safe(tmp, tmp2, &retry_list) {
|
|
@@ -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,9 +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 has not responded in %d seconds. Reconnecting...\n",
|
|
|
- server->hostname, (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;
|
|
@@ -828,7 +831,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|
|
* 48 bytes is enough to display the header and a little bit
|
|
|
* into the payload for debugging purposes.
|
|
|
*/
|
|
|
- length = server->ops->check_message(buf, server->total_read);
|
|
|
+ length = server->ops->check_message(buf, server->total_read, server);
|
|
|
if (length != 0)
|
|
|
cifs_dump_mem("Bad SMB: ", buf,
|
|
|
min_t(unsigned int, server->total_read, 48));
|
|
@@ -1624,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 */
|
|
|
|
|
@@ -2089,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;
|
|
|
}
|
|
|
|
|
@@ -2208,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");
|
|
@@ -2237,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;
|
|
|
|