diff --git a/CHANGELOG b/CHANGELOG index bcd6e5c..88b6a47 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,7 @@ - fix nsswitch parser locking. - allow only one master map read task at a time. - fix misc memory leaks. +- mitigate manual umount of automounts where possible. 1/9/2006 autofs-5.0.1 rc2 ------------------------- diff --git a/daemon/direct.c b/daemon/direct.c index c92a745..ef96cc4 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -848,13 +848,14 @@ static int expire_direct(int ioctlfd, co static void mnts_cleanup(void *arg) { struct mnt_list *mnts = (struct mnt_list *) arg; - free_mnt_list(mnts); + tree_free_mnt_tree(mnts); return; } void *expire_proc_direct(void *arg) { struct mnt_list *mnts = NULL, *next; + struct list_head list, *p; struct expire_args *ea; struct expire_args ec; struct autofs_point *ap; @@ -886,10 +887,27 @@ void *expire_proc_direct(void *arg) left = 0; - /* Get a list of real mounts and expire them if possible */ - mnts = get_mnt_list(_PROC_MOUNTS, "/", 0); + mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/"); + + /* Get a list of mounts select real ones and expire them if possible */ + INIT_LIST_HEAD(&list); + if (!tree_get_mnt_list(mnts, &list, "/", 0)) { + ec.status = 0; + return NULL; + } pthread_cleanup_push(mnts_cleanup, mnts); - for (next = mnts; next; next = next->next) { + + list_for_each(p, &list) { + next = list_entry(p, struct mnt_list, list); + + /* + * All direct mounts must be present in the map + * entry cache. + */ + me = lookup_source_mapent(ap, next->path, LKP_DISTINCT); + if (!me) + continue; + if (!strcmp(next->fs_type, "autofs")) { /* * If we have submounts check if this path lives below @@ -897,27 +915,32 @@ void *expire_proc_direct(void *arg) */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); if (strstr(next->opts, "indirect")) { + cache_unlock(me->mc); master_notify_submount(ap, next->path, ap->state); pthread_setcancelstate(cur_state, NULL); continue; } - pthread_setcancelstate(cur_state, NULL); - - /* Skip offsets */ - if (strstr(next->opts, "offset")) - continue; - } - - if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE) - pthread_testcancel(); - /* - * All direct mounts must be present in the map - * entry cache. - */ - me = lookup_source_mapent(ap, next->path, LKP_DISTINCT); - if (!me) + if (!tree_is_mounted(mnts, next->path, MNTS_REAL)) { + /* + * Maybe a manual umount, repair. + * It will take ap->exp_timeout/4 for us to relaize + * this so user must still use USR1 signal to close + * the open file handle for mounts atop multi-mount + * triggers. There is no way that I'm aware of to + * to avoid maintaining a file handle for control + * functions as once it's mounted all opens are + * directed to the mount not the trigger. + */ + if (me->ioctlfd != -1) { + close(me->ioctlfd); + me->ioctlfd = -1; + } + } + cache_unlock(me->mc); + pthread_setcancelstate(cur_state, NULL); continue; + } if (me->ioctlfd >= 0) { /* Real mounts have an open ioctl fd */ @@ -928,6 +951,9 @@ void *expire_proc_direct(void *arg) continue; } + if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE) + pthread_testcancel(); + debug(ap->logopt, "send expire to trigger %s", next->path); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); @@ -1392,8 +1418,14 @@ int handle_packet_missing_direct(struct return 1; } - ioctlfd = open(me->key, O_RDONLY); - if (ioctlfd < 0) { + if (me->ioctlfd != -1) { + /* Maybe someone did a manual umount, clean up ! */ + ioctlfd = me->ioctlfd; + me->ioctlfd = -1; + } else + ioctlfd = open(me->key, O_RDONLY); + + if (ioctlfd == -1) { cache_unlock(mc); pthread_setcancelstate(state, NULL); crit(ap->logopt, "failed to create ioctl fd for %s", me->key); diff --git a/include/automount.h b/include/automount.h index 798cc50..89610ee 100644 --- a/include/automount.h +++ b/include/automount.h @@ -338,6 +338,7 @@ struct mnt_list { struct mnt_list *right; struct list_head self; struct list_head list; + struct list_head entries; struct list_head sublist; /* * Offset mount handling ie. add_ordered_list diff --git a/lib/mounts.c b/lib/mounts.c index 1e92ca5..a4f68c5 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -606,6 +606,7 @@ struct mnt_list *tree_make_mnt_tree(cons INIT_LIST_HEAD(&ent->self); INIT_LIST_HEAD(&ent->list); + INIT_LIST_HEAD(&ent->entries); INIT_LIST_HEAD(&ent->sublist); INIT_LIST_HEAD(&ent->ordered); @@ -824,8 +825,8 @@ int tree_find_mnt_ents(struct mnt_list * tree_find_mnt_ents(mnts->left, list, path); if (!strcmp(mnts->path, path)) { - INIT_LIST_HEAD(&mnts->list); - list_add(&mnts->list, list); + INIT_LIST_HEAD(&mnts->entries); + list_add(&mnts->entries, list); } self = &mnts->self; @@ -835,8 +836,8 @@ int tree_find_mnt_ents(struct mnt_list * this = list_entry(p, struct mnt_list, self); if (!strcmp(this->path, path)) { - INIT_LIST_HEAD(&this->list); - list_add(&this->list, list); + INIT_LIST_HEAD(&this->entries); + list_add(&this->entries, list); } } @@ -863,7 +864,7 @@ int tree_is_mounted(struct mnt_list *mnt list_for_each(p, &list) { struct mnt_list *mptr; - mptr = list_entry(p, struct mnt_list, list); + mptr = list_entry(p, struct mnt_list, entries); if (type) { unsigned int autofs_fs;