[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