You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.1 KiB
213 lines
6.1 KiB
autofs-5.0.9 - amd lookup fix host mount naming |
|
|
|
From: Ian Kent <raven@themaw.net> |
|
|
|
Currently the amd host mount type assumes the lookup name is |
|
the host name for the host mount but amd uses ${rhost} for |
|
this. |
|
|
|
This introduces the possibility of multiple concurrent mount |
|
requests since constructing a mount tree that isn't under the |
|
lookup name can't take advantage of the kernel queuing other |
|
concurrent lookups while the mount tree is constructed. |
|
--- |
|
daemon/lookup.c | 20 +++++++++++++---- |
|
modules/parse_amd.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++-- |
|
modules/parse_sun.c | 22 +++++++++++------- |
|
3 files changed, 89 insertions(+), 14 deletions(-) |
|
|
|
--- autofs-5.0.7.orig/daemon/lookup.c |
|
+++ autofs-5.0.7/daemon/lookup.c |
|
@@ -815,7 +815,8 @@ static int lookup_amd_instance(struct au |
|
|
|
m_key = malloc(strlen(ap->path) + strlen(me->multi->key) + 1); |
|
if (!m_key) { |
|
- error(ap->logopt, "failed to allocate storage for search key"); |
|
+ error(ap->logopt, |
|
+ "failed to allocate storage for search key"); |
|
return NSS_STATUS_UNKNOWN; |
|
} |
|
|
|
@@ -823,12 +824,12 @@ static int lookup_amd_instance(struct au |
|
strcat(m_key, "/"); |
|
strcat(m_key, me->multi->key); |
|
entry = master_find_amdmount(ap, m_key); |
|
+ free(m_key); |
|
+ |
|
if (!entry) { |
|
error(ap->logopt, "expected amd mount entry not found"); |
|
- free(m_key); |
|
return NSS_STATUS_UNKNOWN; |
|
} |
|
- free(m_key); |
|
|
|
if (strcmp(entry->type, "host")) { |
|
error(ap->logopt, "unexpected map type %s", entry->type); |
|
@@ -843,6 +844,17 @@ static int lookup_amd_instance(struct au |
|
} |
|
|
|
instance = master_find_source_instance(map, "hosts", "sun", argc, pargv); |
|
+ /* If this is an nss map instance it may have an amd host map sub instance */ |
|
+ if (!instance && map->instance) { |
|
+ struct map_source *next = map->instance; |
|
+ while (next) { |
|
+ instance = master_find_source_instance(next, |
|
+ "hosts", "sun", argc, pargv); |
|
+ if (instance) |
|
+ break; |
|
+ next = next->next; |
|
+ } |
|
+ } |
|
if (!instance) { |
|
error(ap->logopt, "expected hosts map instance not found"); |
|
return NSS_STATUS_UNKNOWN; |
|
@@ -1174,7 +1186,6 @@ int lookup_nss_mount(struct autofs_point |
|
} |
|
if (ap->state != ST_INIT) |
|
send_map_update_request(ap); |
|
- pthread_cleanup_pop(1); |
|
|
|
/* |
|
* The last source lookup will return NSS_STATUS_NOTFOUND if the |
|
@@ -1183,6 +1194,7 @@ int lookup_nss_mount(struct autofs_point |
|
*/ |
|
if (result == NSS_STATUS_NOTFOUND || result == NSS_STATUS_UNAVAIL) |
|
update_negative_cache(ap, source, name); |
|
+ pthread_cleanup_pop(1); |
|
|
|
return !result; |
|
} |
|
--- autofs-5.0.7.orig/modules/parse_amd.c |
|
+++ autofs-5.0.7/modules/parse_amd.c |
|
@@ -1068,6 +1068,23 @@ static int do_nfsl_mount(struct autofs_p |
|
return do_link_mount(ap, name, entry, flags); |
|
} |
|
|
|
+static int wait_for_expire(struct autofs_point *ap) |
|
+{ |
|
+ int ret = 1; |
|
+ |
|
+ st_wait_task(ap, ST_EXPIRE, 0); |
|
+ |
|
+ st_mutex_lock(); |
|
+ if (ap->state != ST_SHUTDOWN && |
|
+ ap->state != ST_SHUTDOWN_PENDING && |
|
+ ap->state != ST_SHUTDOWN_FORCE) { |
|
+ ret = 0; |
|
+ } |
|
+ st_mutex_unlock(); |
|
+ |
|
+ return ret; |
|
+} |
|
+ |
|
static int do_host_mount(struct autofs_point *ap, const char *name, |
|
struct amd_entry *entry, struct map_source *source, |
|
unsigned int flags) |
|
@@ -1080,6 +1097,36 @@ static int do_host_mount(struct autofs_p |
|
int argc = 0; |
|
int ret = 1; |
|
|
|
+ /* |
|
+ * If the mount point name isn't the same as the host name |
|
+ * then we need to symlink to it after the mount. Attempt |
|
+ * the allocation and set entry->path to the base location |
|
+ * of the hosts mount tree so we can find it in |
|
+ * lookup_nss_mount() later. |
|
+ */ |
|
+ if (strcmp(name, entry->rhost)) { |
|
+ char *target; |
|
+ size_t len = strlen(ap->path) + strlen(entry->rhost) + 2; |
|
+ target = malloc(len); |
|
+ if (!target) { |
|
+ warn(ap->logopt, MODPREFIX |
|
+ "failed to alloc target to hosts mount base"); |
|
+ goto out; |
|
+ } |
|
+ strcpy(target, ap->path); |
|
+ strcat(target, "/"); |
|
+ strcat(target, entry->rhost); |
|
+ if (entry->path) |
|
+ free(entry->path); |
|
+ entry->path = target; |
|
+ /* |
|
+ * Wait for any expire before racing to mount the |
|
+ * export tree or bail out if we're shutting down. |
|
+ */ |
|
+ if (!wait_for_expire(ap)) |
|
+ goto out; |
|
+ } |
|
+ |
|
if (entry->opts) { |
|
argv[0] = entry->opts; |
|
argv[1] = NULL; |
|
@@ -1095,7 +1142,8 @@ static int do_host_mount(struct autofs_p |
|
goto out; |
|
} |
|
|
|
- instance = master_find_source_instance(source, "hosts", "sun", argc, pargv); |
|
+ instance = master_find_source_instance(source, |
|
+ "hosts", "sun", argc, pargv); |
|
if (!instance) { |
|
instance = master_add_source_instance(source, |
|
"hosts", "sun", time(NULL), argc, pargv); |
|
@@ -1119,7 +1167,16 @@ static int do_host_mount(struct autofs_p |
|
master_source_current_wait(ap->entry); |
|
ap->entry->current = source; |
|
|
|
- ret = lookup->lookup_mount(ap, name, strlen(name), lookup->context); |
|
+ ret = lookup->lookup_mount(ap, entry->rhost, |
|
+ strlen(entry->rhost), lookup->context); |
|
+ |
|
+ if (!strcmp(name, entry->rhost)) |
|
+ goto out; |
|
+ |
|
+ if (do_mount(ap, ap->path, |
|
+ name, strlen(name), entry->path, "bind", "symlink")) |
|
+ warn(ap->logopt, MODPREFIX |
|
+ "failed to create symlink to hosts mount base"); |
|
out: |
|
return ret; |
|
} |
|
--- autofs-5.0.7.orig/modules/parse_sun.c |
|
+++ autofs-5.0.7/modules/parse_sun.c |
|
@@ -1343,26 +1343,32 @@ int parse_mount(struct autofs_point *ap, |
|
strcat(m_root, name); |
|
} |
|
|
|
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); |
|
cache_readlock(mc); |
|
me = cache_lookup_distinct(mc, name); |
|
- if (me) { |
|
- /* So we know we're the multi-mount root */ |
|
- if (!me->multi) |
|
- me->multi = me; |
|
- } |
|
- |
|
if (!me) { |
|
free(options); |
|
cache_unlock(mc); |
|
+ pthread_setcancelstate(cur_state, NULL); |
|
error(ap->logopt, |
|
MODPREFIX "can't find multi root %s", name); |
|
return 1; |
|
} |
|
|
|
+ cache_multi_writelock(me); |
|
+ /* Someone beat us to it, return success */ |
|
+ if (me->multi) { |
|
+ free(options); |
|
+ cache_multi_unlock(me); |
|
+ cache_unlock(mc); |
|
+ pthread_setcancelstate(cur_state, NULL); |
|
+ return 0; |
|
+ } |
|
+ /* So we know we're the multi-mount root */ |
|
+ me->multi = me; |
|
+ |
|
age = me->age; |
|
|
|
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); |
|
- cache_multi_writelock(me); |
|
/* It's a multi-mount; deal with it */ |
|
do { |
|
char *path, *myoptions, *loc;
|
|
|