All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Feist <cfeist@redhat.com>
To: autofs@linux.kernel.org
Subject: Re: [daniel@vision.ime.usp.br: Bug#304245: patch - NFS mounts occasionally fail]
Date: Mon, 18 Apr 2005 14:44:07 -0500	[thread overview]
Message-ID: <42640E07.9080305@redhat.com> (raw)
In-Reply-To: <20050417154240.GA17232@uio.no>

[-- Attachment #1: Type: text/plain, Size: 537 bytes --]

I'm currently using the attached patch which should fix this problem. We've 
tested it and it works pretty well (It also fixes a problem with local mounts 
not using --bind).

Thanks,
Chris

Steinar H. Gunderson wrote:
> Hi,
> 
> Thanks for the patch; sending upstream for evaluation.
> 
> /* Steinar */
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> autofs mailing list
> autofs@linux.kernel.org
> http://linux.kernel.org/mailman/listinfo/autofs


[-- Attachment #2: autofs-4.1.4-non-replicated-ping.patch --]
[-- Type: text/x-patch, Size: 5442 bytes --]

--- autofs-4.1.4/modules/mount_nfs.c.orig	2005-04-13 20:31:24.639009544 -0400
+++ autofs-4.1.4/modules/mount_nfs.c	2005-04-13 20:31:40.727563712 -0400
@@ -31,6 +31,7 @@
 #include <netinet/in.h>
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
+#include <ctype.h>
 
 #define MODULE_MOUNT
 #include "automount.h"
@@ -105,28 +106,116 @@ int is_local_addr(const char *host, cons
 	
 	return 1;
 }
+
+/*
+ * If the map doesn't contain a ',' and doesn't contain more than
+ * one ':' then @what is not a multimount entry.
+ */
+static int is_multimount_entry(char *what)
+{
+	return !strchr(what, ',') && (strchr(what, ':') == strrchr(what, ':'));
+}
+
+/*
+ *  Check to see if the 'host:path' or 'host' is on the local machine
+ *  Returns < 0 if there is a host lookup problem, otherwise returns 0
+ *  if it's not a local mount, and returns > 0 if it is a local mount.
+ */
+int is_local_mount(const char *hostpath)
+{
+	struct hostent *he;
+	char **haddr;
+	char *delim;
+	char *hostname;
+	int hostnamelen;
+	int local = 0;
+
+	debug(MODPREFIX "is_local_mount: %s", hostpath);
+	delim = strpbrk(hostpath,":");
+
+	if (delim) 
+		hostnamelen = delim - hostpath; 
+	else 
+		hostnamelen = strlen(hostpath);
+
+	hostname = malloc(hostnamelen+1);
+	strncpy(hostname,hostpath,hostnamelen);
+	hostname[hostnamelen] = '\0';
+	he = gethostbyname(hostname);
+	if (!he) {
+		error(MODPREFIX "host %s: lookup failure", hostname);
+		return -1;
+	}
+
+	for (haddr = he->h_addr_list; *haddr; haddr++) {
+		local = is_local_addr(hostname, *haddr, he->h_length);
+		if (local < 0) 
+			return local;
+ 		if (local) {
+			debug(MODPREFIX "host %s: is localhost",
+					hostname);
+			return local;
+		}
+	}
+	return 0;
+}
+
 /*
  * Given a mount string, return (in the same string) the
- * best mount to use based on weight/locality/rpctime
+ * best mount to use based on locality/weight/rpctime.
+ *
+ * If longtimeout is set to 0 then we only do 100 ms pings to hosts.  In
+ * the event that this fails, we call ourself recursively with the
+ * longtimeout option set to 1.  In this case we ping for up to 10s and
+ * skip logic for detecting if a localhost has been passed. (if a local
+ * host had been passed, we would have returned that mount as the best
+ * mount.  The skipping of local maps in this case is an optimization).
+ *
  * - return -1 and what = '\0' on error,
  *           1 and what = local mount path if local bind,
  *     else  0 and what = remote mount path
  */
-int get_best_mount(char *what, const char *original, int longtimeout, int skiplocal)
+int get_best_mount(char *what, const char *original, int longtimeout)
 {
 	char *p = what;
 	char *winner = NULL;
 	int winner_weight = INT_MAX, local = 0;
 	double winner_time = 0;
-	char *delim;
+	char *delim, *pstrip;
 	int sec = (longtimeout) ? 10 : 0;
 	int micros = (longtimeout) ? 0 : 100000;
+	int skiplocal = longtimeout; /* clearly local is not available */
 
 	if (!p) {
 		*what = '\0';
 		return -1;
 	}
 
+	/*
+	 *  If only one mountpoint has been passed in, we don't need to
+	 *  do anything except strip whitespace from the end of the string.
+	 */
+	if (!is_multimount_entry(p)) {
+		for (pstrip = p+strlen(p) - 1; pstrip >= p; pstrip--) 
+			if (isspace(*pstrip))
+				*pstrip = '\0';
+
+		/* Check if the host is the localhost */
+		if (is_local_mount(p)) {
+			debug(MODPREFIX "host %s: is localhost", p);
+
+			/* Strip off hostname and ':' */
+			delim = strchr(p,':');
+			while (delim && *delim != '\0') {
+				delim++;
+				*what = *delim;
+				what++;
+			}
+			return 1;
+		}
+		return 0;
+	}
+
 	while (p && *p) {
 		char *next;
 		unsigned int ping_stat = 0;
@@ -171,37 +260,17 @@ int get_best_mount(char *what, const cha
 		/* p points to a server, "next is our next parse point */
 		if (!skiplocal) {
 			/* Check if it's localhost */
-			struct hostent *he;
-			char **haddr;
-
-			he = gethostbyname(p);
-			if (!he) {
-				error(MODPREFIX "host %s: lookup failure", p);
-				p = next;
-				continue;
-			}
-
-			/* Check each host in round robin list */
-			for (haddr = he->h_addr_list; *haddr; haddr++) {
-				local = is_local_addr(p, *haddr, he->h_length);
-
-				if (local < 0)
-					continue;
-
-				if (local) {
-					winner = p;
-					break;
-				}
-			}
-			
+			local = is_local_mount(p);
 			if (local < 0) {
 				local = 0;
 				p = next;
 				continue;
 			}
 
-			if (local)
+			if (local) {
+				winner = p;
 				break;
+			}
 		}
 
 		/* ping each (or the) entry to see if it's alive. */
@@ -256,7 +325,7 @@ int get_best_mount(char *what, const cha
 	 */
 	if (!local && winner_weight == INT_MAX) {
 		/* We had more than one contender and none responded in time */
-		if (winner_time != 0 && winner_time > 500) {
+		if (winner_time == 0 || winner_time > 500) {
 			/* We've already tried a longer timeout */
 			if (!longtimeout) {
 				/* Reset string and try again */
@@ -267,7 +336,7 @@ int get_best_mount(char *what, const cha
 				      "retrying with longer timeout",
 				      original);
 
-				return get_best_mount(what, original, 1, 1);
+				return get_best_mount(what, original, 1);
 			}
 		}
 	}
@@ -395,7 +464,7 @@ int mount_mount(const char *root, const 
 		/* No colon, take this as a bind (local) entry */
 		local = 1;
 	} else if (!nosymlink) {
-		local = get_best_mount(whatstr, what, 0, 0);
+		local = get_best_mount(whatstr, what, 0);
 		if (!*whatstr) {
 			warn(MODPREFIX "no host elected");
 			return 1;

[-- Attachment #3: Type: text/plain, Size: 140 bytes --]

_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs

  parent reply	other threads:[~2005-04-18 19:44 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-04-17 15:42 [daniel@vision.ime.usp.br: Bug#304245: patch - NFS mounts occasionally fail] Steinar H. Gunderson
2005-04-17 18:18 ` Daniel Andre Vaquero
2005-04-18 13:42   ` raven
2005-04-18 19:46     ` Chris Feist
2005-04-24  9:01       ` raven
2005-04-24  9:32         ` raven
2005-04-24 12:04           ` raven
2005-04-24 16:18           ` Bug#304245: patch - NFS mounts occasionally fail Daniel Andre Vaquero
2005-04-24 18:10             ` raven
2005-04-25  0:22               ` Daniel Andre Vaquero
2005-04-25  1:27                 ` raven
2005-04-25  4:12                   ` raven
2005-04-25 14:03                     ` Daniel Andre Vaquero
2005-04-18 19:44 ` Chris Feist [this message]
2005-04-19 17:00 ` [daniel@vision.ime.usp.br: Bug#304245: patch - NFS mounts occasionally fail] raven
2005-04-19 21:06   ` Bug#304245: patch - NFS mounts occasionally fail Daniel Andre Vaquero
2005-04-20  1:02     ` Ian Kent
2005-04-20  1:32       ` Daniel Andre Vaquero
2005-04-20 11:27         ` raven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=42640E07.9080305@redhat.com \
    --to=cfeist@redhat.com \
    --cc=autofs@linux.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.