diff --git a/CHANGELOG b/CHANGELOG index c36017a..0e9dc51 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ - fix don't fail on empty master map. - if there's no "automount" entry in nsswitch.conf use "files" source. - add LDAP schema discovery if no schema is configured. +- add random selection as a master map entry option. 18/06/2007 autofs-5.0.2 ----------------------- diff --git a/daemon/automount.c b/daemon/automount.c index 7b79f02..4b6584a 100644 --- a/daemon/automount.c +++ b/daemon/automount.c @@ -49,9 +49,9 @@ const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */ const char *global_options; /* Global option, from command line */ -static char *pid_file = NULL; /* File in which to keep pid */ -unsigned int random_selection; /* use random policy when selecting - * which multi-mount host to mount */ +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 */ static int start_pipefd[2]; static int st_stat = 0; static int *pst_stat = &st_stat; @@ -1490,7 +1490,7 @@ int main(int argc, char *argv[]) timeout = defaults_get_timeout(); ghost = defaults_get_browse_mode(); logging = defaults_get_logging(); - random_selection = 0; + global_random_selection = 0; global_options = NULL; have_global_options = 0; foreground = 0; @@ -1531,7 +1531,7 @@ int main(int argc, char *argv[]) exit(0); case 'r': - random_selection = 1; + global_random_selection = 1; break; case 'O': diff --git a/include/automount.h b/include/automount.h index d9e4ecd..d55ba5c 100644 --- a/include/automount.h +++ b/include/automount.h @@ -448,6 +448,8 @@ struct autofs_point { enum states state; /* Current state */ int state_pipe[2]; /* State change router pipe */ unsigned dir_created; /* Directory created for this mount? */ + unsigned random_selection; /* Use random policy when selecting a + * host from which to mount */ struct autofs_point *parent; /* Owner of mounts list for submount */ pthread_mutex_t mounts_mutex; /* Protect mount lists */ pthread_cond_t mounts_cond; /* Submounts condition variable */ diff --git a/include/replicated.h b/include/replicated.h index c77cda6..3afe9f7 100644 --- a/include/replicated.h +++ b/include/replicated.h @@ -63,7 +63,7 @@ struct host { void seed_random(void); void free_host_list(struct host **); int parse_location(struct host **, const char *); -int prune_host_list(struct host **, unsigned int, const char *); +int prune_host_list(struct host **, unsigned int, const char *, unsigned int); void dump_host_list(struct host *); #endif diff --git a/lib/master_parse.y b/lib/master_parse.y index ab2895d..70b48be 100644 --- a/lib/master_parse.y +++ b/lib/master_parse.y @@ -56,6 +56,8 @@ static char *type; static char *format; static long timeout; static unsigned ghost; +extern unsigned global_random_selection; +static unsigned random_selection; static char **tmp_argv; static int tmp_argc; static char **local_argv; @@ -93,7 +95,7 @@ static int master_fprintf(FILE *, char *, ...); %token COMMENT %token MAP -%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG +%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM %token COLON COMMA NL DDASH %type map %type options @@ -174,6 +176,7 @@ line: | PATH COLON { master_notify($1); YYABORT; } | PATH OPTION { master_notify($2); YYABORT; } | PATH NILL { master_notify($2); YYABORT; } + | PATH OPT_RANDOM { 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; } @@ -543,6 +546,7 @@ daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; } | OPT_GHOST { ghost = 1; } | OPT_VERBOSE { verbose = 1; } | OPT_DEBUG { debug = 1; } + | OPT_RANDOM { random_selection = 1; } ; mount_option: OPTION @@ -600,6 +604,7 @@ static void local_init_vars(void) debug = 0; timeout = -1; ghost = defaults_get_browse_mode(); + random_selection = global_random_selection; tmp_argv = NULL; tmp_argc = 0; local_argv = NULL; @@ -790,6 +795,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne } set_mnt_logging(ap); } + entry->ap->random_selection = random_selection; /* source = master_find_map_source(entry, type, format, diff --git a/lib/master_tok.l b/lib/master_tok.l index ff69a24..013a15a 100644 --- a/lib/master_tok.l +++ b/lib/master_tok.l @@ -324,6 +324,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) -g|--ghost|-?browse { return(OPT_GHOST); } -v|--verbose { return(OPT_VERBOSE); } -d|--debug { return(OPT_DEBUG); } + -r|--random-multimount-selection { return(OPT_RANDOM); } {OPTWS}","{OPTWS} { return(COMMA); } diff --git a/man/auto.master.5.in b/man/auto.master.5.in index 249c9a7..ab5ab1e 100644 --- a/man/auto.master.5.in +++ b/man/auto.master.5.in @@ -146,6 +146,12 @@ to prevent symlinking of local NFS mounts. Nowadays it can be used to prevent bind mounting of local NFS filesystems as well. If you need to prevent bind mounting for only specific entrys in a map then this can be done by adding the "port=" mount option to the given entries. +.TP +.I "\-r, \-\-random-multimount-selection" +Enables the use of ramdom selection when choosing a host from a +list of replicated servers. This option is applied to this mount +only, overriding the global setting that may be specified on the +command line. .SH GENERAL SYSTEM DEFAULTS CONFIGURATION .P The default value of several general settings may be changed in the diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c index e7a9a8a..e4480c5 100644 --- a/modules/mount_nfs.c +++ b/modules/mount_nfs.c @@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int warn(ap->logopt, MODPREFIX "no hosts available"); return 1; } - prune_host_list(&hosts, vers, nfsoptions); + prune_host_list(&hosts, vers, nfsoptions, ap->random_selection); if (!hosts) { warn(ap->logopt, MODPREFIX "no hosts available"); diff --git a/modules/replicated.c b/modules/replicated.c index 0764d4a..e15587c 100644 --- a/modules/replicated.c +++ b/modules/replicated.c @@ -74,8 +74,6 @@ #define max(x, y) (x >= y ? x : y) #define mmax(x, y, z) (max(x, y) == x ? max(x, z) : max(y, z)) -extern unsigned int random_selection; - void seed_random(void) { int fd; @@ -392,7 +390,7 @@ static unsigned short get_port_option(const char *options) static unsigned int get_nfs_info(struct host *host, struct conn_info *pm_info, struct conn_info *rpc_info, const char *proto, unsigned int version, - const char *options) + const char *options, unsigned int random_selection) { char *have_port_opt = options ? strstr(options, "port=") : NULL; struct pmap parms; @@ -535,7 +533,9 @@ done_ver: return supported; } -static int get_vers_and_cost(struct host *host, unsigned int version, const char *options) +static int get_vers_and_cost(struct host *host, + unsigned int version, const char *options, + unsigned int random_selection) { struct conn_info pm_info, rpc_info; time_t timeout = RPC_TIMEOUT; @@ -559,7 +559,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char vers &= version; if (version & UDP_REQUESTED) { - supported = get_nfs_info(host, &pm_info, &rpc_info, "udp", vers, options); + supported = get_nfs_info(host, + &pm_info, &rpc_info, "udp", vers, + options, random_selection); if (supported) { ret = 1; host->version |= (supported << 8); @@ -567,7 +569,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char } if (version & TCP_REQUESTED) { - supported = get_nfs_info(host, &pm_info, &rpc_info, "tcp", vers, options); + supported = get_nfs_info(host, + &pm_info, &rpc_info, "tcp", vers, + options, random_selection); if (supported) { ret = 1; host->version |= supported; @@ -577,7 +581,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char return ret; } -static int get_supported_ver_and_cost(struct host *host, unsigned int version, const char *options) +static int get_supported_ver_and_cost(struct host *host, + unsigned int version, const char *options, + unsigned int random_selection) { char *have_port_opt = options ? strstr(options, "port=") : NULL; struct conn_info pm_info, rpc_info; @@ -695,7 +701,9 @@ done: return 0; } -int prune_host_list(struct host **list, unsigned int vers, const char *options) +int prune_host_list(struct host **list, + unsigned int vers, const char *options, + unsigned int random_selection) { struct host *this, *last, *first; struct host *new = NULL; @@ -734,7 +742,8 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) break; if (this->name) { - status = get_vers_and_cost(this, vers, options); + status = get_vers_and_cost(this, vers, + options, random_selection); if (!status) { if (this == first) { first = next; @@ -824,7 +833,9 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) remove_host(list, this); add_host(&new, this); } else { - status = get_supported_ver_and_cost(this, selected_version, options); + status = get_supported_ver_and_cost(this, + selected_version, options, + random_selection); if (status) { this->version = selected_version; remove_host(list, this);