]>
Commit | Line | Data |
---|---|---|
e5fd101c PS |
1 | autofs-5.0.4 - improve manual umount recovery |
2 | ||
3 | From: Ian Kent <raven@themaw.net> | |
4 | ||
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 | |
11 | add one. | |
12 | --- | |
13 | ||
14 | CHANGELOG | 1 + | |
15 | daemon/direct.c | 28 ++++++++++------------------ | |
16 | daemon/indirect.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- | |
17 | 3 files changed, 57 insertions(+), 19 deletions(-) | |
18 | ||
19 | ||
20 | diff --git a/CHANGELOG b/CHANGELOG | |
21 | index 5e01812..89aaa99 100644 | |
22 | --- a/CHANGELOG | |
23 | +++ b/CHANGELOG | |
24 | @@ -45,6 +45,7 @@ | |
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. | |
29 | ||
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 | |
34 | --- a/daemon/direct.c | |
35 | +++ b/daemon/direct.c | |
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. | |
41 | */ | |
42 | ||
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); | |
52 | me->ioctlfd = -1; | |
53 | cache_unlock(me->mc); | |
54 | pthread_setcancelstate(cur_state, NULL); | |
55 | @@ -904,15 +905,6 @@ void *expire_proc_direct(void *arg) | |
56 | continue; | |
57 | } | |
58 | ||
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); | |
64 | - me->ioctlfd = -1; | |
65 | - } | |
66 | - cache_unlock(me->mc); | |
67 | - | |
68 | pthread_setcancelstate(cur_state, NULL); | |
69 | continue; | |
70 | } | |
71 | @@ -1068,7 +1060,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di | |
72 | map = ap->entry->maps; | |
73 | while (map) { | |
74 | mc = map->mc; | |
75 | - cache_readlock(mc); | |
76 | + cache_writelock(mc); | |
77 | me = cache_lookup_ino(mc, pkt->dev, pkt->ino); | |
78 | if (me) | |
79 | break; | |
80 | @@ -1345,7 +1337,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ | |
81 | } | |
82 | ||
83 | mc = map->mc; | |
84 | - cache_readlock(mc); | |
85 | + cache_writelock(mc); | |
86 | me = cache_lookup_ino(mc, pkt->dev, pkt->ino); | |
87 | if (me) | |
88 | break; | |
89 | @@ -1367,10 +1359,10 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ | |
90 | ||
91 | if (me->ioctlfd != -1) { | |
92 | /* Maybe someone did a manual umount, clean up ! */ | |
93 | - ioctlfd = me->ioctlfd; | |
94 | + close(me->ioctlfd); | |
95 | me->ioctlfd = -1; | |
96 | - } else | |
97 | - ops->open(ap->logopt, &ioctlfd, me->dev, me->key); | |
98 | + } | |
99 | + ops->open(ap->logopt, &ioctlfd, me->dev, me->key); | |
100 | ||
101 | if (ioctlfd == -1) { | |
102 | cache_unlock(mc); | |
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; | |
116 | + struct stat st; | |
117 | + | |
118 | + master_source_readlock(ap->entry); | |
119 | + | |
120 | + map = ap->entry->maps; | |
121 | + while (map) { | |
122 | + mc = map->mc; | |
123 | + cache_writelock(mc); | |
124 | + me = cache_lookup_distinct(mc, next->path); | |
125 | + if (me) | |
126 | + break; | |
127 | + cache_unlock(mc); | |
128 | + map = map->next; | |
129 | + } | |
130 | ||
131 | + if (!mc || !me) { | |
132 | + master_source_unlock(ap->entry); | |
133 | + pthread_setcancelstate(cur_state, NULL); | |
134 | + continue; | |
135 | + } | |
136 | + | |
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)) { | |
142 | + error(ap->logopt, | |
143 | + "error: possible mtab mismatch %s", | |
144 | + me->key); | |
145 | + cache_unlock(mc); | |
146 | + master_source_unlock(ap->entry); | |
147 | + pthread_setcancelstate(cur_state, NULL); | |
148 | + continue; | |
149 | + } | |
150 | + close(me->ioctlfd); | |
151 | + me->ioctlfd = -1; | |
152 | + } | |
153 | + | |
154 | + cache_unlock(mc); | |
155 | + master_source_unlock(ap->entry); | |
156 | + } | |
157 | + | |
158 | + pthread_setcancelstate(cur_state, NULL); | |
159 | continue; | |
160 | } | |
161 |