diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 8 | ||||
-rw-r--r-- | fs/cifs/connect.c | 35 |
3 files changed, 34 insertions, 11 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b7fcb3151103..53e343d073bb 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -507,6 +507,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
507 | 507 | ||
508 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); | 508 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); |
509 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); | 509 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); |
510 | seq_printf(s, ",echo_interval=%lu", | ||
511 | tcon->ses->server->echo_interval / HZ); | ||
510 | /* convert actimeo and display it in seconds */ | 512 | /* convert actimeo and display it in seconds */ |
511 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); | 513 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); |
512 | 514 | ||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 2b510c537a0d..9d14926531ba 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -70,8 +70,10 @@ | |||
70 | #define SERVER_NAME_LENGTH 40 | 70 | #define SERVER_NAME_LENGTH 40 |
71 | #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) | 71 | #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) |
72 | 72 | ||
73 | /* SMB echo "timeout" -- FIXME: tunable? */ | 73 | /* echo interval in seconds */ |
74 | #define SMB_ECHO_INTERVAL (60 * HZ) | 74 | #define SMB_ECHO_INTERVAL_MIN 1 |
75 | #define SMB_ECHO_INTERVAL_MAX 600 | ||
76 | #define SMB_ECHO_INTERVAL_DEFAULT 60 | ||
75 | 77 | ||
76 | #include "cifspdu.h" | 78 | #include "cifspdu.h" |
77 | 79 | ||
@@ -507,6 +509,7 @@ struct smb_vol { | |||
507 | struct sockaddr_storage dstaddr; /* destination address */ | 509 | struct sockaddr_storage dstaddr; /* destination address */ |
508 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ | 510 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ |
509 | struct nls_table *local_nls; | 511 | struct nls_table *local_nls; |
512 | unsigned int echo_interval; /* echo interval in secs */ | ||
510 | }; | 513 | }; |
511 | 514 | ||
512 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ | 515 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ |
@@ -628,6 +631,7 @@ struct TCP_Server_Info { | |||
628 | unsigned int max_read; | 631 | unsigned int max_read; |
629 | unsigned int max_write; | 632 | unsigned int max_write; |
630 | #endif /* CONFIG_CIFS_SMB2 */ | 633 | #endif /* CONFIG_CIFS_SMB2 */ |
634 | unsigned long echo_interval; | ||
631 | }; | 635 | }; |
632 | 636 | ||
633 | static inline unsigned int | 637 | static inline unsigned int |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 103054af9713..de53c5558fe3 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -95,6 +95,7 @@ enum { | |||
95 | Opt_cruid, Opt_gid, Opt_file_mode, | 95 | Opt_cruid, Opt_gid, Opt_file_mode, |
96 | Opt_dirmode, Opt_port, | 96 | Opt_dirmode, Opt_port, |
97 | Opt_rsize, Opt_wsize, Opt_actimeo, | 97 | Opt_rsize, Opt_wsize, Opt_actimeo, |
98 | Opt_echo_interval, | ||
98 | 99 | ||
99 | /* Mount options which take string value */ | 100 | /* Mount options which take string value */ |
100 | Opt_user, Opt_pass, Opt_ip, | 101 | Opt_user, Opt_pass, Opt_ip, |
@@ -188,6 +189,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
188 | { Opt_rsize, "rsize=%s" }, | 189 | { Opt_rsize, "rsize=%s" }, |
189 | { Opt_wsize, "wsize=%s" }, | 190 | { Opt_wsize, "wsize=%s" }, |
190 | { Opt_actimeo, "actimeo=%s" }, | 191 | { Opt_actimeo, "actimeo=%s" }, |
192 | { Opt_echo_interval, "echo_interval=%s" }, | ||
191 | 193 | ||
192 | { Opt_blank_user, "user=" }, | 194 | { Opt_blank_user, "user=" }, |
193 | { Opt_blank_user, "username=" }, | 195 | { Opt_blank_user, "username=" }, |
@@ -418,6 +420,7 @@ cifs_echo_request(struct work_struct *work) | |||
418 | int rc; | 420 | int rc; |
419 | struct TCP_Server_Info *server = container_of(work, | 421 | struct TCP_Server_Info *server = container_of(work, |
420 | struct TCP_Server_Info, echo.work); | 422 | struct TCP_Server_Info, echo.work); |
423 | unsigned long echo_interval = server->echo_interval; | ||
421 | 424 | ||
422 | /* | 425 | /* |
423 | * We cannot send an echo if it is disabled or until the | 426 | * We cannot send an echo if it is disabled or until the |
@@ -427,7 +430,7 @@ cifs_echo_request(struct work_struct *work) | |||
427 | */ | 430 | */ |
428 | if (!server->ops->need_neg || server->ops->need_neg(server) || | 431 | if (!server->ops->need_neg || server->ops->need_neg(server) || |
429 | (server->ops->can_echo && !server->ops->can_echo(server)) || | 432 | (server->ops->can_echo && !server->ops->can_echo(server)) || |
430 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | 433 | time_before(jiffies, server->lstrp + echo_interval - HZ)) |
431 | goto requeue_echo; | 434 | goto requeue_echo; |
432 | 435 | ||
433 | rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; | 436 | rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; |
@@ -436,7 +439,7 @@ cifs_echo_request(struct work_struct *work) | |||
436 | server->hostname); | 439 | server->hostname); |
437 | 440 | ||
438 | requeue_echo: | 441 | requeue_echo: |
439 | queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL); | 442 | queue_delayed_work(cifsiod_wq, &server->echo, echo_interval); |
440 | } | 443 | } |
441 | 444 | ||
442 | static bool | 445 | static bool |
@@ -487,12 +490,9 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
487 | * a response in >60s. | 490 | * a response in >60s. |
488 | */ | 491 | */ |
489 | if (server->tcpStatus == CifsGood && | 492 | if (server->tcpStatus == CifsGood && |
490 | time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) { | 493 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { |
491 | cifs_dbg(VFS, "Server %s (addr=%pISc) has not responded in " | 494 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", |
492 | "%d seconds. Reconnecting...\n", | 495 | server->hostname, (2 * server->echo_interval) / HZ); |
493 | server->hostname, | ||
494 | (struct sockaddr *)&server->dstaddr, | ||
495 | (2 * SMB_ECHO_INTERVAL) / HZ); | ||
496 | cifs_reconnect(server); | 496 | cifs_reconnect(server); |
497 | wake_up(&server->response_q); | 497 | wake_up(&server->response_q); |
498 | return true; | 498 | return true; |
@@ -1627,6 +1627,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1627 | goto cifs_parse_mount_err; | 1627 | goto cifs_parse_mount_err; |
1628 | } | 1628 | } |
1629 | break; | 1629 | break; |
1630 | case Opt_echo_interval: | ||
1631 | if (get_option_ul(args, &option)) { | ||
1632 | cifs_dbg(VFS, "%s: Invalid echo interval value\n", | ||
1633 | __func__); | ||
1634 | goto cifs_parse_mount_err; | ||
1635 | } | ||
1636 | vol->echo_interval = option; | ||
1637 | break; | ||
1630 | 1638 | ||
1631 | /* String Arguments */ | 1639 | /* String Arguments */ |
1632 | 1640 | ||
@@ -2092,6 +2100,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2092 | if (!match_security(server, vol)) | 2100 | if (!match_security(server, vol)) |
2093 | return 0; | 2101 | return 0; |
2094 | 2102 | ||
2103 | if (server->echo_interval != vol->echo_interval) | ||
2104 | return 0; | ||
2105 | |||
2095 | return 1; | 2106 | return 1; |
2096 | } | 2107 | } |
2097 | 2108 | ||
@@ -2211,6 +2222,12 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2211 | tcp_ses->tcpStatus = CifsNew; | 2222 | tcp_ses->tcpStatus = CifsNew; |
2212 | ++tcp_ses->srv_count; | 2223 | ++tcp_ses->srv_count; |
2213 | 2224 | ||
2225 | if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN && | ||
2226 | volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX) | ||
2227 | tcp_ses->echo_interval = volume_info->echo_interval * HZ; | ||
2228 | else | ||
2229 | tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; | ||
2230 | |||
2214 | rc = ip_connect(tcp_ses); | 2231 | rc = ip_connect(tcp_ses); |
2215 | if (rc < 0) { | 2232 | if (rc < 0) { |
2216 | cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n"); | 2233 | cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n"); |
@@ -2240,7 +2257,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2240 | cifs_fscache_get_client_cookie(tcp_ses); | 2257 | cifs_fscache_get_client_cookie(tcp_ses); |
2241 | 2258 | ||
2242 | /* queue echo request delayed work */ | 2259 | /* queue echo request delayed work */ |
2243 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); | 2260 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); |
2244 | 2261 | ||
2245 | return tcp_ses; | 2262 | return tcp_ses; |
2246 | 2263 | ||