diff --git a/autofs-5.0.5-add-autofs_ldap_auth_conf-man-page.patch b/autofs-5.0.5-add-autofs_ldap_auth_conf-man-page.patch new file mode 100644 index 0000000..cfc36ab --- /dev/null +++ b/autofs-5.0.5-add-autofs_ldap_auth_conf-man-page.patch @@ -0,0 +1,246 @@ +autofs-5.0.5 - add autofs_ldap_auth.conf man page + +From: Ian Kent + + +--- + + CHANGELOG | 1 + man/auto.master.5.in | 3 + + man/autofs.5 | 1 + man/autofs.8.in | 1 + man/autofs_ldap_auth.conf.5.in | 93 +++++++++++++++++++++++++++++++++++++++++ + man/automount.8 | 1 + samples/autofs_ldap_auth.conf | 64 ---------------------------- + 7 files changed, 101 insertions(+), 63 deletions(-) + create mode 100644 man/autofs_ldap_auth.conf.5.in + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -29,6 +29,7 @@ + - add locality as valid ldap master map attribute fix. + - add simple bind authentication. + - fix master map source server unavailable handling. ++- add autofs_ldap_auth.conf man page. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/man/auto.master.5.in ++++ autofs-5.0.5/man/auto.master.5.in +@@ -365,6 +365,8 @@ and set the location of the client certi + in the per-user configuration. The location of these files and the configuration + entry requirements is system dependent so the documentation for your + installation will need to be consulted to get further information. ++.P ++See \fBautofs_ldap_auth.conf\fP(5) for more information. + .SH EXAMPLE + .sp + .RS +.2i +@@ -399,6 +401,7 @@ configuration will be used to locate the + .BR automount (8), + .BR autofs (5), + .BR autofs (8). ++.BR autofs_ldap_auth.conf (5) + .SH AUTHOR + This manual page was written by Christoph Lameter , + for the Dean GNU/Linux system. Edited by and +--- autofs-5.0.5.orig/man/autofs.5 ++++ autofs-5.0.5/man/autofs.5 +@@ -229,6 +229,7 @@ and LDAP only. + .BR auto.master (5), + .BR autofs (8), + .BR mount (8). ++.BR autofs_ldap_auth.conf (5) + .SH AUTHOR + This manual page was written by Christoph Lameter , + for the Debian GNU/Linux system. Edited by H. Peter Avian +--- autofs-5.0.5.orig/man/autofs.8.in ++++ autofs-5.0.5/man/autofs.8.in +@@ -50,6 +50,7 @@ will display the status of, + .BR automount (8), + .BR autofs (5), + .BR auto.master (5). ++.BR autofs_ldap_auth.conf (5) + .SH AUTHOR + This manual page was written by Christoph Lameter , + for the Debi GNU/Linux system. Edited by H. Peter Anvin +--- /dev/null ++++ autofs-5.0.5/man/autofs_ldap_auth.conf.5.in +@@ -0,0 +1,93 @@ ++.\" t ++.TH AUTOFS_LDAP_AUTH.CONF 5 "19 Feb 2010" ++.SH NAME ++autofs_ldap_auth.conf \- autofs LDAP authentication configuration ++.SH "DESCRIPTION" ++LDAP authenticated binds, TLS encrypted connections and certification ++may be used by setting appropriate values in the autofs authentication ++configuration file and configuring the LDAP client with appropriate ++settings. The default location of this file is ++.nh ++.BR @@autofsmapdir@@/autofs_ldap_auth.conf . ++.hy ++If this file exists it will be used to establish whether TLS or authentication ++should be used. ++.P ++An example of this file is: ++.sp ++.RS +.2i ++.ta 1.0i ++.nf ++ ++ ++.fi ++.RE ++.sp ++If TLS encryption is to be used the location of the Certificate Authority ++certificate must be set within the LDAP client configuration in ++order to validate the server certificate. If, in addition, a certified ++connection is to be used then the client certificate and private key file ++locations must also be configured within the LDAP client. ++.SH "OPTIONS" ++This files contains a single XML element, as shown in the example above, with ++several attributes. ++.TP ++The possible attributes are: ++.TP ++\fBusetls="yes"|"no"\fP ++Determines whether an encrypted connection to the ldap server ++should be attempted. ++.TP ++\fBtlsrequired="yes"|"no"\fP ++This flag tells whether the ldap connection must be encrypted. If set to "yes", ++the automounter will fail to start if an encrypted connection cannot be ++established. ++.TP ++\fBauthrequired="yes"|"no"|"autodetect"|"simple"\fP ++This option tells whether an authenticated connection to the ldap server is ++required in order to perform ldap queries. If the flag is set to yes, only ++sasl authenticated connections will be allowed. If it is set to no then ++authentication is not needed for ldap server connections. If it is set to ++autodetect then the ldap server will be queried to establish a suitable sasl ++authentication mechanism. If no suitable mechanism can be found, connections ++to the ldap server are made without authentication. Finally, if it is set to ++simple, then simple authentication will be used instead of SASL. ++.TP ++\fBauthtype="GSSAPI"|"LOGIN"|"PLAIN"|"ANONYMOUS"|"DIGEST-MD5"\fP ++This attribute can be used to specify a preferred authentication mechanism. ++ In normal operations, the automounter will attempt to authenticate to the ++ldap server using the list of supportedSASLmechanisms obtained from the ++directory server. Explicitly setting the authtype will bypass this selection ++and only try the mechanism specified. ++.TP ++\fBuser=""\fP ++This attribute holds the authentication identity used by authentication ++mechanisms that require it. Legal values for this attribute include any ++printable characters that can be used by the selected authentication ++mechanism. ++.TP ++\fBsecret=""\fP ++This attribute holds the secret used by authentication mechanisms that ++require it. Legal values for this attribute include any printable ++characters that can be used by the selected authentication mechanism. ++.TP ++\fBclientprinc=""\fP ++When using GSSAPI authentication, this attribute is consulted to determine ++the principal name to use when authenticating to the directory server. By ++default, this will be set to "autofsclient/@. ++.TP ++\fBcredentialcache=""\fP ++When using GSSAPI authentication, this attribute can be used to specify an ++externally configured credential cache that is used during authentication. ++By default, autofs will setup a memory based credential cache. ++.SH "SEE ALSO" ++.BR auto.master (5), ++.SH AUTHOR ++This manual page was written by Ian Kent . +--- autofs-5.0.5.orig/man/automount.8 ++++ autofs-5.0.5/man/automount.8 +@@ -152,6 +152,7 @@ constructed has been detached from the m + .BR autofs (8), + .BR auto.master (5), + .BR mount (8). ++.BR autofs_ldap_auth.conf (5) + .SH BUGS + Don't know, I've fixed everything I know about. + +--- autofs-5.0.5.orig/samples/autofs_ldap_auth.conf ++++ autofs-5.0.5/samples/autofs_ldap_auth.conf +@@ -1,69 +1,7 @@ + + + + + +We return a space separated list of dc servers from get_dc_list() but the +GSSAPI code needs an individual server in the uri to function correctly. + +Change the logic in find_server() and do_reconnect() to attempt a connection +to each dc server individually. +--- + + CHANGELOG | 1 + modules/lookup_ldap.c | 103 +++++++++++++++++++++++++++++--------------------- + 2 files changed, 62 insertions(+), 42 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -40,6 +40,7 @@ + - fix null cache race. + - fix cache_init() on source re-read. + - fix mapent becomes negative during lookup. ++- check each dc server individually. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/modules/lookup_ldap.c ++++ autofs-5.0.5/modules/lookup_ldap.c +@@ -615,23 +615,43 @@ static LDAP *connect_to_server(unsigned + return ldap; + } + ++static LDAP *find_dc_server(unsigned logopt, const char *uri, struct lookup_context *ctxt) ++{ ++ char *str, *tok, *ptr = NULL; ++ LDAP *ldap = NULL; ++ ++ str = strdup(uri); ++ if (!str) ++ return NULL; ++ ++ tok = strtok_r(str, " ", &ptr); ++ while (tok) { ++ const char *this = (const char *) tok; ++ debug(logopt, "trying server uri %s", this); ++ ldap = connect_to_server(logopt, this, ctxt); ++ if (ldap) { ++ info(logopt, "connected to uri %s", this); ++ free(str); ++ return ldap; ++ } ++ tok = strtok_r(NULL, " ", &ptr); ++ } ++ ++ free(str); ++ ++ return NULL; ++} ++ + static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; + struct ldap_uri *this; + struct list_head *p, *first; +- struct dclist *dclist = NULL; ++ struct dclist *dclist; + char *uri = NULL; + + uris_mutex_lock(ctxt); +- if (ctxt->dclist) { +- dclist = ctxt->dclist; +- if (ctxt->dclist->expire < time(NULL)) { +- free_dclist(ctxt->dclist); +- ctxt->dclist = NULL; +- dclist = NULL; +- } +- } ++ dclist = ctxt->dclist; + if (!ctxt->uri) + first = ctxt->uris; + else +@@ -648,9 +668,16 @@ static LDAP *find_server(unsigned logopt + continue; + } + this = list_entry(p, struct ldap_uri, list); +- if (!strstr(this->uri, ":///")) ++ if (!strstr(this->uri, ":///")) { + uri = strdup(this->uri); +- else { ++ debug(logopt, "trying server uri %s", uri); ++ ldap = connect_to_server(logopt, uri, ctxt); ++ if (ldap) { ++ info(logopt, "connected to uri %s", uri); ++ free(uri); ++ break; ++ } ++ } else { + if (dclist) + uri = strdup(dclist->uri); + else { +@@ -663,21 +690,11 @@ static LDAP *find_server(unsigned logopt + dclist = tmp; + uri = strdup(dclist->uri); + } +- } +- if (!uri) { +- if (dclist) { +- free_dclist(dclist); +- dclist = NULL; ++ ldap = find_dc_server(logopt, uri, ctxt); ++ if (ldap) { ++ free(uri); ++ break; + } +- p = p->next; +- continue; +- } +- debug(logopt, "trying server uri %s", uri); +- ldap = connect_to_server(logopt, uri, ctxt); +- if (ldap) { +- info(logopt, "connected to uri %s", uri); +- free(uri); +- break; + } + free(uri); + uri = NULL; +@@ -708,7 +725,7 @@ static LDAP *find_server(unsigned logopt + + static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + { +- LDAP *ldap; ++ LDAP *ldap = NULL; + char *uri; + + if (ctxt->server || !ctxt->uris) { +@@ -723,25 +740,29 @@ static LDAP *do_reconnect(unsigned logop + return ldap; + } + ++ if (ctxt->dclist) { ++ ldap = find_dc_server(logopt, ctxt->dclist->uri, ctxt); ++ if (ldap) ++ return ldap; ++ } ++ + uris_mutex_lock(ctxt); +- if (ctxt->dclist) +- uri = strdup(ctxt->dclist->uri); +- else if (ctxt->uri) +- uri = strdup(ctxt->uri->uri); +- else { ++ if (ctxt->dclist) { ++ if (!ldap || ctxt->dclist->expire < time(NULL)) { ++ free_dclist(ctxt->dclist); ++ ctxt->dclist = NULL; ++ } ++ /* Make sure we don't skip the domain spec */ ++ ctxt->uri = NULL; + uris_mutex_unlock(ctxt); + goto find_server; + } + uris_mutex_unlock(ctxt); + +- if (!uri) { +- char buf[MAX_ERR_BUF]; +- char *estr = strerror_r(errno, buf, sizeof(buf)); +- crit(logopt, MODPREFIX "strdup: %s", estr); +- return NULL; +- } ++ if (!ctxt->uri) ++ goto find_server; + +- ldap = do_connect(logopt, uri, ctxt); ++ ldap = do_connect(logopt, ctxt->uri->uri, ctxt); + #ifdef WITH_SASL + /* + * Dispose of the sasl authentication connection and try the +@@ -752,19 +773,17 @@ static LDAP *do_reconnect(unsigned logop + ldap = connect_to_server(logopt, uri, ctxt); + } + #endif +- free(uri); +- + if (ldap) + return ldap; + + /* Failed to connect, try to find a new server */ + ++find_server: + #ifdef WITH_SASL + autofs_sasl_dispose(ctxt); + #endif + +-find_server: +- /* Current server failed connect, try the rest */ ++ /* Current server failed, try the rest or dc connection */ + ldap = find_server(logopt, ctxt); + if (!ldap) + error(logopt, MODPREFIX "failed to find available server"); diff --git a/autofs-5.0.5-dont-check-null-cache-on-expire.patch b/autofs-5.0.5-dont-check-null-cache-on-expire.patch new file mode 100644 index 0000000..eae102a --- /dev/null +++ b/autofs-5.0.5-dont-check-null-cache-on-expire.patch @@ -0,0 +1,48 @@ +autofs-5.0.5 - dont check null cache on expire + +From: Ian Kent + +When expiring an entry there is no need to check the null map +entry cache. If we have a mount then it must have been done at +some point when the entry was not a nulled so it still needs +to be expired. Remove this check. +--- + + CHANGELOG | 1 + + daemon/automount.c | 9 --------- + 2 files changed, 1 insertion(+), 9 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -36,6 +36,7 @@ + - fix remount locking. + - fix wildcard map entry match. + - fix parse_sun() module init. ++- dont check null cache on expire. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/automount.c ++++ autofs-5.0.5/daemon/automount.c +@@ -526,20 +526,11 @@ static int umount_subtree_mounts(struct + it also tries to umount path itself */ + int umount_multi(struct autofs_point *ap, const char *path, int incl) + { +- struct mapent_cache *nc; + int is_autofs_fs; + int left; + + debug(ap->logopt, "path %s incl %d", path, incl); + +- nc = ap->entry->master->nc; +- cache_readlock(nc); +- if (cache_lookup_distinct(nc, path)) { +- cache_unlock(nc); +- return 0; +- } +- cache_unlock(nc); +- + is_autofs_fs = 0; + if (master_find_submount(ap, path)) + is_autofs_fs = 1; diff --git a/autofs-5.0.5-dont-hold-lock-for-simple-mounts.patch b/autofs-5.0.5-dont-hold-lock-for-simple-mounts.patch new file mode 100644 index 0000000..d2b933d --- /dev/null +++ b/autofs-5.0.5-dont-hold-lock-for-simple-mounts.patch @@ -0,0 +1,117 @@ +autofs-5.0.5 - don't hold lock for simple mounts + +From: Ian Kent + +A map entry that depends on another map entry in the "same" map cannot +be allowed in all cases. In particular, multi-mount entries must not +change during mount operations so the internal map entry cache must +remain locked during the mount. This is because, during the mount, we +must consult the map and possibly update the internal cache entry to +ensure we are using the most up to date mount information. + +This isn't the case for non multi-mount map entries but autofs didn't +allow for this, which is the issue this patch addresses. +--- + + CHANGELOG | 1 + + modules/parse_sun.c | 41 +++++++++++++++++------------------------ + 2 files changed, 18 insertions(+), 24 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -32,6 +32,7 @@ + - add autofs_ldap_auth.conf man page. + - fix random selection for host on different network. + - make redhat init script more lsb compliant. ++- don't hold lock for simple mounts. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/modules/parse_sun.c ++++ autofs-5.0.5/modules/parse_sun.c +@@ -1136,19 +1136,6 @@ static int mount_subtree(struct autofs_p + + rv = 0; + +- if (!me || !me->multi) { +- int loclen = strlen(loc); +- int namelen = strlen(name); +- const char *root = ap->path; +- +- if (!strcmp(ap->path, "/-")) +- root = name; +- +- rv = sun_mount(ap, root, name, namelen, loc, loclen, options, ctxt); +- +- goto done; +- } +- + mm = me->multi; + mm_key = mm->key; + move = MOUNT_MOVE_NONE; +@@ -1294,7 +1281,6 @@ static int mount_subtree(struct autofs_p + if (rv > 0) + return rv; + +-done: + /* + * Convert fail on nonstrict, non-empty multi-mount + * to success +@@ -1622,17 +1608,25 @@ int parse_mount(struct autofs_point *ap, + * it's already been parsed (above) and any option string + * has already been stripped so just use the remainder. + */ ++ cache_readlock(mc); + if (*name == '/' && + (me = cache_lookup_distinct(mc, name)) && me->multi) { + loc = strdup(p); + if (!loc) { + free(options); ++ cache_unlock(mc); + warn(ap->logopt, MODPREFIX "out of memory"); + return 1; + } +- loclen = strlen(p); +- goto mount_it; ++ cache_multi_writelock(me); ++ rv = mount_subtree(ap, me, name, loc, options, ctxt); ++ cache_multi_unlock(me); ++ cache_unlock(mc); ++ free(loc); ++ free(options); ++ return rv; + } ++ cache_unlock(mc); + + l = chunklen(p, check_colon(p)); + loc = dequote(p, l, ap->logopt); +@@ -1716,21 +1710,20 @@ int parse_mount(struct autofs_point *ap, + MODPREFIX "entry %s is empty!", name); + return 1; + } +-mount_it: ++ + debug(ap->logopt, + MODPREFIX "core of entry: options=%s, loc=%.*s", + options, loclen, loc); + +- cache_readlock(mc); +- cache_multi_writelock(me); +- +- rv = mount_subtree(ap, me, name, loc, options, ctxt); ++ if (!strcmp(ap->path, "/-")) ++ rv = sun_mount(ap, name, name, name_len, ++ loc, loclen, options, ctxt); ++ else ++ rv = sun_mount(ap, ap->path, name, name_len, ++ loc, loclen, options, ctxt); + + free(loc); + free(options); +- +- cache_multi_unlock(me); +- cache_unlock(mc); + pthread_setcancelstate(cur_state, NULL); + } + return rv; diff --git a/autofs-5.0.5-fix-cache_init-on-source-re-read.patch b/autofs-5.0.5-fix-cache_init-on-source-re-read.patch new file mode 100644 index 0000000..1100132 --- /dev/null +++ b/autofs-5.0.5-fix-cache_init-on-source-re-read.patch @@ -0,0 +1,90 @@ +autofs-5.0.5 - fix cache_init() on source re-read + +From: Ian Kent + +The master map entry cache is released and re-allocated for each +map source upon master map re-read. This is done without holding +the master map entry write lock and, when there are many master +map entries, could lead to a race because other activities can be +underway concurrently. In this case then we must either use +additional expensive exclusive locking or not do the cache +re-recreate. + +So the question really becomes what do we have to gain by releasing +and re-creating the cache since we spend a fairly significant amount +of effort on pruning stale entries during ongoing operation already. + +This patch moves the allocation of the map entry cache (belonging to +the map source) into the function used to add the map source to the +master map entry and does not release and re-create the cache if the +source already exists for the given master map entry. +--- + + CHANGELOG | 1 + + lib/master.c | 6 ++++++ + lib/master_parse.y | 10 ---------- + modules/mount_autofs.c | 8 -------- + 4 files changed, 7 insertions(+), 18 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -38,6 +38,7 @@ + - fix parse_sun() module init. + - dont check null cache on expire. + - fix null cache race. ++- fix cache_init() on source re-read. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/lib/master.c ++++ autofs-5.0.5/lib/master.c +@@ -188,6 +188,12 @@ master_add_map_source(struct master_mape + source->argc = argc; + source->argv = tmpargv; + ++ source->mc = cache_init(entry->ap, source); ++ if (!source->mc) { ++ master_free_map_source(source, 0); ++ return NULL; ++ } ++ + master_source_writelock(entry); + + if (!entry->maps) { +--- autofs-5.0.5.orig/lib/master_parse.y ++++ autofs-5.0.5/lib/master_parse.y +@@ -830,16 +830,6 @@ int master_parse_entry(const char *buffe + return 0; + } + +- if (!source->mc) { +- source->mc = cache_init(entry->ap, source); +- if (!source->mc) { +- error(m_logopt, "failed to init source cache"); +- if (new) +- master_free_mapent(new); +- local_free_vars(); +- return 0; +- } +- } + source->master_line = lineno; + + entry->age = age; +--- autofs-5.0.5.orig/modules/mount_autofs.c ++++ autofs-5.0.5/modules/mount_autofs.c +@@ -200,14 +200,6 @@ int mount_mount(struct autofs_point *ap, + } + free_map_type_info(info); + +- source->mc = cache_init(entry->ap, source); +- if (!source->mc) { +- error(ap->logopt, MODPREFIX "failed to init source cache"); +- master_free_map_source(source, 0); +- master_free_mapent(entry); +- return 1; +- } +- + mounts_mutex_lock(ap); + + if (handle_mounts_startup_cond_init(&suc)) { diff --git a/autofs-5.0.5-fix-master-map-source-server-unavialable-handling.patch b/autofs-5.0.5-fix-master-map-source-server-unavialable-handling.patch new file mode 100644 index 0000000..6dc2a99 --- /dev/null +++ b/autofs-5.0.5-fix-master-map-source-server-unavialable-handling.patch @@ -0,0 +1,129 @@ +autofs-5.0.5 - fix master map source server unavailable handling + +From: Ian Kent + +If we get an NSS_STATUS_UNAVAIL from any server when trying to read +the master map we have no choice but to not update mounted automounts +because we can't know what entries may have come from the server that +isn't avialable. So we leave everything the way it is and wait until +the next re-read to update our mounts. +--- + + CHANGELOG | 1 + + daemon/automount.c | 5 +++-- + daemon/lookup.c | 9 +++++++++ + include/master.h | 1 + + lib/master.c | 9 ++++++++- + modules/lookup_file.c | 2 -- + 6 files changed, 22 insertions(+), 5 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -28,6 +28,7 @@ + - add locality as valid ldap master map attribute. + - add locality as valid ldap master map attribute fix. + - add simple bind authentication. ++- fix master map source server unavailable handling. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/automount.c ++++ autofs-5.0.5/daemon/automount.c +@@ -1478,7 +1478,6 @@ static void handle_mounts_cleanup(void * + master_free_mapent_sources(ap->entry, 1); + master_free_mapent(ap->entry); + } +- master_mutex_unlock(); + + if (clean) { + if (rmdir(path) == -1) { +@@ -1497,7 +1496,9 @@ static void handle_mounts_cleanup(void * + */ + if (!submount) + pthread_kill(state_mach_thid, SIGTERM); +- ++ ++ master_mutex_unlock(); ++ + return; + } + +--- autofs-5.0.5.orig/daemon/lookup.c ++++ autofs-5.0.5/daemon/lookup.c +@@ -157,6 +157,9 @@ int lookup_nss_read_master(struct master + result = do_read_master(master, "file", age); + } + ++ if (result == NSS_STATUS_UNAVAIL) ++ master->read_fail = 1; ++ + return !result; + } else { + char *name = master->name; +@@ -194,6 +197,9 @@ int lookup_nss_read_master(struct master + result = do_read_master(master, source, age); + master->name = name; + ++ if (result == NSS_STATUS_UNAVAIL) ++ master->read_fail = 1; ++ + return !result; + } + } +@@ -248,6 +254,9 @@ int lookup_nss_read_master(struct master + continue; + } + ++ if (result == NSS_STATUS_UNAVAIL) ++ master->read_fail = 1; ++ + status = check_nss_result(this, result); + if (status >= 0) { + free_sources(&nsslist); +--- autofs-5.0.5.orig/include/master.h ++++ autofs-5.0.5/include/master.h +@@ -56,6 +56,7 @@ struct master { + unsigned int recurse; + unsigned int depth; + unsigned int reading; ++ unsigned int read_fail; + unsigned int default_ghost; + unsigned int default_logging; + unsigned int default_timeout; +--- autofs-5.0.5.orig/lib/master.c ++++ autofs-5.0.5/lib/master.c +@@ -794,6 +794,7 @@ struct master *master_new(const char *na + master->recurse = 0; + master->depth = 0; + master->reading = 0; ++ master->read_fail = 0; + master->default_ghost = ghost; + master->default_timeout = timeout; + master->default_logging = defaults_get_logging(); +@@ -821,7 +822,13 @@ int master_read_master(struct master *ma + master_init_scan(); + + lookup_nss_read_master(master, age); +- master_mount_mounts(master, age, readall); ++ if (!master->read_fail) ++ master_mount_mounts(master, age, readall); ++ else { ++ master->read_fail = 0; ++ if (!readall) ++ master_mount_mounts(master, age, readall); ++ } + + master_mutex_lock(); + +--- autofs-5.0.5.orig/modules/lookup_file.c ++++ autofs-5.0.5/modules/lookup_file.c +@@ -656,8 +656,6 @@ int lookup_read_map(struct autofs_point + if (!status) { + warn(ap->logopt, + "failed to read included map %s", key); +- fclose(f); +- return NSS_STATUS_UNAVAIL; + } + } else { + char *s_key; diff --git a/autofs-5.0.5-fix-negative-cache-included-map-lookup.patch b/autofs-5.0.5-fix-negative-cache-included-map-lookup.patch new file mode 100644 index 0000000..09319ef --- /dev/null +++ b/autofs-5.0.5-fix-negative-cache-included-map-lookup.patch @@ -0,0 +1,49 @@ +autofs-5.0.5 - fix negative cache included map lookup + +From: Ian Kent + +If we are looking up a mount from multiple included map sources we +can't update the negative cache until we have looked at all sources. +If we don't postpone the negative cache update we will get a false +negative on a subsequent lookups. + +Also clean up "not found" message. +--- + + CHANGELOG | 1 + + daemon/lookup.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -41,6 +41,7 @@ + - fix cache_init() on source re-read. + - fix mapent becomes negative during lookup. + - check each dc server individually. ++- fix negative cache included map lookup. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/lookup.c ++++ autofs-5.0.5/daemon/lookup.c +@@ -813,6 +813,10 @@ static void update_negative_cache(struct + struct map_source *map; + struct mapent *me; + ++ /* Don't update negative cache for included maps */ ++ if (source && source->depth) ++ return; ++ + /* Have we recorded the lookup fail for negative caching? */ + me = lookup_source_mapent(ap, name, LKP_DISTINCT); + if (me) +@@ -823,7 +827,7 @@ static void update_negative_cache(struct + cache_unlock(me->mc); + else { + /* Notify only once after fail */ +- error(ap->logopt, "key \"%s\" not found in map.", name); ++ logmsg("key \"%s\" not found in map source(s).", name); + + /* Doesn't exist in any source, just add it somewhere */ + if (source) diff --git a/autofs-5.0.5-fix-null-cache-race.patch b/autofs-5.0.5-fix-null-cache-race.patch new file mode 100644 index 0000000..5454b26 --- /dev/null +++ b/autofs-5.0.5-fix-null-cache-race.patch @@ -0,0 +1,187 @@ +autofs-5.0.5 - fix null cache race + +From: Ian Kent + +The null map entry cache scope is across the entire master map but +it is used by individual master map entries during master map re-read +and subsequest updates resulting form it. The current null cache locking +doesn't properly account for this. + +To resolve this, when we re-read the master, map we need to block +access to the null cache until the master map has been read and the +null cache updated. +--- + + CHANGELOG | 1 + + daemon/automount.c | 4 +++- + include/automount.h | 1 + + lib/cache.c | 33 ++++++++++++++++++++++++++------- + lib/master.c | 27 ++++++++++++++++++++------- + lib/master_parse.y | 5 ----- + 6 files changed, 51 insertions(+), 20 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -37,6 +37,7 @@ + - fix wildcard map entry match. + - fix parse_sun() module init. + - dont check null cache on expire. ++- fix null cache race. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/automount.c ++++ autofs-5.0.5/daemon/automount.c +@@ -1273,14 +1273,16 @@ static int do_hup_signal(struct master * + if (status) + fatal(status); + ++ master_mutex_lock(); + if (master->reading) { + status = pthread_mutex_unlock(&mrc.mutex); + if (status) + fatal(status); ++ master_mutex_unlock(); + return 1; + } +- + master->reading = 1; ++ master_mutex_unlock(); + + status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL); + if (status) { +--- autofs-5.0.5.orig/include/automount.h ++++ autofs-5.0.5/include/automount.h +@@ -194,6 +194,7 @@ void cache_multi_writelock(struct mapent + void cache_multi_unlock(struct mapent *me); + int cache_delete_offset_list(struct mapent_cache *mc, const char *key); + void cache_release(struct map_source *map); ++void cache_clean_null_cache(struct mapent_cache *mc); + void cache_release_null_cache(struct master *master); + struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me); + char *cache_get_offset(const char *prefix, char *offset, int start, struct list_head *head, struct list_head **pos); +--- autofs-5.0.5.orig/lib/cache.c ++++ autofs-5.0.5/lib/cache.c +@@ -228,15 +228,38 @@ struct mapent_cache *cache_init(struct a + return mc; + } + ++void cache_clean_null_cache(struct mapent_cache *mc) ++{ ++ struct mapent *me, *next; ++ int i; ++ ++ for (i = 0; i < mc->size; i++) { ++ me = mc->hash[i]; ++ if (me == NULL) ++ continue; ++ next = me->next; ++ free(me->key); ++ if (me->mapent) ++ free(me->mapent); ++ free(me); ++ ++ while (next != NULL) { ++ me = next; ++ next = me->next; ++ free(me->key); ++ free(me); ++ } ++ } ++ ++ return; ++} ++ + struct mapent_cache *cache_init_null_cache(struct master *master) + { + struct mapent_cache *mc; + unsigned int i; + int status; + +- if (master->nc) +- cache_release_null_cache(master); +- + mc = malloc(sizeof(struct mapent_cache)); + if (!mc) + return NULL; +@@ -264,8 +287,6 @@ struct mapent_cache *cache_init_null_cac + if (status) + fatal(status); + +- cache_writelock(mc); +- + for (i = 0; i < mc->size; i++) { + mc->hash[i] = NULL; + INIT_LIST_HEAD(&mc->ino_index[i]); +@@ -274,8 +295,6 @@ struct mapent_cache *cache_init_null_cac + mc->ap = NULL; + mc->map = NULL; + +- cache_unlock(mc); +- + return mc; + } + +--- autofs-5.0.5.orig/lib/master.c ++++ autofs-5.0.5/lib/master.c +@@ -811,15 +811,28 @@ int master_read_master(struct master *ma + unsigned int logopt = master->logopt; + struct mapent_cache *nc; + +- nc = cache_init_null_cache(master); +- if (!nc) { +- error(logopt, +- "failed to init null map cache for %s", master->name); +- return 0; ++ /* ++ * We need to clear and re-populate the null map entry cache ++ * before alowing anyone else to use it. ++ */ ++ if (master->nc) { ++ cache_writelock(master->nc); ++ nc = master->nc; ++ cache_clean_null_cache(nc); ++ } else { ++ nc = cache_init_null_cache(master); ++ if (!nc) { ++ error(logopt, ++ "failed to init null map cache for %s", ++ master->name); ++ return 0; ++ } ++ cache_writelock(nc); ++ master->nc = nc; + } +- master->nc = nc; +- + master_init_scan(); ++ lookup_nss_read_master(master, age); ++ cache_unlock(nc); + + lookup_nss_read_master(master, age); + if (!master->read_fail) +--- autofs-5.0.5.orig/lib/master_parse.y ++++ autofs-5.0.5/lib/master_parse.y +@@ -741,21 +741,16 @@ int master_parse_entry(const char *buffe + + /* Add null map entries to the null map cache */ + if (type && !strcmp(type, "null")) { +- cache_writelock(nc); + cache_update(nc, NULL, path, NULL, lineno); +- cache_unlock(nc); + local_free_vars(); + return 1; + } + + /* Ignore all subsequent matching nulled entries */ +- cache_readlock(nc); + if (cache_lookup_distinct(nc, path)) { +- cache_unlock(nc); + local_free_vars(); + return 1; + } +- cache_unlock(nc); + + if (debug || verbose) { + logopt = (debug ? LOGOPT_DEBUG : 0); diff --git a/autofs-5.0.5-fix-parse_sun-module-init.patch b/autofs-5.0.5-fix-parse_sun-module-init.patch new file mode 100644 index 0000000..279bd9c --- /dev/null +++ b/autofs-5.0.5-fix-parse_sun-module-init.patch @@ -0,0 +1,107 @@ +autofs-5.0.5 - fix parse_sun() module init + +From: Ian Kent + +In the parse sun module we pre-open the NFS mount module and cache +the library handle because it is used so often. Since this is shared +amonst all the master map entries multiple threads can race when +accessing the instance counter, especially when there are many +master map entries, leading to a double close on the mount library +handle. +--- + + CHANGELOG | 1 + + modules/parse_sun.c | 37 ++++++++++++++++++++++++++++++------- + 2 files changed, 31 insertions(+), 7 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -35,6 +35,7 @@ + - don't hold lock for simple mounts. + - fix remount locking. + - fix wildcard map entry match. ++- fix parse_sun() module init. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/modules/parse_sun.c ++++ autofs-5.0.5/modules/parse_sun.c +@@ -45,6 +45,22 @@ int parse_version = AUTOFS_PARSE_VERSION + + static struct mount_mod *mount_nfs = NULL; + static int init_ctr = 0; ++static int macro_init_done = 0; ++static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static void instance_mutex_lock(void) ++{ ++ int status = pthread_mutex_lock(&instance_mutex); ++ if (status) ++ fatal(status); ++} ++ ++static void instance_mutex_unlock(void) ++{ ++ int status = pthread_mutex_unlock(&instance_mutex); ++ if (status) ++ fatal(status); ++} + + extern const char *global_options; + +@@ -276,9 +292,12 @@ int parse_init(int argc, const char *con + unsigned int append_options; + + /* Get processor information for predefined escapes */ +- +- if (!init_ctr) ++ macro_lock(); ++ if (!macro_init_done) { ++ macro_init_done = 1; + macro_init(); ++ } ++ macro_unlock(); + + /* Set up context and escape chain */ + +@@ -434,19 +453,21 @@ options_done: + + /* We only need this once. NFS mounts are so common that we cache + this module. */ +- if (!mount_nfs) { ++ instance_mutex_lock(); ++ if (mount_nfs) ++ init_ctr++; ++ else { + if ((mount_nfs = open_mount("nfs", MODPREFIX))) { + init_ctr++; +- return 0; + } else { + kill_context(ctxt); + *context = NULL; ++ instance_mutex_unlock(); + return 1; + } +- } else { +- init_ctr++; +- return 0; + } ++ instance_mutex_unlock(); ++ return 0; + } + + static const char *parse_options(const char *str, char **ret, unsigned int logopt) +@@ -1734,10 +1755,12 @@ int parse_done(void *context) + int rv = 0; + struct parse_context *ctxt = (struct parse_context *) context; + ++ instance_mutex_lock(); + if (--init_ctr == 0) { + rv = close_mount(mount_nfs); + mount_nfs = NULL; + } ++ instance_mutex_unlock(); + if (ctxt) + kill_context(ctxt); + diff --git a/autofs-5.0.5-fix-random-selection-for-host-on-different-network.patch b/autofs-5.0.5-fix-random-selection-for-host-on-different-network.patch new file mode 100644 index 0000000..2c175f3 --- /dev/null +++ b/autofs-5.0.5-fix-random-selection-for-host-on-different-network.patch @@ -0,0 +1,137 @@ +autofs-5.0.5 - fix random selection for host on different network + +From: Ian Kent + +When we select from a list of hosts from which we can mount the list +is ordered by response time within proximity. + +This is intended for normal selection but when using random selection +if any hosts are on another network (and so considered further away) +they will never be at the head of the list and so are unlikely to be +used. This leads to a limited set of hosts being used for mounts which +usually isn't what's required when the random selection option is used. +--- + + CHANGELOG | 1 + + include/replicated.h | 2 +- + modules/mount_nfs.c | 2 +- + modules/replicated.c | 28 ++++++++++++++++++++-------- + 4 files changed, 23 insertions(+), 10 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -30,6 +30,7 @@ + - add simple bind authentication. + - fix master map source server unavailable handling. + - add autofs_ldap_auth.conf man page. ++- fix random selection for host on different network. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/include/replicated.h ++++ autofs-5.0.5/include/replicated.h +@@ -64,7 +64,7 @@ struct host { + + void seed_random(void); + void free_host_list(struct host **); +-int parse_location(unsigned, struct host **, const char *); ++int parse_location(unsigned, struct host **, const char *, unsigned int); + int prune_host_list(unsigned, struct host **, unsigned int, const char *, unsigned int); + void dump_host_list(struct host *); + +--- autofs-5.0.5.orig/modules/mount_nfs.c ++++ autofs-5.0.5/modules/mount_nfs.c +@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, + else if (mount_default_proto == 4) + vers = vers | NFS4_VERS_MASK; + +- if (!parse_location(ap->logopt, &hosts, what)) { ++ if (!parse_location(ap->logopt, &hosts, what, random_selection)) { + info(ap->logopt, MODPREFIX "no hosts available"); + return 1; + } +--- autofs-5.0.5.orig/modules/replicated.c ++++ autofs-5.0.5/modules/replicated.c +@@ -1041,13 +1041,23 @@ int prune_host_list(unsigned logopt, str + + static int add_new_host(struct host **list, + const char *host, unsigned int weight, +- struct addrinfo *host_addr) ++ struct addrinfo *host_addr, ++ unsigned int random_selection) + { + struct host *new; + unsigned int prx; + int addr_len; + +- prx = get_proximity(host_addr->ai_addr); ++ /* ++ * If we are using random selection we pretend all hosts are at ++ * the same proximity so hosts further away don't get excluded. ++ * We can't use PROXIMITY_LOCAL or we won't perform an RPC ping ++ * to remove hosts that may be down. ++ */ ++ if (random_selection) ++ prx = PROXIMITY_SUBNET; ++ else ++ prx = get_proximity(host_addr->ai_addr); + /* + * If we tried to add an IPv6 address and we don't have IPv6 + * support return success in the hope of getting an IPv4 +@@ -1071,7 +1081,8 @@ static int add_new_host(struct host **li + return 1; + } + +-static int add_host_addrs(struct host **list, const char *host, unsigned int weight) ++static int add_host_addrs(struct host **list, const char *host, ++ unsigned int weight, unsigned int random_selection) + { + struct addrinfo hints, *ni, *this; + int ret; +@@ -1087,7 +1098,7 @@ static int add_host_addrs(struct host ** + + this = ni; + while (this) { +- ret = add_new_host(list, host, weight, this); ++ ret = add_new_host(list, host, weight, this, random_selection); + if (!ret) + break; + this = this->ai_next; +@@ -1110,7 +1121,7 @@ try_name: + + this = ni; + while (this) { +- ret = add_new_host(list, host, weight, this); ++ ret = add_new_host(list, host, weight, this, random_selection); + if (!ret) + break; + this = this->ai_next; +@@ -1197,7 +1208,8 @@ static char *seek_delim(const char *s) + return NULL; + } + +-int parse_location(unsigned logopt, struct host **hosts, const char *list) ++int parse_location(unsigned logopt, struct host **hosts, ++ const char *list, unsigned int random_selection) + { + char *str, *p, *delim; + unsigned int empty = 1; +@@ -1252,7 +1264,7 @@ int parse_location(unsigned logopt, stru + } + + if (p != delim) { +- if (!add_host_addrs(hosts, p, weight)) { ++ if (!add_host_addrs(hosts, p, weight, random_selection)) { + if (empty) { + p = next; + continue; +@@ -1274,7 +1286,7 @@ int parse_location(unsigned logopt, stru + *delim = '\0'; + next = delim + 1; + +- if (!add_host_addrs(hosts, p, weight)) { ++ if (!add_host_addrs(hosts, p, weight, random_selection)) { + p = next; + continue; + } diff --git a/autofs-5.0.5-fix-remount-locking.patch b/autofs-5.0.5-fix-remount-locking.patch new file mode 100644 index 0000000..c7cc7a2 --- /dev/null +++ b/autofs-5.0.5-fix-remount-locking.patch @@ -0,0 +1,365 @@ +autofs-5.0.5 - fix remount locking + +From: Ian Kent + +When autofs is restarted with active mounts it is possible, due +to possible recursion when mounting multi-mount map entries, that +a lookup module will take a write lock on the map entry cache +when a read lock is alreay held. + +Since, during the re-mount, we are still essentially running +single threaded we need only take care to ensure we don't take +the write lock. +--- + + CHANGELOG | 1 + + modules/lookup_file.c | 27 +++++++++++++++++---------- + modules/lookup_hosts.c | 24 +++++++++++++++--------- + modules/lookup_ldap.c | 24 ++++++++++++++++-------- + modules/lookup_nisplus.c | 29 ++++++++++++++++++----------- + modules/lookup_program.c | 29 +++++++++++++++++++++-------- + modules/lookup_yp.c | 27 +++++++++++++++++---------- + 7 files changed, 105 insertions(+), 56 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -33,6 +33,7 @@ + - fix random selection for host on different network. + - make redhat init script more lsb compliant. + - don't hold lock for simple mounts. ++- fix remount locking. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/modules/lookup_file.c ++++ autofs-5.0.5/modules/lookup_file.c +@@ -871,7 +871,6 @@ static int check_map_indirect(struct aut + if (ret == CHE_FAIL) + return NSS_STATUS_NOTFOUND; + +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ +@@ -882,7 +881,7 @@ static int check_map_indirect(struct aut + exists->status = 0; + } + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + + if (ret == CHE_MISSING) { + struct mapent *we; +@@ -896,7 +895,6 @@ static int check_map_indirect(struct aut + * Check for map change and update as needed for + * following cache lookup. + */ +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { +@@ -904,7 +902,7 @@ static int check_map_indirect(struct aut + if (we->source == source && (wild & CHE_MISSING)) + cache_delete(mc, "*"); + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + + if (wild & (CHE_OK | CHE_UPDATED)) + return NSS_STATUS_SUCCESS; +@@ -957,13 +955,22 @@ int lookup_mount(struct autofs_point *ap + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; ++ ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, key); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, key); ++ cache_unlock(smc); ++ } + } +- +- /* Negative timeout expired for non-existent entry. */ +- if (!me->mapent) +- cache_delete(me->mc, key); +- +- cache_unlock(me->mc); + } + + /* +--- autofs-5.0.5.orig/modules/lookup_hosts.c ++++ autofs-5.0.5/modules/lookup_hosts.c +@@ -146,19 +146,25 @@ int lookup_mount(struct autofs_point *ap + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, name, LKP_DISTINCT); + if (me) { +- struct mapent_cache *fmc = me->mc; +- + if (me->status >= time(NULL)) { +- cache_unlock(fmc); ++ cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; +- } ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; + +- if (!me->mapent) { +- cache_delete(fmc, name); +- me = NULL; ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, name); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, name); ++ cache_unlock(smc); ++ } + } +- +- cache_unlock(fmc); + } + + cache_readlock(mc); +--- autofs-5.0.5.orig/modules/lookup_ldap.c ++++ autofs-5.0.5/modules/lookup_ldap.c +@@ -2681,7 +2681,6 @@ next: + unbind_ldap_connection(ap->logopt, ldap, ctxt); + + /* Failed to find wild entry, update cache if needed */ +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { +@@ -2707,7 +2706,7 @@ next: + } + } + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + free(query); + + return ret; +@@ -2817,13 +2816,22 @@ int lookup_mount(struct autofs_point *ap + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; ++ ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, key); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, key); ++ cache_unlock(smc); ++ } + } +- +- /* Negative timeout expired for non-existent entry. */ +- if (!me->mapent) +- cache_delete(me->mc, key); +- +- cache_unlock(me->mc); + } + + /* +--- autofs-5.0.5.orig/modules/lookup_nisplus.c ++++ autofs-5.0.5/modules/lookup_nisplus.c +@@ -421,7 +421,6 @@ static int check_map_indirect(struct aut + return NSS_STATUS_UNAVAIL; + } + +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + t_last_read = ap->exp_runfreq + 1; + me = cache_lookup_first(mc); +@@ -442,8 +441,8 @@ static int check_map_indirect(struct aut + exists->status = 0; + } + } +- pthread_cleanup_pop(1); +- ++ cache_unlock(mc); ++ + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) + source->stale = 1; + +@@ -459,7 +458,6 @@ static int check_map_indirect(struct aut + * Check for map change and update as needed for + * following cache lookup. + */ +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { +@@ -473,7 +471,7 @@ static int check_map_indirect(struct aut + if (wild & (CHE_OK | CHE_UPDATED)) + source->stale = 1; + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + + if (wild & (CHE_UPDATED | CHE_OK)) + return NSS_STATUS_SUCCESS; +@@ -516,13 +514,22 @@ int lookup_mount(struct autofs_point *ap + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; +- } +- +- /* Negative timeout expired for non-existent entry. */ +- if (!me->mapent) +- cache_delete(me->mc, key); ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; + +- cache_unlock(me->mc); ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, key); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, key); ++ cache_unlock(smc); ++ } ++ } + } + + /* +--- autofs-5.0.5.orig/modules/lookup_program.c ++++ autofs-5.0.5/modules/lookup_program.c +@@ -135,17 +135,26 @@ int lookup_mount(struct autofs_point *ap + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; +- } +- +- /* Negative timeout expired for non-existent entry. */ +- if (!me->mapent) +- cache_delete(me->mc, name); ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; + +- cache_unlock(me->mc); ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, name); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, name); ++ cache_unlock(smc); ++ } ++ } + } + + /* Catch installed direct offset triggers */ +- cache_writelock(mc); ++ cache_readlock(mc); + me = cache_lookup_distinct(mc, name); + if (!me) { + cache_unlock(mc); +@@ -191,7 +200,11 @@ int lookup_mount(struct autofs_point *ap + " key %s, returning fail", name); + return NSS_STATUS_UNAVAIL; + } +- cache_delete(mc, name); ++ cache_unlock(mc); ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (me) ++ cache_delete(mc, name); + cache_unlock(mc); + } + } +--- autofs-5.0.5.orig/modules/lookup_yp.c ++++ autofs-5.0.5/modules/lookup_yp.c +@@ -533,7 +533,6 @@ static int check_map_indirect(struct aut + source->stale = 1; + } + +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ +@@ -545,7 +544,7 @@ static int check_map_indirect(struct aut + exists->status = 0; + } + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + + if (ret == CHE_MISSING) { + struct mapent *we; +@@ -559,7 +558,6 @@ static int check_map_indirect(struct aut + * Check for map change and update as needed for + * following cache lookup. + */ +- pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { +@@ -573,7 +571,7 @@ static int check_map_indirect(struct aut + if (wild & (CHE_OK | CHE_UPDATED)) + source->stale = 1; + } +- pthread_cleanup_pop(1); ++ cache_unlock(mc); + + if (wild & (CHE_OK | CHE_UPDATED)) + return NSS_STATUS_SUCCESS; +@@ -616,13 +614,22 @@ int lookup_mount(struct autofs_point *ap + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; +- } +- +- /* Negative timeout expired for non-existent entry. */ +- if (!me->mapent) +- cache_delete(me->mc, key); ++ } else { ++ struct mapent_cache *smc = me->mc; ++ struct mapent *sme; + +- cache_unlock(me->mc); ++ if (me->mapent) ++ cache_unlock(smc); ++ else { ++ cache_unlock(smc); ++ cache_writelock(smc); ++ sme = cache_lookup_distinct(smc, key); ++ /* Negative timeout expired for non-existent entry. */ ++ if (sme && !sme->mapent) ++ cache_delete(smc, key); ++ cache_unlock(smc); ++ } ++ } + } + + /* diff --git a/autofs-5.0.5-fix-wildcard-map-entry-match.patch b/autofs-5.0.5-fix-wildcard-map-entry-match.patch new file mode 100644 index 0000000..b49f81e --- /dev/null +++ b/autofs-5.0.5-fix-wildcard-map-entry-match.patch @@ -0,0 +1,59 @@ +autofs-5.0.5 - fix wildcard map entry match + +From: Ian Kent + +In some cases we can get a key string that includes a '*' at the start. +This causes an incorrect comparison in the cache library routines and can +lead to a segmentation fault. + +This patch enures that the key length is also considered when checking the +wildcard key entry. +--- + + CHANGELOG | 1 + + daemon/lookup.c | 4 ++-- + lib/cache.c | 2 +- + 3 files changed, 4 insertions(+), 3 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -34,6 +34,7 @@ + - make redhat init script more lsb compliant. + - don't hold lock for simple mounts. + - fix remount locking. ++- fix wildcard map entry match. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/lookup.c ++++ autofs-5.0.5/daemon/lookup.c +@@ -600,7 +600,7 @@ int lookup_ghost(struct autofs_point *ap + cache_readlock(mc); + me = cache_enumerate(mc, NULL); + while (me) { +- if (*me->key == '*') ++ if (!strcmp(me->key, "*")) + goto next; + + if (*me->key == '/') { +@@ -1035,7 +1035,7 @@ void lookup_prune_one_cache(struct autof + + key = strdup(me->key); + me = cache_enumerate(mc, me); +- if (!key || *key == '*') { ++ if (!key || !strcmp(key, "*")) { + if (key) + free(key); + continue; +--- autofs-5.0.5.orig/lib/cache.c ++++ autofs-5.0.5/lib/cache.c +@@ -719,7 +719,7 @@ int cache_update(struct mapent_cache *mc + me = cache_lookup(mc, key); + while (me && me->source != ms) + me = cache_lookup_key_next(me); +- if (!me || (*me->key == '*' && *key != '*')) { ++ if (!me || (!strcmp(me->key, "*") && strcmp(key, "*"))) { + ret = cache_add(mc, ms, key, mapent, age); + if (!ret) { + debug(logopt, "failed for %s", key); diff --git a/autofs-5.0.5-make-redhat-init-script-more-lsb-compliant.patch b/autofs-5.0.5-make-redhat-init-script-more-lsb-compliant.patch new file mode 100644 index 0000000..83bebd6 --- /dev/null +++ b/autofs-5.0.5-make-redhat-init-script-more-lsb-compliant.patch @@ -0,0 +1,112 @@ +autofs-5.0.5 - make redhat init script more lsb compliant + +From: Ian Kent + + +--- + + CHANGELOG | 1 + + redhat/autofs.init.in | 39 ++++++++++++++++++++++++++++++++------- + 2 files changed, 33 insertions(+), 7 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -31,6 +31,7 @@ + - fix master map source server unavailable handling. + - add autofs_ldap_auth.conf man page. + - fix random selection for host on different network. ++- make redhat init script more lsb compliant. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/redhat/autofs.init.in ++++ autofs-5.0.5/redhat/autofs.init.in +@@ -86,14 +86,18 @@ function start() { + fi + + echo -n $"Starting $prog: " +- $prog $OPTIONS ++ $prog $OPTIONS --pid-file /var/run/autofs.pid + RETVAL=$? + if [ $RETVAL -eq 0 ] ; then + success "$prog startup" + else + failure "$prog startup" + fi +- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/autofs ++ if [ $RETVAL -eq 0 ]; then ++ touch /var/lock/subsys/autofs ++ else ++ RETVAL=1 ++ fi + echo + return $RETVAL + } +@@ -107,7 +111,11 @@ function stop() { + [ $RETVAL = 0 -a -z "`pidof $prog`" ] || sleep 3 + count=`expr $count + 1` + done +- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/autofs ++ if [ $RETVAL -eq 0 ]; then ++ rm -f /var/lock/subsys/autofs ++ else ++ RETVAL=1 ++ fi + if [ -n "`pidof $prog`" ] ; then + failure "$prog shutdown" + else +@@ -118,7 +126,10 @@ function stop() { + } + + function restart() { +- stop ++ status > /dev/null 2>&1 ++ if [ $? -eq 0 ]; then ++ stop ++ fi + start + } + +@@ -142,6 +153,12 @@ function reload() { + + RETVAL=0 + ++# Only the root user may change the service status ++if [ `id -u` -ne 0 ]; then ++ echo "insufficient privilege to change service status" ++ exit 4 ++fi ++ + case "$1" in + start) + start +@@ -154,7 +171,7 @@ case "$1" in + stop + ;; + status) +- status $prog ++ status -p /var/run/autofs.pid -l autofs $prog + ;; + restart) + restart +@@ -171,9 +188,17 @@ case "$1" in + restart + fi + ;; +- *) ++ usage) + echo $"Usage: $0 {start|forcestart|stop|status|restart|forcerestart|reload|condrestart}" +- exit 1; ++ exit 0 ++ ;; ++ try-restart|force-reload) ++ echo "$1 service action not supported" ++ exit 3 ++ ;; ++ *) ++ echo "unknown, invalid or excess argument(s)" ++ exit 2 + ;; + esac + diff --git a/autofs-5.0.5-mapent-becomes-negative-during-lookup.patch b/autofs-5.0.5-mapent-becomes-negative-during-lookup.patch new file mode 100644 index 0000000..0956267 --- /dev/null +++ b/autofs-5.0.5-mapent-becomes-negative-during-lookup.patch @@ -0,0 +1,73 @@ +autofs-5.0.5 - mapent becomes negative during lookup + +From: Ian Kent + +During a mount request it is possible for a mapent to become negative +between the time it is checked on entry and when we fetch the mount +location information. This is because we drop the cache lock after +the initial check and take it back again before getting the location +information. +--- + + CHANGELOG | 1 + + modules/lookup_file.c | 2 +- + modules/lookup_ldap.c | 2 +- + modules/lookup_nisplus.c | 2 +- + modules/lookup_yp.c | 2 +- + 5 files changed, 5 insertions(+), 4 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -39,6 +39,7 @@ + - dont check null cache on expire. + - fix null cache race. + - fix cache_init() on source re-read. ++- fix mapent becomes negative during lookup. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/modules/lookup_file.c ++++ autofs-5.0.5/modules/lookup_file.c +@@ -1047,7 +1047,7 @@ do_cache_lookup: + if (!me) + me = cache_lookup_distinct(mc, "*"); + } +- if (me && (me->source == source || *me->key == '/')) { ++ if (me && me->mapent && (me->source == source || *me->key == '/')) { + pthread_cleanup_push(cache_lock_cleanup, mc); + strcpy(mapent_buf, me->mapent); + mapent = mapent_buf; +--- autofs-5.0.5.orig/modules/lookup_ldap.c ++++ autofs-5.0.5/modules/lookup_ldap.c +@@ -2872,7 +2872,7 @@ int lookup_mount(struct autofs_point *ap + if (!me) + me = cache_lookup_distinct(mc, "*"); + } +- if (me && (me->source == source || *me->key == '/')) { ++ if (me && me->mapent && (me->source == source || *me->key == '/')) { + strcpy(mapent_buf, me->mapent); + mapent = mapent_buf; + } +--- autofs-5.0.5.orig/modules/lookup_nisplus.c ++++ autofs-5.0.5/modules/lookup_nisplus.c +@@ -569,7 +569,7 @@ int lookup_mount(struct autofs_point *ap + if (!me) + me = cache_lookup_distinct(mc, "*"); + } +- if (me && (me->source == source || *me->key == '/')) { ++ if (me && me->mapent && (me->source == source || *me->key == '/')) { + mapent_len = strlen(me->mapent); + mapent = malloc(mapent_len + 1); + strcpy(mapent, me->mapent); +--- autofs-5.0.5.orig/modules/lookup_yp.c ++++ autofs-5.0.5/modules/lookup_yp.c +@@ -670,7 +670,7 @@ int lookup_mount(struct autofs_point *ap + if (!me) + me = cache_lookup_distinct(mc, "*"); + } +- if (me && (me->source == source || *me->key == '/')) { ++ if (me && me->mapent && (me->source == source || *me->key == '/')) { + mapent_len = strlen(me->mapent); + mapent = alloca(mapent_len + 1); + strcpy(mapent, me->mapent); diff --git a/autofs-5.0.5-remove-state-machine-timed-wait.patch b/autofs-5.0.5-remove-state-machine-timed-wait.patch new file mode 100644 index 0000000..06f37a3 --- /dev/null +++ b/autofs-5.0.5-remove-state-machine-timed-wait.patch @@ -0,0 +1,114 @@ +autofs-5.0.5 - remove state machine timed wait + +From: Ian Kent + +We are seeing a problem using timed waits when running under KVM. + +Using timed condition waits in the state machine (and in some other +places) has been used because of observed task throughput problems +in the past. Also, we've seen condition waits not reacting to signals +occassionaly. + +But now we are seeing problems with the setup of the wait time within +KVM VMs causing the condition wait to go into a tight loop using +excessive CPU. + +Changing the state queue handler to not use timed waits appears to +not have the previously observed throughput problems, hopefully we +won't see lost signals either. +--- + + CHANGELOG | 1 + + daemon/state.c | 30 +++++++----------------------- + 2 files changed, 8 insertions(+), 23 deletions(-) + + +--- autofs-5.0.5.orig/CHANGELOG ++++ autofs-5.0.5/CHANGELOG +@@ -42,6 +42,7 @@ + - fix mapent becomes negative during lookup. + - check each dc server individually. + - fix negative cache included map lookup. ++- remove state machine timed wait. + + 03/09/2009 autofs-5.0.5 + ----------------------- +--- autofs-5.0.5.orig/daemon/state.c ++++ autofs-5.0.5/daemon/state.c +@@ -197,11 +197,11 @@ void expire_cleanup(void *arg) + } + } + ++ st_set_done(ap); ++ + if (next != ST_INVAL) + __st_add_task(ap, next); + +- st_set_done(ap); +- + st_mutex_unlock(); + + return; +@@ -332,11 +332,10 @@ static void do_readmap_cleanup(void *arg + st_mutex_lock(); + + ap->readmap_thread = 0; +- st_ready(ap); + st_set_done(ap); +- + if (!ap->submount) + alarm_add(ap, ap->exp_runfreq); ++ st_ready(ap); + + st_mutex_unlock(); + +@@ -1060,8 +1059,6 @@ static void *st_queue_handler(void *arg) + { + struct list_head *head; + struct list_head *p; +- struct timespec wait; +- struct timeval now; + int status, ret; + + st_mutex_lock(); +@@ -1072,17 +1069,11 @@ static void *st_queue_handler(void *arg) + * entry is added. + */ + head = &state_queue; +- gettimeofday(&now, NULL); +- wait.tv_sec = now.tv_sec + 1; +- wait.tv_nsec = now.tv_usec * 1000; + + while (list_empty(head)) { +- status = pthread_cond_timedwait(&cond, &mutex, &wait); +- if (status) { +- if (status == ETIMEDOUT) +- break; ++ status = pthread_cond_wait(&cond, &mutex); ++ if (status) + fatal(status); +- } + } + + p = head->next; +@@ -1108,18 +1099,11 @@ static void *st_queue_handler(void *arg) + } + + while (1) { +- gettimeofday(&now, NULL); +- wait.tv_sec = now.tv_sec + 1; +- wait.tv_nsec = now.tv_usec * 1000; +- + signaled = 0; + while (!signaled) { +- status = pthread_cond_timedwait(&cond, &mutex, &wait); +- if (status) { +- if (status == ETIMEDOUT) +- break; ++ status = pthread_cond_wait(&cond, &mutex); ++ if (status) + fatal(status); +- } + } + + head = &state_queue; diff --git a/autofs.spec b/autofs.spec index 847dc3e..a2f60e7 100644 --- a/autofs.spec +++ b/autofs.spec @@ -4,7 +4,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.0.5 -Release: 26%{?dist} +Release: 27%{?dist} Epoch: 1 License: GPLv2+ Group: System Environment/Daemons @@ -38,6 +38,21 @@ Patch26: autofs-5.0.5-add-locality-as-valid-ldap-master-map-attribute.patch Patch27: autofs-5.0.5-add-locality-as-valid-ldap-master-map-attribute-fix.patch Patch28: autofs-5.0.5-make-nfs4-default-for-redhat-replicated-selection.patch Patch29: autofs-5.0.5-add-simple-bind-auth.patch +Patch30: autofs-5.0.5-fix-master-map-source-server-unavialable-handling.patch +Patch31: autofs-5.0.5-add-autofs_ldap_auth_conf-man-page.patch +Patch32: autofs-5.0.5-fix-random-selection-for-host-on-different-network.patch +Patch33: autofs-5.0.5-make-redhat-init-script-more-lsb-compliant.patch +Patch34: autofs-5.0.5-dont-hold-lock-for-simple-mounts.patch +Patch35: autofs-5.0.5-fix-remount-locking.patch +Patch36: autofs-5.0.5-fix-wildcard-map-entry-match.patch +Patch37: autofs-5.0.5-fix-parse_sun-module-init.patch +Patch38: autofs-5.0.5-dont-check-null-cache-on-expire.patch +Patch39: autofs-5.0.5-fix-null-cache-race.patch +Patch40: autofs-5.0.5-fix-cache_init-on-source-re-read.patch +Patch41: autofs-5.0.5-mapent-becomes-negative-during-lookup.patch +Patch42: autofs-5.0.5-check-each-dc-server.patch +Patch43: autofs-5.0.5-fix-negative-cache-included-map-lookup.patch +Patch44: autofs-5.0.5-remove-state-machine-timed-wait.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs libtirpc-devel Conflicts: cyrus-sasl-lib < 2.1.23-9 @@ -109,6 +124,21 @@ echo %{version}-%{release} > .version %patch27 -p1 %patch28 -p1 %patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 +%patch44 -p1 %build #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir} @@ -161,6 +191,23 @@ fi %{_libdir}/autofs/ %changelog +* Mon May 24 2010 Ian Kent - 1:5.0.5-27.fc14 +- fix master map source server unavailable handling. +- add autofs_ldap_auth.conf man page. +- fix random selection for host on different network. +- make redhat init script more lsb compliant. +- don't hold lock for simple mounts. +- fix remount locking. +- fix wildcard map entry match. +- fix parse_sun() module init. +- dont check null cache on expire. +- fix null cache race. +- fix cache_init() on source re-read. +- fix mapent becomes negative during lookup. +- check each dc server individually. +- fix negative cache included map lookup. +- remove state machine timed wait. + * Fri Apr 30 2010 Ian Kent - 1:5.0.5-26.fc14 - remove URL tag as there is not official autofs wiki (bz529804).