Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 215

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - use weight only for server selection

From: Ian Kent <raven@themaw.net>

When using weighted server names in map entries the server response
time is also taken into consideration when selecting a server for
the target of the mount. In some cases people need to be able to
rely on selection strictly by weight. We add pseudo option
"--use-weight-only" that can be used in with master map entries
or with individual map entries to provide for this. For individual
map entries the option "no-use-weight-only" can also be used to
override the master map option.
---

 daemon/automount.c   |    8 ++--
 include/automount.h  |    3 +
 include/replicated.h |    3 +
 lib/master_parse.y   |   12 +++++--
 lib/master_tok.l     |    1 
 man/auto.master.5.in |    6 +++
 man/autofs.5         |    7 ++++
 modules/mount_nfs.c  |   15 ++++++---
 modules/parse_sun.c  |   35 +++++++++++++++++++--
 modules/replicated.c |   84 ++++++++++++++++++++++++++++++++-------------------
 10 files changed, 128 insertions(+), 46 deletions(-)


--- autofs-5.0.1.orig/daemon/automount.c
+++ autofs-5.0.1/daemon/automount.c
@@ -56,8 +56,8 @@ const char *fifodir = AUTOFS_FIFO_DIR "/
 const char *global_options;		/* Global option, from command line */
 
 static char *pid_file = NULL;		/* File in which to keep pid */
-unsigned int global_random_selection;	/* use random policy when selecting
-					 * which multi-mount host to mount */
+unsigned int global_selection_options;
+
 long global_negative_timeout = -1;
 int do_force_unlink = 0;		/* Forceably unlink mount tree at startup */
 
@@ -1861,7 +1861,7 @@ int main(int argc, char *argv[])
 	timeout = defaults_get_timeout();
 	ghost = defaults_get_browse_mode();
 	logging = defaults_get_logging();
-	global_random_selection = 0;
+	global_selection_options = 0;
 	global_options = NULL;
 	have_global_options = 0;
 	foreground = 0;
@@ -1902,7 +1902,7 @@ int main(int argc, char *argv[])
 			exit(0);
 
 		case 'r':
-			global_random_selection = 1;
+			global_selection_options |= MOUNT_FLAG_RANDOM_SELECT;
 			break;
 
 		case 'n':
--- autofs-5.0.1.orig/include/automount.h
+++ autofs-5.0.1/include/automount.h
@@ -441,6 +441,9 @@ struct kernel_mod_version {
 /* Mount being re-mounted */
 #define MOUNT_FLAG_REMOUNT		0x0008
 
+/* Use server weight only for selection */
+#define MOUNT_FLAG_USE_WEIGHT_ONLY	0x0010
+
 struct autofs_point {
 	pthread_t thid;
 	char *path;			/* Mount point name */
--- autofs-5.0.1.orig/include/replicated.h
+++ autofs-5.0.1/include/replicated.h
@@ -55,6 +55,7 @@ struct host {
 	size_t addr_len;
 	char *path;
 	unsigned int version;
+	unsigned int options;
 	unsigned int proximity;
 	unsigned int weight;
 	unsigned long cost;
@@ -64,7 +65,7 @@ struct host {
 void seed_random(void);
 void free_host_list(struct host **);
 int parse_location(unsigned, struct host **, const char *, unsigned int);
-int prune_host_list(unsigned, struct host **, unsigned int, const char *, unsigned int);
+int prune_host_list(unsigned, struct host **, unsigned int, const char *);
 void dump_host_list(struct host *);
 
 #endif
--- autofs-5.0.1.orig/lib/master_parse.y
+++ autofs-5.0.1/lib/master_parse.y
@@ -60,8 +60,9 @@ static char *format;
 static long timeout;
 static long negative_timeout;
 static unsigned ghost;
-extern unsigned global_random_selection;
+extern unsigned global_selection_options;
 static unsigned random_selection;
+static unsigned use_weight;
 static char **tmp_argv;
 static int tmp_argc;
 static char **local_argv;
@@ -100,7 +101,7 @@ static int master_fprintf(FILE *, char *
 %token COMMENT
 %token MAP
 %token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE
-%token OPT_DEBUG OPT_RANDOM
+%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT
 %token COLON COMMA NL DDASH
 %type <strtype> map
 %type <strtype> options
@@ -183,6 +184,7 @@ line:
 	| PATH OPTION { master_notify($2); YYABORT; }
 	| PATH NILL { master_notify($2); YYABORT; }
 	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
+	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
 	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
 	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
 	| PATH OPT_GHOST { master_notify($1); YYABORT; }
@@ -560,6 +562,7 @@ daemon_option: OPT_TIMEOUT NUMBER { time
 	| OPT_VERBOSE	{ verbose = 1; }
 	| OPT_DEBUG	{ debug = 1; }
 	| OPT_RANDOM	{ random_selection = 1; }
+	| OPT_USE_WEIGHT { use_weight = 1; }
 	;
 
 mount_option: OPTION
@@ -624,7 +627,8 @@ static void local_init_vars(void)
 	timeout = -1;
 	negative_timeout = 0;
 	ghost = defaults_get_browse_mode();
-	random_selection = global_random_selection;
+	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
+	use_weight = 0;
 	tmp_argv = NULL;
 	tmp_argc = 0;
 	local_argv = NULL;
@@ -810,6 +814,8 @@ int master_parse_entry(const char *buffe
 	}
 	if (random_selection)
 		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
+	if (use_weight)
+		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
 	if (negative_timeout)
 		entry->ap->negative_timeout = negative_timeout;
 
--- autofs-5.0.1.orig/lib/master_tok.l
+++ autofs-5.0.1/lib/master_tok.l
@@ -361,6 +361,7 @@ OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--
 	-g|--ghost|-?browse	{ return(OPT_GHOST); }
 	-v|--verbose		{ return(OPT_VERBOSE); }
 	-d|--debug		{ return(OPT_DEBUG); }
+	-w|--use-weight-only	{ return(OPT_USE_WEIGHT); }
 	-r|--random-multimount-selection { return(OPT_RANDOM); }
 
 	{OPTWS}","{OPTWS}	{ return(COMMA); }
--- autofs-5.0.1.orig/man/auto.master.5.in
+++ autofs-5.0.1/man/auto.master.5.in
@@ -154,6 +154,12 @@ list of replicated servers. This option 
 only, overriding the global setting that may be specified on the
 command line.
 .TP
+.I "\-w, \-\-use-weight-only"
+Use only specified weights for server selection where more than one
+server is specified in the map entry. If no server weights are given
+then each available server will be tried in the order listed, within
+proximity.
+.TP
 .I "\-n, \-\-negative\-timeout <seconds>"
 Set the timeout for caching failed key lookups. This option can be
 used to override the global default given either on the command line
--- autofs-5.0.1.orig/man/autofs.5
+++ autofs-5.0.1/man/autofs.5
@@ -50,6 +50,13 @@ is used to treat errors when mounting fi
 multiple file systems should be mounted (`multi-mounts'). If this option
 is given, no file system is mounted at all if at least one file system
 can't be mounted.
+.I -use-weight-only
+is used to make the weight the sole factor in selecting a server when multiple
+servers are present in a map entry.
+and
+.I -no-use-weight-only
+can be used to negate the option if it is present in the master map entry
+for the map but is not wanted for the given mount.
 
 .SS location
 The location specifies from where the file system is to be mounted.  In the
--- autofs-5.0.1.orig/modules/mount_nfs.c
+++ autofs-5.0.1/modules/mount_nfs.c
@@ -64,7 +64,8 @@ int mount_mount(struct autofs_point *ap,
 	struct host *this, *hosts = NULL;
 	unsigned int vers;
 	char *nfsoptions = NULL;
-	unsigned int random_selection = ap->flags & MOUNT_FLAG_RANDOM_SELECT;
+	unsigned int flags = ap->flags &
+			(MOUNT_FLAG_RANDOM_SELECT | MOUNT_FLAG_USE_WEIGHT_ONLY);
 	int len, status, err, existed = 1;
 	int nosymlink = 0;
 	int ro = 0;            /* Set if mount bind should be read-only */
@@ -113,9 +114,13 @@ int mount_mount(struct autofs_point *ap,
 			while (*comma == ' ' || *comma == '\t')
 				end--;
 
-			if (strncmp("nosymlink", cp, end - cp + 1) == 0)
+			if (strncmp("nosymlink", cp, end - cp + 1) == 0) {
 				nosymlink = 1;
-			else {
+			} else if (strncmp("no-use-weight-only", cp, end - cp + 1) == 0) {
+				flags &= ~MOUNT_FLAG_USE_WEIGHT_ONLY;
+			} else if (strncmp("use-weight-only", cp, end - cp + 1) == 0) {
+				flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
+			} else {
 				/* Check for options that also make sense
 				   with bind mounts */
 				if (strncmp("ro", cp, end - cp + 1) == 0)
@@ -136,11 +141,11 @@ int mount_mount(struct autofs_point *ap,
 	else
 		vers = NFS_VERS_MASK | NFS_PROTO_MASK;
 
-	if (!parse_location(ap->logopt, &hosts, what, random_selection)) {
+	if (!parse_location(ap->logopt, &hosts, what, flags)) {
 		info(ap->logopt, MODPREFIX "no hosts available");
 		return 1;
 	}
-	prune_host_list(ap->logopt, &hosts, vers, nfsoptions, random_selection);
+	prune_host_list(ap->logopt, &hosts, vers, nfsoptions);
 
 	if (!hosts) {
 		info(ap->logopt, MODPREFIX "no hosts available");
--- autofs-5.0.1.orig/modules/parse_sun.c
+++ autofs-5.0.1/modules/parse_sun.c
@@ -521,6 +521,7 @@ static int sun_mount(struct autofs_point
 {
 	char *fstype = "nfs";	/* Default filesystem type */
 	int nonstrict = 1;
+	int use_weight_only = ap->flags & MOUNT_FLAG_USE_WEIGHT_ONLY;
 	int rv, cur_state;
 	char *mountpoint;
 	char *what;
@@ -567,6 +568,10 @@ static int sun_mount(struct autofs_point
 					memcpy(np, cp, comma - cp + 1);
 					np += comma - cp + 1;
 				}
+			} else if (strncmp("no-use-weight-only", cp, 18) == 0) {
+				use_weight_only = -1;
+			} else if (strncmp("use-weight-only", cp, 15) == 0) {
+				use_weight_only = MOUNT_FLAG_USE_WEIGHT_ONLY;
 			} else if (strncmp("bg", cp, 2) == 0 ||
 				   strncmp("nofg", cp, 4) == 0) {
 				continue;
@@ -589,7 +594,7 @@ static int sun_mount(struct autofs_point
 	if (!strcmp(fstype, "autofs") && ctxt->macros) {
 		char *noptions = NULL;
 
-		if (!options) {
+		if (!options || *options == '\0') {
 			noptions = alloca(strlen(ctxt->macros) + 1);
 			*noptions = '\0';
 		} else {
@@ -602,7 +607,7 @@ static int sun_mount(struct autofs_point
 			}
 		}
 
-		if (noptions) {
+		if (noptions && *noptions != '\0') {
 			strcat(noptions, ctxt->macros);
 			options = noptions;
 		} else {
@@ -616,7 +621,7 @@ static int sun_mount(struct autofs_point
 
 	type = ap->entry->maps->type;
 	if (type && !strcmp(type, "hosts")) {
-		if (options) {
+		if (options && *options != '\0') {
 			int len = strlen(options);
 			int suid = strstr(options, "suid") ? 0 : 7;
 			int dev = strstr(options, "dev") ? 0 : 6;
@@ -661,6 +666,30 @@ static int sun_mount(struct autofs_point
 		memcpy(what, loc, loclen);
 		what[loclen] = '\0';
 
+		/* Add back "[no-]use-weight-only" for NFS mounts only */
+		if (use_weight_only) {
+			char *tmp;
+			int len;
+
+			if (options && *options != '\0') {
+				len = strlen(options) + 19;
+				tmp = alloca(len);
+				strcpy(tmp, options);
+				strcat(tmp, ",");
+				if (use_weight_only == MOUNT_FLAG_USE_WEIGHT_ONLY)
+					strcat(tmp, "use-weight-only");
+				else
+					strcat(tmp, "no-use-weight-only");
+			} else {
+				tmp = alloca(19);
+				if (use_weight_only == MOUNT_FLAG_USE_WEIGHT_ONLY)
+					strcpy(tmp, "use-weight-only");
+				else
+					strcpy(tmp, "no-use-weight-only");
+			}
+			options = tmp;
+		}
+
 		debug(ap->logopt, MODPREFIX
 		      "mounting root %s, mountpoint %s, "
 		      "what %s, fstype %s, options %s",
--- autofs-5.0.1.orig/modules/replicated.c
+++ autofs-5.0.1/modules/replicated.c
@@ -270,7 +270,8 @@ static unsigned int get_proximity(const 
 
 static struct host *new_host(const char *name,
 			     const char *addr, size_t addr_len,
-			     unsigned int proximity, unsigned int weight)
+			     unsigned int proximity, unsigned int weight,
+			     unsigned int options)
 {
 	struct host *new;
 	char *tmp1, *tmp2;
@@ -303,6 +304,7 @@ static struct host *new_host(const char 
 	new->addr = tmp2;
 	new->proximity = proximity;
 	new->weight = weight;
+	new->options = options;
 
 	return new;
 }
@@ -437,9 +439,11 @@ static unsigned short get_port_option(co
 static unsigned int get_nfs_info(unsigned logopt, struct host *host,
 			 struct conn_info *pm_info, struct conn_info *rpc_info,
 			 const char *proto, unsigned int version,
-			 const char *options, unsigned int random_selection)
+			 const char *options)
 {
 	char *have_port_opt = options ? strstr(options, "port=") : NULL;
+	unsigned int random_selection = host->options & MOUNT_FLAG_RANDOM_SELECT;
+	unsigned int use_weight_only = host->options & MOUNT_FLAG_USE_WEIGHT_ONLY;
 	struct pmap parms;
 	struct timeval start, end;
 	struct timezone tz;
@@ -593,7 +597,10 @@ done_ver:
 		 * Average response time to 7 significant places as
 		 * integral type.
 		 */
-		host->cost = (unsigned long) ((taken * 1000000) / count);
+		if (use_weight_only)
+			host->cost = 1;
+		else
+			host->cost = (unsigned long) ((taken * 1000000) / count);
 
 		/* Allow for user bias */
 		if (host->weight)
@@ -607,8 +614,7 @@ done_ver:
 }
 
 static int get_vers_and_cost(unsigned logopt, struct host *host,
-			     unsigned int version, const char *options,
-			     unsigned int random_selection)
+			     unsigned int version, const char *options)
 {
 	struct conn_info pm_info, rpc_info;
 	time_t timeout = RPC_TIMEOUT;
@@ -635,8 +641,7 @@ static int get_vers_and_cost(unsigned lo
 
 	if (version & UDP_REQUESTED) {
 		supported = get_nfs_info(logopt, host,
-					&pm_info, &rpc_info, "udp", vers,
-					options, random_selection);
+				   &pm_info, &rpc_info, "udp", vers, options);
 		if (supported) {
 			ret = 1;
 			host->version |= (supported << 8);
@@ -645,8 +650,7 @@ static int get_vers_and_cost(unsigned lo
 
 	if (version & TCP_REQUESTED) {
 		supported = get_nfs_info(logopt, host,
-					 &pm_info, &rpc_info, "tcp", vers,
-					 options, random_selection);
+				   &pm_info, &rpc_info, "tcp", vers, options);
 		if (supported) {
 			ret = 1;
 			host->version |= supported;
@@ -657,10 +661,11 @@ static int get_vers_and_cost(unsigned lo
 }
 
 static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
-				      unsigned int version, const char *options,
-				      unsigned int random_selection)
+				      unsigned int version, const char *options)
 {
 	char *have_port_opt = options ? strstr(options, "port=") : NULL;
+	unsigned int random_selection = host->options & MOUNT_FLAG_RANDOM_SELECT;
+	unsigned int use_weight_only = host->options & MOUNT_FLAG_USE_WEIGHT_ONLY;
 	struct conn_info pm_info, rpc_info;
 	struct pmap parms;
 	const char *proto;
@@ -773,7 +778,10 @@ done:
 
 	if (status) {
 		/* Response time to 7 significant places as integral type. */
-		host->cost = (unsigned long) (taken * 1000000);
+		if (use_weight_only)
+			host->cost = 1;
+		else
+			host->cost = (unsigned long) (taken * 1000000);
 
 		/* Allow for user bias */
 		if (host->weight)
@@ -788,8 +796,7 @@ done:
 }
 
 int prune_host_list(unsigned logopt, struct host **list,
-		    unsigned int vers, const char *options,
-		    unsigned int random_selection)
+		    unsigned int vers, const char *options)
 {
 	struct host *this, *last, *first;
 	struct host *new = NULL;
@@ -810,6 +817,7 @@ int prune_host_list(unsigned logopt, str
 	this = first;
 	while (this && this->proximity == PROXIMITY_LOCAL)
 		this = this->next;
+	first = this;
 
 	/*
 	 * Check for either a list containing only proximity local hosts
@@ -821,8 +829,6 @@ int prune_host_list(unsigned logopt, str
 		return 1;
 
 	proximity = this->proximity;
-	first = this;
-	this = first;
 	while (this) {
 		struct host *next = this->next;
 
@@ -830,8 +836,7 @@ int prune_host_list(unsigned logopt, str
 			break;
 
 		if (this->name) {
-			status = get_vers_and_cost(logopt, this, vers,
-						   options, random_selection);
+			status = get_vers_and_cost(logopt, this, vers, options);
 			if (!status) {
 				if (this == first) {
 					first = next;
@@ -940,8 +945,7 @@ int prune_host_list(unsigned logopt, str
 			add_host(&new, this);
 		} else {
 			status = get_supported_ver_and_cost(logopt, this,
-						selected_version, options,
-						random_selection);
+						selected_version, options);
 			if (status) {
 				this->version = selected_version;
 				remove_host(list, this);
@@ -958,7 +962,7 @@ int prune_host_list(unsigned logopt, str
 }
 
 static int add_host_addrs(struct host **list, const char *host,
-			  unsigned int weight, unsigned int random_selection)
+			  unsigned int weight, unsigned int options)
 {
 	struct hostent he;
 	struct hostent *phe = &he;
@@ -979,15 +983,25 @@ static int add_host_addrs(struct host **
 		 * We can't use PROXIMITY_LOCAL or we won't perform an RPC ping
 		 * to remove hosts that may be down.
 		 */
-		if (random_selection)
+		if (options & MOUNT_FLAG_RANDOM_SELECT)
 			prx = PROXIMITY_SUBNET;
-		else
+		else {
 			prx = get_proximity(thost, sizeof(saddr.sin_addr));
+			/*
+			 * If we want the weight to be the determining factor
+			 * when selecting a host then all hosts must have the
+			 * same proximity. However, if this is the local machine
+			 * it should always be used since it is certainly available.
+			 */
+			if (prx != PROXIMITY_LOCAL &&
+			   (options & MOUNT_FLAG_USE_WEIGHT_ONLY))
+				prx = PROXIMITY_SUBNET;
+		}
 
 		if (prx == PROXIMITY_ERROR)
 			return 0;
 
-		if (!(new = new_host(host, thost, sizeof(saddr.sin_addr), prx, weight)))
+		if (!(new = new_host(host, thost, sizeof(saddr.sin_addr), prx, weight, options)))
 			return 0;
 
 		if (!add_host(list, new))
@@ -1020,16 +1034,26 @@ static int add_host_addrs(struct host **
 		 * We can't use PROXIMITY_LOCAL or we won't perform an RPC ping
 		 * to remove hosts that may be down.
 		 */
-		if (random_selection)
+		if (options & MOUNT_FLAG_RANDOM_SELECT)
 			prx = PROXIMITY_SUBNET;
-		else
+		else {
 			prx = get_proximity(*haddr, phe->h_length);
+			/*
+			 * If we want the weight to be the determining factor
+			 * when selecting a host then all hosts must have the
+			 * same proximity. However, if this is the local machine
+			 * it should always be used since it is certainly available.
+			 */
+			if (prx != PROXIMITY_LOCAL &&
+			   (options & MOUNT_FLAG_USE_WEIGHT_ONLY))
+				prx = PROXIMITY_SUBNET;
+		}
 
 		if (prx == PROXIMITY_ERROR)
 			return 0;
 
 		memcpy(&tt, *haddr, sizeof(struct in_addr));
-		if (!(new = new_host(host, *haddr, phe->h_length, prx, weight)))
+		if (!(new = new_host(host, *haddr, phe->h_length, prx, weight, options)))
 			return 0;
 
 		if (!add_host(list, new)) {
@@ -1096,7 +1120,7 @@ static int add_local_path(struct host **
 }
 
 int parse_location(unsigned logopt, struct host **hosts,
-		   const char *list, unsigned int random_selection)
+		   const char *list, unsigned int options)
 {
 	char *str, *p, *delim;
 	unsigned int empty = 1;
@@ -1151,7 +1175,7 @@ int parse_location(unsigned logopt, stru
 				}
 
 				if (p != delim) {
-					if (!add_host_addrs(hosts, p, weight, random_selection)) {
+					if (!add_host_addrs(hosts, p, weight, options)) {
 						if (empty) {
 							p = next;
 							continue;
@@ -1173,7 +1197,7 @@ int parse_location(unsigned logopt, stru
 				*delim = '\0';
 				next = delim + 1;
 
-				if (!add_host_addrs(hosts, p, weight, random_selection)) {
+				if (!add_host_addrs(hosts, p, weight, options)) {
 					p = next;
 					continue;
 				}