[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-nfsv4
Subject: [PATCH 2/2] : mount.nfs: Try v4 mounts first (Release 3)
From: Steve Dickson <SteveD () redhat ! com>
Date: 2009-09-24 18:14:58
Message-ID: 4ABBB722.5030703 () RedHat ! com
[Download RAW message or body]
commit d818d7f481a1ca67aac76c9d8d736114ffecfa74
Author: Steve Dickson <steved@redhat.com>
Date: Thu Sep 24 13:54:25 2009 -0400
Rollback the protocol version when the mount(2)
fails with EPROTONOSUPPORT (93). A side effect
of this type of rollback is the protocol specific
mount options need to be removed.
Signed-off-by: Steve Dickson <steved@redhat.com>
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
index 1dfee8a..b17947c 100644
--- a/utils/mount/parse_opt.c
+++ b/utils/mount/parse_opt.c
@@ -130,6 +130,11 @@ static int options_empty(struct mount_options *options)
return options->count == 0;
}
+int po_count(struct mount_options *options)
+{
+ return options->count;
+}
+
static void options_tail_insert(struct mount_options *options,
struct mount_option *option)
{
@@ -170,6 +175,21 @@ static void options_delete(struct mount_options *options,
}
}
+/**
+ * po_rollback - rollback the options to the give postion
+ * @options: pointer to mount options to free
+ *
+ */
+void po_rollback(struct mount_options *options, int pos)
+{
+ struct mount_option *tail = options->tail, *prev;
+
+ while (tail && pos-- && !options_empty(options)) {
+ prev = tail->prev;
+ options_delete(options, tail);
+ tail = prev;
+ }
+}
/**
* po_destroy - deallocate a group of mount options
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
index f9243c3..9095fc7 100644
--- a/utils/mount/parse_opt.h
+++ b/utils/mount/parse_opt.h
@@ -52,4 +52,6 @@ int po_rightmost(struct mount_options *,
po_found_t po_remove_all(struct mount_options *, char *);
void po_destroy(struct mount_options *);
+void po_rollback(struct mount_options *options, int pos);
+int po_count(struct mount_options *options);
#endif /* _NFS_UTILS_PARSE_OPT_H */
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 9598f47..1c7b775 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -536,6 +536,28 @@ out_err:
}
/*
+ * See if the protocol can be rolled backed to a lower
+ * version. If so, the mount options have to be stripped
+ * of any protocol specific mount options
+ */
+static inline int nfs_rollback_version(struct nfsmount_info *mi, int start)
+{
+ int curr = po_count(mi->options);
+
+ /* Can not go lower that version 2 */
+ if (mi->version < 3)
+ return 0;
+
+ /* See if a option roll back is needed */
+ if (curr > start) {
+ curr -= start;
+ po_rollback(mi->options, curr);
+ }
+
+ mi->version--;
+ return 1;
+}
+/*
* Do the mount(2) system call.
*
* Returns TRUE if successful, otherwise FALSE.
@@ -613,6 +635,8 @@ static int nfs_try_mount(struct nfsmount_info *mi)
static int nfs_is_permanent_error(int error)
{
switch (error) {
+ case EPROTONOSUPPORT:
+ /* recoverable */
case ESTALE:
case ETIMEDOUT:
case ECONNREFUSED:
@@ -633,6 +657,7 @@ static int nfsmount_fg(struct nfsmount_info *mi)
{
unsigned int secs = 1;
time_t timeout;
+ int opt_pos = 0;
timeout = nfs_parse_retry_option(mi->options,
NFS_DEF_FG_TIMEOUT_MINUTES);
@@ -641,12 +666,30 @@ static int nfsmount_fg(struct nfsmount_info *mi)
progname, ctime(&timeout));
for (;;) {
+
+ /*
+ * Make note of where the mount options are
+ * when the protocol version is not specified.
+ */
+ if (mi->version == 0)
+ opt_pos = po_count(mi->options);
+
if (nfs_try_mount(mi))
return EX_SUCCESS;
if (nfs_is_permanent_error(errno))
break;
+ /*
+ * See if the protocol version can be rolled back
+ * when the protocol was not specified.
+ */
+ if (errno == EPROTONOSUPPORT) {
+ if (opt_pos && nfs_rollback_version(mi, opt_pos))
+ continue;
+ break;
+ }
+
if (time(NULL) > timeout) {
errno = ETIMEDOUT;
break;
@@ -698,6 +741,7 @@ static int nfsmount_child(struct nfsmount_info *mi)
{
unsigned int secs = 1;
time_t timeout;
+ int opt_pos = 0;
timeout = nfs_parse_retry_option(mi->options,
NFS_DEF_BG_TIMEOUT_MINUTES);
@@ -709,12 +753,29 @@ static int nfsmount_child(struct nfsmount_info *mi)
if (secs > 120)
secs = 120;
+ /*
+ * Make note of where the mount options are
+ * when the protocol version is not specified.
+ */
+ if (mi->version == 0)
+ opt_pos = po_count(mi->options);
+
if (nfs_try_mount(mi))
return EX_SUCCESS;
if (nfs_is_permanent_error(errno))
break;
+ /*
+ * See if the protocol version can be rolled back
+ * when the protocol was not specified.
+ */
+ if (errno == EPROTONOSUPPORT) {
+ if (opt_pos && nfs_rollback_version(mi, opt_pos))
+ continue;
+ break;
+ }
+
if (time(NULL) > timeout)
break;
_______________________________________________
NFSv4 mailing list
NFSv4@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic