diff --git a/CHANGELOG b/CHANGELOG index cdf8ed2..bf37533 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ - check fqdn of each interface when matching export access list. - fix race when setting task done. - correct return status from do_mkdir. +- fix localhost replicated mounts not working. 4/1/2007 autofs-5.0.1 rc3 ------------------------- diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c index e859284..4063e9a 100644 --- a/modules/mount_nfs.c +++ b/modules/mount_nfs.c @@ -60,6 +60,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int { char *fullpath, buf[MAX_ERR_BUF]; struct host *this, *hosts = NULL; + unsigned int save_ghost = ap->ghost; unsigned int vers; char *nfsoptions = NULL; int len, rlen, status, err, existed = 1; @@ -183,19 +184,35 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int if (!status) existed = 0; + /* + * We need to stop the bind mount module from removing the + * mount point directory if a bind attempt fails so abuse + * the ap->ghost field for this. + */ + ap->ghost = 1; + this = hosts; while (this) { - char *loc; + char *loc, *port_opt = NULL; if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) { error(ap->logopt, MODPREFIX "warning: %s is already mounted", fullpath); - free_host_list(&hosts); break; } - if (this->proximity == PROXIMITY_LOCAL) { + /* + * If the "port" option is specified, then we don't want + * a bind mount. Use the "port" option if you want to + * avoid attempting a local bind mount, such as when + * tunneling NFS via localhost. + */ + if (nfsoptions && *nfsoptions) + port_opt = strstr(nfsoptions, "port="); + + /* Port option specified, don't try to bind */ + if (!port_opt && this->proximity == PROXIMITY_LOCAL) { /* Local host -- do a "bind" */ const char *bind_options = ro ? "ro" : ""; @@ -210,11 +227,15 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int /* Success - we're done */ if (!err) { free_host_list(&hosts); + ap->ghost = save_ghost; return 0; } - this = this->next; - continue; + /* No hostname, can't be NFS */ + if (!this->name) { + this = this->next; + continue; + } } /* Not a local host - do an NFS mount */ @@ -244,6 +265,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int msg(MODPREFIX "mounted %s on %s", loc, fullpath); free(loc); free_host_list(&hosts); + ap->ghost = save_ghost; return 0; } @@ -252,6 +274,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int } free_host_list(&hosts); + ap->ghost = save_ghost; /* If we get here we've failed to complete the mount */ diff --git a/modules/replicated.c b/modules/replicated.c index 46ea36b..cb65d82 100644 --- a/modules/replicated.c +++ b/modules/replicated.c @@ -652,12 +652,28 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) /* Use closest hosts to choose NFS version */ first = *list; + + /* Get proximity of first entry after local entries */ this = first; - proximity = this->proximity; + while (this && this->proximity == PROXIMITY_LOCAL) + this = this->next; + + proximity = PROXIMITY_LOCAL; + if (this) + proximity = this->proximity; - while (this && this->proximity == proximity) { + this = first; + while (this) { struct host *next = this->next; + if (this->proximity == PROXIMITY_LOCAL) { + this = next; + continue; + } + + if (this->proximity != proximity) + break; + if (this->name) { status = get_vers_and_cost(this, vers, options); if (!status) { @@ -674,6 +690,7 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) last = this; + /* If there are only local entries on the list, just return it. */ if (!first) return 0; @@ -722,15 +739,12 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) else if (max_count == v2_udp_count) selected_version = NFS2_UDP_SUPPORTED; - if (!selected_version) - return 0; - - /* Add hosts with selected version to new list */ - - this = first; + /* Add local and hosts with selected version to new list */ + this = *list; do { struct host *next = this->next; - if (this->version & selected_version) { + if (this->version & selected_version || + this->proximity == PROXIMITY_LOCAL) { this->version = selected_version; remove_host(list, this); add_host(&new, this); @@ -740,16 +754,17 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) /* * Now go through rest of list and check for chosen version - * and add to new list if supported. + * and add to new list if selected version is supported. */ first = last; this = first; while (this) { struct host *next = this->next; - if (!this->name) + if (!this->name) { + remove_host(list, this); add_host(&new, this); - else { + } else { status = get_supported_ver_and_cost(this, selected_version, options); if (status) { this->version = selected_version;