diff --git a/CHANGELOG b/CHANGELOG index 6fe9697..fe73ab8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,6 +24,7 @@ - review verbose message feedback and update. - correction for expire of multi-mounts. - spelling corrections to release notes (Jeff Moyer). +- expire individual submounts. 13/7/2006 autofs-5.0.1 rc1 -------------------------- diff --git a/daemon/direct.c b/daemon/direct.c index 4b6162b..b9c0f04 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -786,18 +786,23 @@ void *expire_proc_direct(void *arg) if (status) fatal(status); - master_notify_submounts(ap, ap->state); - /* Get a list of real mounts and expire them if possible */ mnts = get_mnt_list(_PROC_MOUNTS, "/", 0); for (next = mnts; next; next = next->next) { - /* Skip submounts */ - if (strstr(next->fs_type, "indirect")) - continue; + if (!strcmp(next->fs_type, "autofs")) { + /* + * If we have submounts check if this path lives below + * one of them and pass on state change. + */ + if (strstr(next->opts, "indirect")) { + master_notify_submount(ap, next->path, ap->state); + continue; + } - /* Skip offsets */ - if (strstr(next->opts, "offset")) - continue; + /* Skip offsets */ + if (strstr(next->opts, "offset")) + continue; + } /* * All direct mounts must be present in the map @@ -896,9 +901,10 @@ static void *do_expire_direct(void *arg) send_fail(mt->ioctlfd, mt->wait_queue_token); else { struct mapent *me; - me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT); + cache_readlock(mt->mc); + me = cache_lookup_distinct(mt->mc, mt->name); me->ioctlfd = -1; - cache_unlock(me->source->mc); + cache_unlock(mt->mc); send_ready(mt->ioctlfd, mt->wait_queue_token); close(mt->ioctlfd); } @@ -1195,9 +1201,10 @@ cont: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); if (status) { struct mapent *me; - me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT); + cache_readlock(mt->mc); + me = cache_lookup_distinct(mt->mc, mt->name); me->ioctlfd = mt->ioctlfd; - cache_unlock(me->source->mc); + cache_unlock(mt->mc); send_ready(mt->ioctlfd, mt->wait_queue_token); msg("mounted %s", mt->name); } else { diff --git a/daemon/indirect.c b/daemon/indirect.c index 8748413..dadb9ee 100644 --- a/daemon/indirect.c +++ b/daemon/indirect.c @@ -430,16 +430,22 @@ void *expire_proc_indirect(void *arg) if (status) fatal(status); - master_notify_submounts(ap, ap->state); - /* Get a list of real mounts and expire them if possible */ mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0); for (next = mnts; next; next = next->next) { char *ind_key; int ret; - if (!strcmp(next->fs_type, "autofs")) + if (!strcmp(next->fs_type, "autofs")) { + /* + * If we have submounts check if this path lives below + * one of them and pass on the state change. + */ + if (strstr(next->opts, "indirect")) + master_notify_submount(ap, next->path, ap->state); + continue; + } /* * If the mount corresponds to an offset trigger then @@ -458,7 +464,7 @@ void *expire_proc_indirect(void *arg) */ me = lookup_source_mapent(ap, next->path, LKP_DISTINCT); if (!me && ind_key) - lookup_source_mapent(ap, ind_key, LKP_NORMAL); + me = lookup_source_mapent(ap, ind_key, LKP_NORMAL); if (!me) continue; diff --git a/include/automount.h b/include/automount.h index 90a9c7a..267c7d1 100644 --- a/include/automount.h +++ b/include/automount.h @@ -437,7 +437,6 @@ struct autofs_point { pthread_t exp_thread; /* Thread that is expiring */ pthread_t readmap_thread; /* Thread that is reading maps */ pthread_mutex_t state_mutex; /* Protect state changes */ - struct list_head state_queue; /* Pending state transitions */ enum states state; /* Current state */ int state_pipe[2]; /* State change router pipe */ unsigned dir_created; /* Directory created for this mount? */ diff --git a/include/master.h b/include/master.h index ada18d4..e25626d 100644 --- a/include/master.h +++ b/include/master.h @@ -97,7 +97,8 @@ void master_free_mapent_sources(struct m void master_free_mapent(struct master_mapent *); 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); +int master_submount_list_empty(struct autofs_point *ap); +int master_notify_submount(struct autofs_point *, const char *path, enum states); 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); diff --git a/lib/master.c b/lib/master.c index d76ffac..1d66542 100644 --- a/lib/master.c +++ b/lib/master.c @@ -95,7 +95,6 @@ int master_add_autofs_point(struct maste free(ap); return 0; } - INIT_LIST_HEAD(&ap->state_queue); status = pthread_mutex_init(&ap->mounts_mutex, NULL); if (status) { @@ -735,34 +734,68 @@ int master_read_master(struct master *ma return 1; } -void master_notify_submounts(struct autofs_point *ap, enum states state) +int master_submount_list_empty(struct autofs_point *ap) +{ + int res = 0; + + mounts_mutex_lock(ap); + if (list_empty(&ap->submounts)) + res = 1; + mounts_mutex_unlock(ap); + + return res; +} + +int master_notify_submount(struct autofs_point *ap, const char *path, enum states state) { struct list_head *head, *p; struct autofs_point *this; pthread_t thid; - int status; - - /* Initiate from master entries only */ - if (ap->submount || list_empty(&ap->submounts)) - return; + size_t plen = strlen(path); + int status, ret = 1; mounts_mutex_lock(ap); head = &ap->submounts; - p = head->next; + p = head->prev; while (p != head) { + size_t len; + this = list_entry(p, struct autofs_point, mounts); + p = p->prev; - p = p->next; + if (!master_submount_list_empty(this)) { + if (!master_notify_submount(this, path, state)) { + ret = 0; + break; + } + } + + len = strlen(this->path); - if (!list_empty(&this->submounts)) - master_notify_submounts(this, state); + /* Initial path not the same */ + if (strncmp(this->path, path, len)) + continue; + + /* + * Part of submount tree? + * We must wait till we get to submount itself. + * If it is tell caller by returning true. + */ + if (plen > len) { + /* Not part of this directory tree */ + if (path[len] != '/') + continue; + break; + } + + /* Now we have a submount to expire */ state_mutex_lock(this); if (this->state == ST_SHUTDOWN) { state_mutex_unlock(this); - continue; + break; } nextstate(this->state_pipe[1], state); @@ -775,17 +808,21 @@ void master_notify_submounts(struct auto status = pthread_cond_wait(&ap->mounts_cond, &ap->mounts_mutex); if (status) fatal(status); - if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) { - status = pthread_join(thid, NULL); - if (status) - fatal(status); - } } + + if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) { + status = pthread_join(thid, NULL); + if (status) + fatal(status); + } else + ret = 0; + + break; } mounts_mutex_unlock(ap); - return; + return ret; } void master_signal_submount(struct autofs_point *ap, unsigned int join) @@ -797,13 +834,13 @@ void master_signal_submount(struct autof mounts_mutex_lock(ap->parent); - if (join) { + ap->parent->mounts_signaled = join; + + if (join == MASTER_SUBMNT_JOIN) { /* We are finishing up */ ap->parent->submnt_count--; list_del(&ap->mounts); - ap->parent->mounts_signaled = 1; - } else - ap->parent->mounts_signaled = 2; + } status = pthread_cond_signal(&ap->parent->mounts_cond); if (status) diff --git a/lib/mounts.c b/lib/mounts.c index f446a6a..46131cd 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -149,7 +149,7 @@ struct mnt_list *get_mnt_list(const char mptr = list; last = NULL; while (mptr) { - if (len > strlen(mptr->path)) + if (len >= strlen(mptr->path)) break; last = mptr; mptr = mptr->next;