From d7a1070383bcf40d32c7f10e535ba443209dedef Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 6 Jun 2008 15:02:18 -0400 Subject: [PATCH] Steinar Gunderson reports: "It seems retry= is now additive with the text-based mount interface. In particular, "mount -o retry=0" still gives a two-minute timeout." Correct the bug and make retry= option parsing more robust. If parsing the retry option fails, the option is ignored and a default timeout is used. Note that currently the kernel parser ignores the "retry=" option if the value is a number. If the value contains other characters, the kernel will choke. A subsequent patch to the kernel will allow any characters as the value of the retry option (excepting of course ","). Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- utils/mount/stropts.c | 51 ++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index b2b56be..ad5bdee 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -65,6 +65,14 @@ #define NFS_MAXPATHNAME (1024) #endif +#ifndef NFS_DEF_FG_TIMEOUT_MINUTES +#define NFS_DEF_FG_TIMEOUT_MINUTES (2u) +#endif + +#ifndef NFS_DEF_BG_TIMEOUT_MINUTES +#define NFS_DEF_BG_TIMEOUT_MINUTES (10000u) +#endif + extern int nfs_mount_data_version; extern char *progname; extern int verbose; @@ -140,6 +148,32 @@ static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr) return 1; } +/* + * Obtain a retry timeout value based on the value of the "retry=" option. + * + * Returns a time_t timeout timestamp, in seconds. + */ +static time_t nfs_parse_retry_option(struct mount_options *options, + unsigned int timeout_minutes) +{ + char *retry_option, *endptr; + + retry_option = po_get(options, "retry"); + if (retry_option) { + long tmp; + + errno = 0; + tmp = strtol(retry_option, &endptr, 10); + if (errno == 0 && endptr != retry_option && tmp >= 0) + timeout_minutes = tmp; + else if (verbose) + nfs_error(_("%s: invalid retry timeout was specified; " + "using default timeout"), progname); + } + + return time(NULL) + (time_t)(timeout_minutes * 60); +} + /* * Append the 'addr=' option to the options string to pass a resolved * server address to the kernel. After a successful mount, this address @@ -557,14 +591,9 @@ static int nfsmount_fg(const char *spec, const char *node, char **extra_opts) { unsigned int secs = 1; - time_t timeout = time(NULL); - char *retry; - - timeout += 60 * 2; /* default: 2 minutes */ - retry = po_get(options, "retry"); - if (retry) - timeout += 60 * atoi(retry); + time_t timeout; + timeout = nfs_parse_retry_option(options, NFS_DEF_FG_TIMEOUT_MINUTES); if (verbose) printf(_("%s: timeout set for %s"), progname, ctime(&timeout)); @@ -634,13 +663,9 @@ static int nfsmount_child(const char *spec, const char *node, int fake, char **extra_opts) { unsigned int secs = 1; - time_t timeout = time(NULL); - char *retry; + time_t timeout; - timeout += 60 * 10000; /* default: 10,000 minutes */ - retry = po_get(options, "retry"); - if (retry) - timeout += 60 * atoi(retry); + timeout = nfs_parse_retry_option(options, NFS_DEF_BG_TIMEOUT_MINUTES); for (;;) { if (sleep(secs)) -- 2.39.5