diff --git a/CHANGELOG b/CHANGELOG index 111c6af..f68e16e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ - cthon fix submount operation broken by above. - cthon more parser corrections and attempt to fix multi-mounts with various combinations of submounts (still broken). +- cthon fix expire of various forms of nested mounts. 13/7/2006 autofs-5.0.1 rc1 -------------------------- diff --git a/daemon/automount.c b/daemon/automount.c index 8fcf19a..91f4d15 100644 --- a/daemon/automount.c +++ b/daemon/automount.c @@ -550,21 +550,35 @@ int umount_multi(struct autofs_point *ap left = 0; list_for_each(p, &list) { + struct autofs_point *oap = ap; + char *has_opt_direct; + int is_autofs; + mptr = list_entry(p, struct mnt_list, list); - /* We only want real mounts */ - if (!strcmp(mptr->fs_type, "autofs")) + is_autofs = !strcmp(mptr->fs_type, "autofs"); + has_opt_direct = strstr(mptr->opts, "direct"); + + /* We only want real mounts and top level direct mounts */ + if (is_autofs && !has_opt_direct) continue; + if (ap->submount) + oap = ap->parent; + sched_yield(); - if (umount_offsets(ap, mnts, mptr->path)) - warn(ap->logopt, "could not umount some offsets under %s", - mptr->path); + if (umount_offsets(oap, mnts, mptr->path)) + warn(ap->logopt, + "could not umount some offsets under %s", + mptr->path); + + if (is_autofs) + continue; sched_yield(); - debug(ap->logopt, "unmounting dir = %s", mptr->path); + warn(ap->logopt, "unmounting dir = %s", mptr->path); if (umount_ent(ap, mptr->path, mptr->fs_type)) { warn(ap->logopt, "could not umount dir %s", @@ -573,49 +587,16 @@ int umount_multi(struct autofs_point *ap } } - /* Lastly check for offsets with no root mount */ - n = scandir(path, &de, 0, alphasort); - if (n && n != -1) { - char buf[PATH_MAX + 1]; - - while (n--) { - size_t size; - int ret; + /* Catch any offsets of indirect mounts with no root mount */ + if (!left && !tree_is_mounted(mnts, path, MNTS_ALL)) { + struct autofs_point *rap = ap; - sched_yield(); + if (ap->submount) + rap = ap->parent; - if (strcmp(de[n]->d_name, ".") == 0 || - strcmp(de[n]->d_name, "..") == 0) { - free(de[n]); - continue; - } - - size = sizeof(buf); - ret = cat_path(buf, size, path, de[n]->d_name); - if (!ret) { - do { - free(de[n]); - } while (n--); - left++; - break; - } - - if (umount_offsets(ap, mnts, buf)) { - warn(ap->logopt, - "could not umount some offsets under %s", - buf); - left++; - } - free(de[n]); - } - free(de); - } - - if (!left && !tree_is_mounted(mnts, path)) { - sched_yield(); - if (umount_offsets(ap, mnts, path)) { + if (umount_offsets(rap, mnts, path)) { warn(ap->logopt, - "could not umount some offsets under %s", path); + "could not umount some offsets under %s", path); left++; } } @@ -1229,7 +1210,7 @@ static void handle_mounts_cleanup(void * umount_autofs(ap, 1); if (submount) - master_signal_submount(ap); + master_signal_submount(ap, MASTER_SUBMNT_JOIN); else master_remove_mapent(ap->entry); master_free_mapent_sources(ap->entry, 1); diff --git a/daemon/direct.c b/daemon/direct.c index 89c8db2..f4f60f3 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -125,6 +125,24 @@ int do_umount_autofs_direct(struct autof me->ioctlfd = open(me->key, O_RDONLY); if (me->ioctlfd >= 0) { + int status = 1; + + rv = ioctl(me->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status); + if (rv) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, "ioctl failed: %s", estr); + return 1; + } else if (!status) { + if (ap->state != ST_SHUTDOWN_FORCE) { + debug(ap->logopt, "ask umount returned busy"); + return 1; + } else { + ioctl(me->ioctlfd, AUTOFS_IOC_CATATONIC, 0); + close(me->ioctlfd); + me->ioctlfd = -1; + goto force_umount; + } + } ioctl(me->ioctlfd, AUTOFS_IOC_CATATONIC, 0); close(me->ioctlfd); me->ioctlfd = -1; @@ -136,7 +154,7 @@ int do_umount_autofs_direct(struct autof } rv = umount(me->key); - if (rv != 0) { + if (rv == -1) { switch (errno) { case ENOENT: case EINVAL: @@ -468,8 +486,12 @@ int umount_autofs_offset(struct autofs_p if (me->ioctlfd >= 0) { int status = 1; - ioctl(me->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status); - if (!status) { + rv = ioctl(me->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status); + if (rv) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, "ioctl failed: %s", estr); + return 1; + } else if (!status) { if (ap->state != ST_SHUTDOWN_FORCE) { debug(ap->logopt, "ask umount returned busy"); return 1; @@ -517,15 +539,7 @@ force_umount: rv = umount2(me->key, MNT_DETACH); } else msg("umounted offset %s", me->key); -/* - if (!rv && me->dir_created) { - if (rmdir(me->key) == -1) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - warn(ap->logopt, - "failed to remove dir %s: %s", me->key, estr); - } - } -*/ + return rv; } @@ -800,25 +814,25 @@ static void kernel_callback_cleanup(void mc = mt->mc; if (mt->status) { + cache_writelock(mc); send_ready(mt->ioctlfd, mt->wait_queue_token); if (mt->type == NFY_EXPIRE) { close(mt->ioctlfd); - cache_writelock(mc); me = cache_lookup_distinct(mc, mt->name); if (me) me->ioctlfd = -1; - cache_unlock(mc); } + cache_unlock(mc); } else { + cache_writelock(mc); send_fail(mt->ioctlfd, mt->wait_queue_token); if (mt->type == NFY_MOUNT) { close(mt->ioctlfd); - cache_writelock(mc); me = cache_lookup_distinct(mc, mt->name); if (me) me->ioctlfd = -1; - cache_unlock(mc); } + cache_unlock(mc); } free(mt); diff --git a/daemon/indirect.c b/daemon/indirect.c index 7bde7ec..737d965 100644 --- a/daemon/indirect.c +++ b/daemon/indirect.c @@ -289,40 +289,24 @@ int umount_autofs_indirect(struct autofs * to do it here. If the cache entry isn't found then there aren't * any offset mounts. */ - if (ap->submount) { - struct master_mapent *entry = ap->parent->entry; - struct map_source *map; - struct mapent_cache *mc; - struct mapent *me; - - pthread_cleanup_push(master_source_lock_cleanup, entry); - master_source_readlock(entry); - map = entry->first; - while (map) { - mc = map->mc; - cache_readlock(mc); - me = cache_lookup_distinct(mc, ap->path); - if (me) { - close(me->ioctlfd); - me->ioctlfd = -1; - cache_unlock(mc); - break; - } - cache_unlock(mc); - map = map->next; - } - pthread_cleanup_pop(1); - } + if (ap->submount) + lookup_source_close_ioctlfd(ap->parent, ap->path); /* If we are trying to shutdown make sure we can umount */ - if (!ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) { - if (!ret) - warn(ap->logopt, "mount still busy %s", ap->path); + rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret); + if (rv) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, "ioctl failed: %s", estr); + return 1; + } else if (!ret) { + error(ap->logopt, "ask umount returned busy %s", ap->path); + busy = 1; } if (ap->ioctlfd >= 0) { ioctl(ap->ioctlfd, AUTOFS_IOC_CATATONIC, 0); close(ap->ioctlfd); + ap->ioctlfd = -1; close(ap->state_pipe[0]); close(ap->state_pipe[1]); ap->state_pipe[0] = -1; @@ -340,12 +324,12 @@ int umount_autofs_indirect(struct autofs switch (errno) { case ENOENT: case EINVAL: - warn(ap->logopt, + error(ap->logopt, "mount point %s does not exist", ap->path); return 0; break; case EBUSY: - warn(ap->logopt, + error(ap->logopt, "mount point %s is in use", ap->path); if (ap->state == ST_SHUTDOWN_FORCE) goto force_umount; @@ -385,6 +369,7 @@ void *expire_proc_indirect(void *arg) int offsets, submnts, count; int ioctlfd; int status, ret; + char buf[MAX_ERR_BUF]; ea = (struct expire_args *) arg; @@ -470,8 +455,9 @@ void *expire_proc_indirect(void *arg) ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now); if (ret < 0 && errno != EAGAIN) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); warn(ap->logopt, - "failed to expire mount %s", next->path); + "failed to expire mount %s:", next->path, estr); ea->status = 1; break; } @@ -479,7 +465,7 @@ void *expire_proc_indirect(void *arg) free_mnt_list(mnts); count = offsets = submnts = 0; - mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0); + mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1); /* Are there any real mounts left */ for (next = mnts; next; next = next->next) { if (strcmp(next->fs_type, "autofs")) @@ -497,10 +483,10 @@ void *expire_proc_indirect(void *arg) * have some offset mounts with no '/' offset so we need to * umount them here. */ - if (mnts && !ea->status && !count) { - int ret; + if (mnts) { + int ret, tries = (count + submnts + offsets + 2) * 2; - while (offsets--) { + while (tries--) { ret = ioctl(ap->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now); if (ret < 0 && errno != EAGAIN) { warn(ap->logopt, @@ -513,6 +499,21 @@ void *expire_proc_indirect(void *arg) } free_mnt_list(mnts); + count = offsets = submnts = 0; + mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0); + /* Are there any real mounts left */ + for (next = mnts; next; next = next->next) { + if (strcmp(next->fs_type, "autofs")) + count++; + else { + if (strstr(next->opts, "indirect")) + submnts++; + else + offsets++; + } + } + free_mnt_list(mnts); + if (submnts) { debug(ap->logopt, "%d submounts remaining in %s", submnts, ap->path); diff --git a/daemon/lookup.c b/daemon/lookup.c index f0f9718..a8ef518 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -395,6 +395,7 @@ int lookup_nss_read_map(struct autofs_po struct list_head *head, *p; struct nss_source *this; struct map_source *map; + enum nsswitch_status status; int result = 0; /* @@ -445,17 +446,16 @@ int lookup_nss_read_map(struct autofs_po INIT_LIST_HEAD(&nsslist); - result = nsswitch_parse(&nsslist); - if (result) { + status = nsswitch_parse(&nsslist); + if (status) { error(ap->logopt, "can't to read name service switch config."); + result = 1; break; } head = &nsslist; list_for_each(p, head) { - int status; - this = list_entry(p, struct nss_source, list); debug(ap->logopt, @@ -721,6 +721,7 @@ int lookup_nss_mount(struct autofs_point struct list_head *head, *p; struct nss_source *this; struct map_source *map; + enum nsswitch_status status; int result = 0; /* @@ -775,8 +776,8 @@ int lookup_nss_mount(struct autofs_point INIT_LIST_HEAD(&nsslist); - result = nsswitch_parse(&nsslist); - if (result) { + status = nsswitch_parse(&nsslist); + if (status) { error(ap->logopt, "can't to read name service switch config."); result = 1; @@ -961,3 +962,58 @@ next: return 1; } +/* Return with cache readlock held */ +struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key) +{ + struct master_mapent *entry = ap->entry; + struct map_source *map; + struct mapent_cache *mc; + struct mapent *me; + + pthread_cleanup_push(master_source_lock_cleanup, entry); + master_source_readlock(entry); + map = entry->first; + while (map) { + mc = map->mc; + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me) + break; + cache_unlock(mc); + map = map->next; + } + pthread_cleanup_pop(1); + + return me; +} + +int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key) +{ + struct master_mapent *entry = ap->entry; + struct map_source *map; + struct mapent_cache *mc; + struct mapent *me; + int ret = 0; + + pthread_cleanup_push(master_source_lock_cleanup, entry); + master_source_readlock(entry); + map = entry->first; + while (map) { + mc = map->mc; + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me) { + close(me->ioctlfd); + me->ioctlfd = -1; + cache_unlock(mc); + ret = 1; + break; + } + cache_unlock(mc); + map = map->next; + } + pthread_cleanup_pop(1); + + return ret; +} + diff --git a/daemon/state.c b/daemon/state.c index e74674a..caeb3e3 100644 --- a/daemon/state.c +++ b/daemon/state.c @@ -103,7 +103,6 @@ void expire_cleanup(void *arg) /* Check to see if expire process finished */ if (thid == ap->exp_thread) { ap->exp_thread = 0; - st_set_thid(ap, 0); switch (ap->state) { case ST_EXPIRE: @@ -174,7 +173,7 @@ static unsigned int st_ready(struct auto ap->state = ST_READY; if (ap->submount) - master_signal_submount(ap); + master_signal_submount(ap, MASTER_SUBMNT_CONTINUE); return 1; } @@ -362,7 +361,7 @@ static void *do_readmap(void *arg) while (me) { /* TODO: check return of do_... */ if (me->age < now) { - if (!tree_is_mounted(mnts, me->key)) + if (!tree_is_mounted(mnts, me->key, MNTS_REAL)) do_umount_autofs_direct(ap, mnts, me); else debug(ap->logopt, @@ -586,18 +585,14 @@ int st_add_task(struct autofs_point *ap, state_mutex_unlock(ap); - status = pthread_mutex_lock(&mutex); - if (status) - fatal(status); + st_mutex_lock(); signaled = 1; status = pthread_cond_signal(&cond); if (status) fatal(status); - status = pthread_mutex_unlock(&mutex); - if (status) - fatal(status); + st_mutex_unlock(); return 1; } @@ -620,9 +615,7 @@ int st_add_task(struct autofs_point *ap, INIT_LIST_HEAD(&new->list); INIT_LIST_HEAD(&new->pending); - status = pthread_mutex_lock(&mutex); - if (status) - fatal(status); + st_mutex_lock(); head = &state_queue; @@ -648,9 +641,7 @@ int st_add_task(struct autofs_point *ap, if (status) fatal(status); - status = pthread_mutex_unlock(&mutex); - if (status) - fatal(status); + st_mutex_unlock(); return 1; } diff --git a/include/automount.h b/include/automount.h index a689046..b10cfad 100644 --- a/include/automount.h +++ b/include/automount.h @@ -224,6 +224,8 @@ int lookup_ghost(struct autofs_point *ap int lookup_nss_mount(struct autofs_point *ap, const char *name, int name_len); void lookup_close_lookup(struct autofs_point *ap); int lookup_prune_cache(struct autofs_point *ap, time_t age); +struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key); +int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key); #ifdef MODULE_LOOKUP int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context); @@ -313,9 +315,9 @@ int ncat_path(char *buf, size_t len, /* mount table utilities */ -#define MNTS_ALL 0x0000 -#define MNTS_REAL 0x0001 -#define MNTS_AUTOFS 0x0002 +#define MNTS_ALL 0x0001 +#define MNTS_REAL 0x0002 +#define MNTS_AUTOFS 0x0004 struct mnt_list { char *path; @@ -356,7 +358,7 @@ void tree_free_mnt_tree(struct mnt_list struct mnt_list *tree_make_mnt_tree(const char *table, const char *path); int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include); int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path); -int tree_is_mounted(struct mnt_list *mnts, const char *path); +int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type); /* Core automount definitions */ diff --git a/include/master.h b/include/master.h index 57760a6..ada18d4 100644 --- a/include/master.h +++ b/include/master.h @@ -20,6 +20,10 @@ #ifndef MASTER_H #define MASTER_H +#define MASTER_SUBMNT_WAIT 0 +#define MASTER_SUBMNT_CONTINUE 1 +#define MASTER_SUBMNT_JOIN 2 + struct map_source { char *type; char *format; @@ -94,7 +98,7 @@ void master_free_mapent(struct master_ma struct master *master_new(const char *, unsigned int, unsigned int); int master_read_master(struct master *, time_t, int); void master_notify_submounts(struct autofs_point *, enum states); -void master_signal_submount(struct autofs_point *); +void master_signal_submount(struct autofs_point *, unsigned int); void master_notify_state_change(struct master *, int); int master_mount_mounts(struct master *, time_t, int); int master_list_empty(struct master *); diff --git a/include/state.h b/include/state.h index 69355b0..ea4c62a 100644 --- a/include/state.h +++ b/include/state.h @@ -59,6 +59,20 @@ struct expire_args { int status; /* Return status */ }; +#define expire_args_mutex_lock(ea) \ +do { \ + int status = pthread_mutex_lock(&ea->mutex); \ + if (status) \ + fatal(status); \ +} while (0) + +#define expire_args_mutex_unlock(ea) \ +do { \ + int status = pthread_mutex_unlock(&ea->mutex); \ + if (status) \ + fatal(status); \ +} while (0) + struct readmap_args { pthread_mutex_t mutex; pthread_cond_t cond; @@ -75,4 +89,18 @@ int st_add_task(struct autofs_point *, e void st_remove_tasks(struct autofs_point *); int st_start_handler(void); +#define st_mutex_lock() \ +do { \ + int status = pthread_mutex_lock(&mutex); \ + if (status) \ + fatal(status); \ +} while (0) + +#define st_mutex_unlock() \ +do { \ + int status = pthread_mutex_unlock(&mutex); \ + if (status) \ + fatal(status); \ +} while (0) + #endif diff --git a/lib/master.c b/lib/master.c index 6bf21ad..d5e58d2 100644 --- a/lib/master.c +++ b/lib/master.c @@ -754,15 +754,20 @@ int master_read_master(struct master *ma static void notify_submounts(struct autofs_point *ap, enum states state) { - struct list_head *p; + struct list_head *head, *p; struct autofs_point *this; + pthread_t thid; int status; mounts_mutex_lock(ap); - list_for_each(p, &ap->submounts) { + head = &ap->submounts; + p = head->next; + while (p != head) { this = list_entry(p, struct autofs_point, mounts); + p = p->next; + if (!list_empty(&this->submounts)) notify_submounts(this, state); @@ -777,11 +782,19 @@ static void notify_submounts(struct auto state_mutex_unlock(this); - ap->mounts_signaled = 0; - while (!ap->mounts_signaled) { + thid = this->thid; + ap->mounts_signaled = MASTER_SUBMNT_WAIT; + while (ap->mounts_signaled == MASTER_SUBMNT_WAIT) { status = pthread_cond_wait(&ap->mounts_cond, &ap->mounts_mutex); if (status) fatal(status); + if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) { + mounts_mutex_unlock(ap); + status = pthread_join(thid, NULL); + if (status) + fatal(status); + mounts_mutex_lock(ap); + } } } @@ -801,7 +814,7 @@ void master_notify_submounts(struct auto return; } -void master_signal_submount(struct autofs_point *ap) +void master_signal_submount(struct autofs_point *ap, unsigned int join) { int status; @@ -810,7 +823,10 @@ void master_signal_submount(struct autof mounts_mutex_lock(ap->parent); - ap->parent->mounts_signaled = 1; + if (join) + ap->parent->mounts_signaled = 1; + else + ap->parent->mounts_signaled = 2; status = pthread_cond_signal(&ap->parent->mounts_cond); if (status) fatal(status); diff --git a/lib/mounts.c b/lib/mounts.c index dd73f9f..b11c4c7 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -744,7 +744,7 @@ int tree_find_mnt_ents(struct mnt_list * return 0; } -int tree_is_mounted(struct mnt_list *mnts, const char *path) +int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type) { struct list_head *p; struct list_head list; @@ -760,13 +760,27 @@ int tree_is_mounted(struct mnt_list *mnt mptr = list_entry(p, struct mnt_list, list); - /* We only want real mounts */ - if (!strcmp(mptr->fs_type, "autofs")) - continue; + if (type) { + unsigned int autofs_fs; - mounted++; - } + autofs_fs = !strcmp(mptr->fs_type, "autofs"); + if (type & MNTS_REAL) { + if (!autofs_fs) { + mounted = 1; + break; + } + } else if (type & MNTS_AUTOFS) { + if (autofs_fs) { + mounted = 1; + break; + } + } else { + mounted = 1; + break; + } + } + } return mounted; } diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c index 95fe00d..9bccdd1 100644 --- a/modules/mount_autofs.c +++ b/modules/mount_autofs.c @@ -201,7 +201,7 @@ int mount_mount(struct autofs_point *ap, mounts_mutex_lock(ap); - if (pthread_create(&thid, &thread_attr, handle_mounts, nap)) { + if (pthread_create(&thid, NULL, handle_mounts, nap)) { crit(ap->logopt, MODPREFIX "failed to create mount handler thread for %s", diff --git a/modules/parse_sun.c b/modules/parse_sun.c index c6dffef..6007828 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -839,7 +839,7 @@ static int parse_mapent(const char *ent, l = chunklen(p, check_colon(p)); ent = dequote(p, l, logopt); if (!ent) { - error(logopt, MODPREFIX "out of memory"); + warn(logopt, MODPREFIX "null location or out of memory"); free(myoptions); free(loc); return 0; @@ -1056,7 +1056,7 @@ int parse_mount(struct autofs_point *ap, } if (!path) { - error(ap->logopt, MODPREFIX "out of memory"); + warn(ap->logopt, MODPREFIX "null path or out of memory"); cache_readlock(mc); cache_multi_lock(mc); cache_delete_offset_list(mc, name); @@ -1174,6 +1174,7 @@ int parse_mount(struct autofs_point *ap, return rv; } else { /* Normal (and non-root multi-mount) entries */ + struct autofs_point *oap = ap; char *loc; int loclen; int l; @@ -1185,14 +1186,11 @@ int parse_mount(struct autofs_point *ap, free(options); return 1; } -/* - if (*p == ':') - p++; /* Sun escape for entries starting with / */ /* -*/ + l = chunklen(p, check_colon(p)); loc = dequote(p, l, ap->logopt); if (!loc) { - error(ap->logopt, MODPREFIX "out of memory"); + warn(ap->logopt, MODPREFIX "null location or out of memory"); free(options); return 1; } @@ -1216,7 +1214,8 @@ int parse_mount(struct autofs_point *ap, l = chunklen(p, check_colon(p)); ent = dequote(p, l, ap->logopt); if (!ent) { - error(ap->logopt, MODPREFIX "out of memory"); + warn(ap->logopt, + MODPREFIX "null location or out of memory"); free(loc); free(options); return 1; @@ -1277,13 +1276,24 @@ int parse_mount(struct autofs_point *ap, * If it's a multi-mount insert the triggers * These are always direct mount triggers so root = "" */ - cache_readlock(mc); - me = cache_lookup_distinct(mc, name); - if (me && me->multi) { - char *m_key = me->multi->key; + if (ap->submount) + oap = ap->parent; + + me = lookup_source_mapent(oap, name); + if (me) { + char *m_key; int start; char *base, *m_root; + mc = me->source->mc; + + if (!me->multi) { + cache_unlock(mc); + return rv; + } + + m_key = me->multi->key; + if (*m_key == '/') { m_root = m_key; start = strlen(m_key); @@ -1308,14 +1318,14 @@ int parse_mount(struct autofs_point *ap, base = &me->key[start]; cache_multi_lock(mc); - if (!mount_multi_triggers(ap, m_root, me->multi, base)) { + if (!mount_multi_triggers(oap, m_root, me->multi, base)) { error(ap->logopt, MODPREFIX "failed to mount offset triggers"); rv = 1; } cache_multi_unlock(mc); + cache_unlock(mc); } - cache_unlock(mc); } return rv; }