1
/* ----------------------------------------------------------------------- *
3
* state.c - state machine functions.
5
* Copyright 2006 Ian Kent <raven@themaw.net> - All Rights Reserved
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
10
* USA; either version 2 of the License, or (at your option) any later
11
* version; incorporated herein by reference.
13
* ----------------------------------------------------------------------- */
15
#include <sys/ioctl.h>
17
#include "automount.h"
19
/* Attribute to create detached thread */
20
extern pthread_attr_t th_attr_detached;
24
struct list_head list;
25
struct list_head pending;
26
struct autofs_point *ap;
33
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
34
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
35
static unsigned int signaled = 0;
36
static LIST_HEAD(state_queue);
38
static void st_set_thid(struct autofs_point *, pthread_t);
39
static void st_set_done(struct autofs_point *ap);
41
void st_mutex_lock(void)
43
int status = pthread_mutex_lock(&mutex);
48
void st_mutex_unlock(void)
50
int status = pthread_mutex_unlock(&mutex);
55
void dump_state_queue(void)
57
struct list_head *head = &state_queue;
58
struct list_head *p, *q;
60
logmsg("dumping queue");
62
list_for_each(p, head) {
63
struct state_queue *entry;
65
entry = list_entry(p, struct state_queue, list);
66
logmsg("queue list head path %s state %d busy %d",
67
entry->ap->path, entry->state, entry->busy);
69
list_for_each(q, &entry->pending) {
70
struct state_queue *this;
72
this = list_entry(q, struct state_queue, pending);
73
logmsg("queue list entry path %s state %d busy %d",
74
this->ap->path, this->state, this->busy);
79
void nextstate(int statefd, enum states next)
81
char buf[MAX_ERR_BUF];
83
if (write(statefd, &next, sizeof(next)) != sizeof(next)) {
84
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
85
logerr("write failed %s", estr);
90
* Handle expire thread cleanup and return the next state the system
91
* should enter as a result.
93
void expire_cleanup(void *arg)
95
struct ioctl_ops *ops = get_ioctl_ops();
96
pthread_t thid = pthread_self();
97
struct expire_args *ec;
98
struct autofs_point *ap;
100
enum states next = ST_INVAL;
102
ec = (struct expire_args *) arg;
104
success = ec->status;
109
"got thid %lu path %s stat %d",
110
(unsigned long) thid, ap->path, success);
112
/* Check to see if expire process finished */
113
if (thid == ap->exp_thread) {
124
* If we're a submount and we've just pruned or
125
* expired everything away, try to shut down.
127
* Since we use the the fact that a mount will not
128
* expire for at least ap->exp_timeout to avoid a
129
* mount <-> expire race we need to wait before
130
* letting a submount expire away. We also need
131
* them to go away fairly quickly so the owner
132
* mount expires in a reasonable time. Just skip
133
* one expire check after it's no longer busy before
134
* allowing it to shutdown.
136
if (ap->submount && !success) {
137
rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
138
if (!rv && idle && ap->submount > 1) {
139
next = ST_SHUTDOWN_PENDING;
143
if (ap->submount++ == 0)
148
alarm_add(ap, ap->exp_runfreq);
156
case ST_SHUTDOWN_PENDING:
158
* If we reveive a mount request while trying to
159
* shutdown return to ready state unless we have
160
* been signaled to shutdown.
162
rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
163
if (!idle && !ap->shutdown) {
166
alarm_add(ap, ap->exp_runfreq);
171
#ifdef ENABLE_IGNORE_BUSY_MOUNTS
177
/* Failed shutdown returns to ready */
178
warn(ap->logopt, "filesystem %s still busy", ap->path);
180
alarm_add(ap, ap->exp_runfreq);
185
case ST_SHUTDOWN_FORCE:
190
error(ap->logopt, "bad state %d", ap->state);
193
if (next != ST_INVAL) {
195
"sigchld: exp %lu finished, switching from %d to %d",
196
(unsigned long) thid, ap->state, next);
200
if (next != ST_INVAL)
201
__st_add_task(ap, next);
210
static unsigned int st_ready(struct autofs_point *ap)
213
"st_ready(): state = %d path %s", ap->state, ap->path);
216
ap->state = ST_READY;
228
* Generate expiry messages. If "now" is true, timeouts are ignored.
230
* Returns: ERROR - error
231
* STARTED - expiry process started
232
* DONE - nothing to expire
233
* PARTIAL - partial expire
236
void expire_proc_cleanup(void *arg)
238
struct expire_args *ea;
241
ea = (struct expire_args *) arg;
243
status = pthread_mutex_unlock(&ea->mutex);
247
status = pthread_cond_destroy(&ea->cond);
251
status = pthread_mutex_destroy(&ea->mutex);
260
static enum expire expire_proc(struct autofs_point *ap, int now)
263
struct expire_args *ea;
264
void *(*expire)(void *);
267
assert(ap->exp_thread == 0);
269
ea = malloc(sizeof(struct expire_args));
271
error(ap->logopt, "failed to malloc expire cond struct");
275
status = pthread_mutex_init(&ea->mutex, NULL);
279
status = pthread_cond_init(&ea->cond, NULL);
283
status = pthread_mutex_lock(&ea->mutex);
291
if (ap->type == LKP_INDIRECT)
292
expire = expire_proc_indirect;
294
expire = expire_proc_direct;
296
status = pthread_create(&thid, &th_attr_detached, expire, ea);
299
"expire thread create for %s failed", ap->path);
300
expire_proc_cleanup((void *) ea);
303
ap->exp_thread = thid;
304
st_set_thid(ap, thid);
306
pthread_cleanup_push(expire_proc_cleanup, ea);
308
debug(ap->logopt, "exp_proc = %lu path %s",
309
(unsigned long) ap->exp_thread, ap->path);
312
while (!ea->signaled) {
313
status = pthread_cond_wait(&ea->cond, &ea->mutex);
318
pthread_cleanup_pop(1);
323
static void do_readmap_cleanup(void *arg)
325
struct readmap_args *ra;
326
struct autofs_point *ap;
328
ra = (struct readmap_args *) arg;
334
ap->readmap_thread = 0;
339
alarm_add(ap, ap->exp_runfreq);
348
static void tree_mnts_cleanup(void *arg)
350
struct mnt_list *mnts = (struct mnt_list *) arg;
351
tree_free_mnt_tree(mnts);
355
static void do_readmap_mount(struct autofs_point *ap, struct mnt_list *mnts,
356
struct map_source *map, struct mapent *me, time_t now)
358
struct mapent_cache *nc;
359
struct mapent *ne, *nested, *valid;
361
nc = ap->entry->master->nc;
363
ne = cache_lookup_distinct(nc, me->key);
365
nested = cache_partial_match(nc, me->key);
368
"removing invalid nested null entry %s",
370
nested = cache_partial_match(nc, me->key);
372
cache_delete(nc, nested->key);
376
if (me->age < now || (ne && map->master_line > ne->age)) {
378
* The map instance may have changed, such as the map name or
379
* the mount options, but the direct map entry may still exist
380
* in one of the other maps. If so then update the new cache
381
* entry device and inode so we can find it at lookup. Later,
382
* the mount for the new cache entry will just update the
385
* TODO: how do we recognise these orphaned map instances. We
386
* can't just delete these instances when the cache becomes
387
* empty because that is a valid state for a master map entry.
388
* This is becuase of the requirement to continue running with
389
* an empty cache awaiting a map re-load.
391
valid = lookup_source_valid_mapent(ap, me->key, LKP_DISTINCT);
392
if (valid && valid->mc == me->mc) {
394
* We've found a map entry that has been removed from
395
* the current cache so there is no need to update it.
396
* The stale entry will be dealt with when we prune the
399
cache_unlock(valid->mc);
403
struct mapent_cache *vmc = valid->mc;
406
"updating cache entry for valid direct trigger %s",
408
cache_writelock(vmc);
409
valid = cache_lookup_distinct(vmc, me->key);
410
/* Take over the mount if there is one */
411
valid->ioctlfd = me->ioctlfd;
413
/* Set device and inode number of the new mapent */
414
cache_set_ino_index(vmc, me->key, me->dev, me->ino);
416
} else if (!tree_is_mounted(mnts, me->key, MNTS_REAL))
417
do_umount_autofs_direct(ap, mnts, me);
420
"%s is mounted", me->key);
422
do_mount_autofs_direct(ap, mnts, me);
427
static void *do_readmap(void *arg)
429
struct autofs_point *ap;
430
struct map_source *map;
431
struct mapent_cache *nc, *mc;
432
struct readmap_args *ra;
433
struct mnt_list *mnts;
437
ra = (struct readmap_args *) arg;
439
status = pthread_mutex_lock(&ra->mutex);
447
status = pthread_cond_signal(&ra->cond);
449
error(ap->logopt, "failed to signal expire condition");
450
pthread_mutex_unlock(&ra->mutex);
454
status = pthread_mutex_unlock(&ra->mutex);
458
pthread_cleanup_push(do_readmap_cleanup, ra);
460
info(ap->logopt, "re-reading map for %s", ap->path);
462
pthread_cleanup_push(master_mutex_lock_cleanup, NULL);
464
status = lookup_nss_read_map(ap, NULL, now);
467
pthread_cleanup_pop(1);
469
if (ap->type == LKP_INDIRECT) {
470
lookup_prune_cache(ap, now);
471
status = lookup_ghost(ap, ap->path);
475
mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
476
pthread_cleanup_push(tree_mnts_cleanup, mnts);
477
pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
478
master_source_readlock(ap->entry);
479
nc = ap->entry->master->nc;
481
pthread_cleanup_push(cache_lock_cleanup, nc);
482
map = ap->entry->maps;
484
/* Is map source up to date or no longer valid */
490
pthread_cleanup_push(cache_lock_cleanup, mc);
492
me = cache_enumerate(mc, NULL);
494
do_readmap_mount(ap, mnts, map, me, now);
495
me = cache_enumerate(mc, me);
497
lookup_prune_one_cache(ap, map->mc, now);
498
pthread_cleanup_pop(1);
502
pthread_cleanup_pop(1);
503
pthread_cleanup_pop(1);
504
pthread_cleanup_pop(1);
505
lookup_prune_cache(ap, now);
508
pthread_cleanup_pop(1);
513
static void st_readmap_cleanup(void *arg)
515
struct readmap_args *ra;
518
ra = (struct readmap_args *) arg;
520
status = pthread_mutex_unlock(&ra->mutex);
524
status = pthread_cond_destroy(&ra->cond);
528
status = pthread_mutex_destroy(&ra->mutex);
535
static unsigned int st_readmap(struct autofs_point *ap)
538
struct readmap_args *ra;
540
int now = time(NULL);
542
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
544
assert(ap->state == ST_READY);
545
assert(ap->readmap_thread == 0);
547
ap->state = ST_READMAP;
549
ra = malloc(sizeof(struct readmap_args));
551
error(ap->logopt, "failed to malloc reamap cond struct");
552
/* It didn't work: return to ready */
555
alarm_add(ap, ap->exp_runfreq);
559
status = pthread_mutex_init(&ra->mutex, NULL);
563
status = pthread_cond_init(&ra->cond, NULL);
567
status = pthread_mutex_lock(&ra->mutex);
574
status = pthread_create(&thid, &th_attr_detached, do_readmap, ra);
576
error(ap->logopt, "read map thread create failed");
577
st_readmap_cleanup(ra);
579
/* It didn't work: return to ready */
582
alarm_add(ap, ap->exp_runfreq);
585
ap->readmap_thread = thid;
586
st_set_thid(ap, thid);
588
pthread_cleanup_push(st_readmap_cleanup, ra);
591
while (!ra->signaled) {
592
status = pthread_cond_wait(&ra->cond, &ra->mutex);
597
pthread_cleanup_pop(1);
602
static unsigned int st_prepare_shutdown(struct autofs_point *ap)
606
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
608
assert(ap->state == ST_READY || ap->state == ST_EXPIRE);
609
ap->state = ST_SHUTDOWN_PENDING;
611
/* Unmount everything */
612
exp = expire_proc(ap, 1);
616
/* It didn't work: return to ready */
618
alarm_add(ap, ap->exp_runfreq);
628
static unsigned int st_force_shutdown(struct autofs_point *ap)
632
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
634
assert(ap->state == ST_READY || ap->state == ST_EXPIRE);
635
ap->state = ST_SHUTDOWN_FORCE;
637
/* Unmount everything */
638
exp = expire_proc(ap, 1);
642
/* It didn't work: return to ready */
644
alarm_add(ap, ap->exp_runfreq);
654
static unsigned int st_shutdown(struct autofs_point *ap)
656
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
658
assert(ap->state == ST_SHUTDOWN_PENDING || ap->state == ST_SHUTDOWN_FORCE);
660
ap->state = ST_SHUTDOWN;
661
nextstate(ap->state_pipe[1], ST_SHUTDOWN);
666
static unsigned int st_prune(struct autofs_point *ap)
668
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
670
assert(ap->state == ST_READY);
671
ap->state = ST_PRUNE;
673
switch (expire_proc(ap, 1)) {
677
alarm_add(ap, ap->exp_runfreq);
687
static unsigned int st_expire(struct autofs_point *ap)
689
debug(ap->logopt, "state %d path %s", ap->state, ap->path);
691
assert(ap->state == ST_READY);
692
ap->state = ST_EXPIRE;
694
switch (expire_proc(ap, 0)) {
698
alarm_add(ap, ap->exp_runfreq);
708
static struct state_queue *st_alloc_task(struct autofs_point *ap, enum states state)
710
struct state_queue *task;
712
task = malloc(sizeof(struct state_queue));
715
memset(task, 0, sizeof(struct state_queue));
720
INIT_LIST_HEAD(&task->list);
721
INIT_LIST_HEAD(&task->pending);
727
* Insert alarm entry on ordered list.
728
* State queue mutex and ap state mutex, in that order, must be held.
730
int __st_add_task(struct autofs_point *ap, enum states state)
732
struct list_head *head;
733
struct list_head *p, *q;
734
struct state_queue *new;
735
unsigned int empty = 1;
738
/* Task termination marker, poke state machine */
739
if (state == ST_READY) {
743
status = pthread_cond_signal(&cond);
750
if (ap->state == ST_SHUTDOWN)
753
if (state == ST_SHUTDOWN)
754
return st_shutdown(ap);
758
/* Add to task queue for autofs_point ? */
759
list_for_each(p, head) {
760
struct state_queue *task;
762
task = list_entry(p, struct state_queue, list);
769
/* Don't add duplicate tasks */
770
if ((task->state == state && !task->done) ||
771
(ap->state == ST_SHUTDOWN_PENDING ||
772
ap->state == ST_SHUTDOWN_FORCE))
775
/* No pending tasks */
776
if (list_empty(&task->pending)) {
777
new = st_alloc_task(ap, state);
779
list_add_tail(&new->pending, &task->pending);
783
list_for_each(q, &task->pending) {
784
struct state_queue *p_task;
786
p_task = list_entry(q, struct state_queue, pending);
788
if (p_task->state == state ||
789
(ap->state == ST_SHUTDOWN_PENDING ||
790
ap->state == ST_SHUTDOWN_FORCE))
794
new = st_alloc_task(ap, state);
796
list_add_tail(&new->pending, &task->pending);
802
new = st_alloc_task(ap, state);
804
list_add(&new->list, head);
807
/* Added task, encourage state machine */
809
status = pthread_cond_signal(&cond);
816
int st_add_task(struct autofs_point *ap, enum states state)
821
ret = __st_add_task(ap, state);
828
* Remove state queue tasks for ap.
829
* State queue mutex and ap state mutex, in that order, must be held.
831
void st_remove_tasks(struct autofs_point *ap)
833
struct list_head *head;
834
struct list_head *p, *q;
835
struct state_queue *task, *waiting;
842
if (list_empty(head)) {
849
task = list_entry(p, struct state_queue, list);
856
/* We only cancel readmap, prune and expire */
857
if (task->state == ST_EXPIRE ||
858
task->state == ST_PRUNE ||
859
task->state == ST_READMAP)
863
q = (&task->pending)->next;
864
while(q != &task->pending) {
865
waiting = list_entry(q, struct state_queue, pending);
868
/* Don't remove existing shutdown task */
869
if (waiting->state != ST_SHUTDOWN_PENDING &&
870
waiting->state != ST_SHUTDOWN_FORCE) {
871
list_del(&waiting->pending);
878
status = pthread_cond_signal(&cond);
887
static int st_task_active(struct autofs_point *ap, enum states state)
889
struct list_head *head;
890
struct list_head *p, *q;
891
struct state_queue *task, *waiting;
892
unsigned int active = 0;
898
list_for_each(p, head) {
899
task = list_entry(p, struct state_queue, list);
904
if (task->state == state) {
909
if (state == ST_ANY) {
914
list_for_each(q, &task->pending) {
915
waiting = list_entry(q, struct state_queue, pending);
917
if (waiting->state == state) {
922
if (state == ST_ANY) {
934
int st_wait_task(struct autofs_point *ap, enum states state, unsigned int seconds)
936
unsigned int wait = 0;
937
unsigned int duration = 0;
941
struct timespec t = { 0, 200000000 };
944
while (nanosleep(&t, &r) == -1 && errno == EINTR)
945
memcpy(&t, &r, sizeof(struct timespec));
952
if (!st_task_active(ap, state)) {
957
if (seconds && duration >= seconds)
964
int st_wait_state(struct autofs_point *ap, enum states state)
967
struct timespec t = { 0, 200000000 };
970
while (nanosleep(&t, &r) == -1 && errno == EINTR)
971
memcpy(&t, &r, sizeof(struct timespec));
974
if (ap->state == state) {
985
static int run_state_task(struct state_queue *task)
987
struct autofs_point *ap;
988
enum states next_state, state;
989
unsigned long ret = 0;
992
next_state = task->state;
996
if (next_state != state) {
997
switch (next_state) {
1003
ret = st_expire(ap);
1007
ret = st_readmap(ap);
1010
case ST_SHUTDOWN_PENDING:
1011
ret = st_prepare_shutdown(ap);
1014
case ST_SHUTDOWN_FORCE:
1015
ret = st_force_shutdown(ap);
1019
error(ap->logopt, "bad next state %d", next_state);
1026
static void st_set_thid(struct autofs_point *ap, pthread_t thid)
1028
struct list_head *p, *head = &state_queue;
1029
struct state_queue *task;
1031
list_for_each(p, head) {
1032
task = list_entry(p, struct state_queue, list);
1033
if (task->ap == ap) {
1041
/* Requires state mutex to be held */
1042
static void st_set_done(struct autofs_point *ap)
1044
struct list_head *p, *head;
1045
struct state_queue *task;
1047
head = &state_queue;
1048
list_for_each(p, head) {
1049
task = list_entry(p, struct state_queue, list);
1050
if (task->ap == ap) {
1059
static void *st_queue_handler(void *arg)
1061
struct list_head *head;
1062
struct list_head *p;
1063
struct timespec wait;
1071
* If the state queue list is empty, wait until an
1074
head = &state_queue;
1075
gettimeofday(&now, NULL);
1076
wait.tv_sec = now.tv_sec + 1;
1077
wait.tv_nsec = now.tv_usec * 1000;
1079
while (list_empty(head)) {
1080
status = pthread_cond_timedwait(&cond, &mutex, &wait);
1082
if (status == ETIMEDOUT)
1090
struct state_queue *task;
1092
task = list_entry(p, struct state_queue, list);
1096
list_del(&task->list);
1103
ret = run_state_task(task);
1105
list_del(&task->list);
1111
gettimeofday(&now, NULL);
1112
wait.tv_sec = now.tv_sec + 1;
1113
wait.tv_nsec = now.tv_usec * 1000;
1117
status = pthread_cond_timedwait(&cond, &mutex, &wait);
1119
if (status == ETIMEDOUT)
1125
head = &state_queue;
1128
struct state_queue *task, *next;
1130
task = list_entry(p, struct state_queue, list);
1134
/* Start a new task */
1137
ret = run_state_task(task);
1143
/* Still starting up */
1148
pthread_cancel(task->thid);
1158
/* No more tasks for this queue */
1159
if (list_empty(&task->pending)) {
1160
list_del(&task->list);
1166
next = list_entry((&task->pending)->next,
1167
struct state_queue, pending);
1169
list_del_init(&next->pending);
1170
list_add_tail(&next->list, p);
1172
list_del(&task->list);
1176
if (list_empty(head))
1182
int st_start_handler(void)
1185
pthread_attr_t attrs;
1186
pthread_attr_t *pattrs = &attrs;
1189
status = pthread_attr_init(pattrs);
1193
pthread_attr_setdetachstate(pattrs, PTHREAD_CREATE_DETACHED);
1194
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
1195
pthread_attr_setstacksize(pattrs, PTHREAD_STACK_MIN*4);
1199
status = pthread_create(&thid, pattrs, st_queue_handler, NULL);
1201
pthread_attr_destroy(pattrs);