2008-04-28 19:05:36

by Chuck Lever

[permalink] [raw]
Subject: [PATCH] text-based mount command: Fix retry= option

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 <[email protected]>
---

utils/mount/stropts.c | 51 +++++++++++++++++++++++++++++++++++++------------
1 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index cadb1f4..6630879 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;
@@ -141,6 +149,32 @@ static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
}

/*
+ * Obtain a retry timeout value based on the value of the "retry=" option.
+ *
+ * Returns a time_t timeout timestamp, in seconds.
+ */
+static time_t 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\n"), 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
* is also added to /etc/mtab for use when unmounting.
@@ -535,14 +569,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 = parse_retry_option(options, NFS_DEF_FG_TIMEOUT_MINUTES);
if (verbose)
printf(_("%s: timeout set for %s"),
progname, ctime(&timeout));
@@ -612,13 +641,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 = parse_retry_option(options, NFS_DEF_BG_TIMEOUT_MINUTES);

for (;;) {
if (sleep(secs))