1 autofs-5.0.4 - improve manual umount recovery
3 From: Ian Kent <raven@themaw.net>
5 The check for manually umounted mounts in the expire of direct mounts is
6 racy and the check itself is inadequate in that it can incorrectly clear
7 the descriptor of an active mount. Also, we do a similar test following
8 the expire which is a waste since we can catch this on the next expire.
9 So these two tests have been combined and the check done only prior to
10 the expire. In the indirect expire we don't have a check at all so we
15 daemon/direct.c | 28 ++++++++++------------------
16 daemon/indirect.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
17 3 files changed, 57 insertions(+), 19 deletions(-)
20 diff --git a/CHANGELOG b/CHANGELOG
21 index 5e01812..89aaa99 100644
25 - fix kernel includes.
26 - dont umount existing direct mount on master re-read.
27 - fix incorrect shutdown introduced by library relaod fixes.
28 +- improve manual umount recovery.
30 4/11/2008 autofs-5.0.4
31 -----------------------
32 diff --git a/daemon/direct.c b/daemon/direct.c
33 index 4f4ff20..1ed2b15 100644
36 @@ -881,13 +881,14 @@ void *expire_proc_direct(void *arg)
37 * avoid maintaining a file handle for control
38 * functions as once it's mounted all opens are
39 * directed to the mount not the trigger.
40 - * But first expire possible rootless offsets first.
43 - /* Offsets always have a real mount at their base */
44 + /* Check for manual umount */
45 cache_writelock(me->mc);
46 - if (strstr(next->opts, "offset")) {
47 - ops->close(ap->logopt, me->ioctlfd);
48 + if (me->ioctlfd != -1 &&
49 + fstat(ioctlfd, &st) != -1 &&
50 + !count_mounts(ap->logopt, next->path, st.st_dev)) {
51 + ops->close(ap->logopt, ioctlfd);
54 pthread_setcancelstate(cur_state, NULL);
55 @@ -904,15 +905,6 @@ void *expire_proc_direct(void *arg)
59 - cache_writelock(me->mc);
60 - if (me->ioctlfd != -1 &&
61 - fstat(ioctlfd, &st) != -1 &&
62 - !count_mounts(ap->logopt, next->path, st.st_dev)) {
63 - ops->close(ap->logopt, ioctlfd);
66 - cache_unlock(me->mc);
68 pthread_setcancelstate(cur_state, NULL);
71 @@ -1068,7 +1060,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
72 map = ap->entry->maps;
76 + cache_writelock(mc);
77 me = cache_lookup_ino(mc, pkt->dev, pkt->ino);
80 @@ -1345,7 +1337,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
85 + cache_writelock(mc);
86 me = cache_lookup_ino(mc, pkt->dev, pkt->ino);
89 @@ -1367,10 +1359,10 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
91 if (me->ioctlfd != -1) {
92 /* Maybe someone did a manual umount, clean up ! */
93 - ioctlfd = me->ioctlfd;
97 - ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
99 + ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
103 diff --git a/daemon/indirect.c b/daemon/indirect.c
104 index 2539282..bc39e63 100644
105 --- a/daemon/indirect.c
106 +++ b/daemon/indirect.c
107 @@ -428,8 +428,53 @@ void *expire_proc_indirect(void *arg)
108 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
109 if (strstr(next->opts, "indirect"))
110 master_notify_submount(ap, next->path, ap->state);
111 - pthread_setcancelstate(cur_state, NULL);
112 + else if (strstr(next->opts, "offset")) {
113 + struct map_source *map;
114 + struct mapent_cache *mc = NULL;
115 + struct mapent *me = NULL;
118 + master_source_readlock(ap->entry);
120 + map = ap->entry->maps;
123 + cache_writelock(mc);
124 + me = cache_lookup_distinct(mc, next->path);
132 + master_source_unlock(ap->entry);
133 + pthread_setcancelstate(cur_state, NULL);
137 + /* Check for manual umount */
138 + if (me->ioctlfd != -1 &&
139 + (fstat(me->ioctlfd, &st) == -1 ||
140 + !count_mounts(ap->logopt, me->key, st.st_dev))) {
141 + if (is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL)) {
143 + "error: possible mtab mismatch %s",
146 + master_source_unlock(ap->entry);
147 + pthread_setcancelstate(cur_state, NULL);
150 + close(me->ioctlfd);
155 + master_source_unlock(ap->entry);
158 + pthread_setcancelstate(cur_state, NULL);